@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.
Files changed (470) hide show
  1. package/dist/base/Badge.js +3 -3
  2. package/dist/base/Badge.js.map +1 -1
  3. package/dist/base/Can.d.ts +12 -0
  4. package/dist/base/Can.js +20 -0
  5. package/dist/base/Can.js.map +1 -0
  6. package/dist/base/ClientOnly.d.ts +10 -0
  7. package/dist/base/ClientOnly.js +18 -0
  8. package/dist/base/ClientOnly.js.map +1 -0
  9. package/dist/base/CloseButton.js +3 -3
  10. package/dist/base/CloseButton.js.map +1 -1
  11. package/dist/base/CodeBlock.js +5 -5
  12. package/dist/base/CodeBlock.js.map +1 -1
  13. package/dist/base/CopyButton.js +3 -3
  14. package/dist/base/CopyButton.js.map +1 -1
  15. package/dist/base/Icon.js +3 -3
  16. package/dist/base/Icon.js.map +1 -1
  17. package/dist/base/Indicator.js +3 -3
  18. package/dist/base/Indicator.js.map +1 -1
  19. package/dist/base/StatusDot.js +3 -3
  20. package/dist/base/StatusDot.js.map +1 -1
  21. package/dist/base/Tag.js +5 -5
  22. package/dist/base/Tag.js.map +1 -1
  23. package/dist/base/button-core.js +4 -4
  24. package/dist/base/button-core.js.map +1 -1
  25. package/dist/charts/AreaChart.js +3 -3
  26. package/dist/charts/AreaChart.js.map +1 -1
  27. package/dist/charts/BarChart.js +3 -3
  28. package/dist/charts/BarChart.js.map +1 -1
  29. package/dist/charts/ChordChart.js +3 -3
  30. package/dist/charts/ChordChart.js.map +1 -1
  31. package/dist/charts/ComboChart.js +3 -3
  32. package/dist/charts/ComboChart.js.map +1 -1
  33. package/dist/charts/DonutChart.js +3 -3
  34. package/dist/charts/DonutChart.js.map +1 -1
  35. package/dist/charts/FunnelChart.js +5 -5
  36. package/dist/charts/FunnelChart.js.map +1 -1
  37. package/dist/charts/GraphChart.js +3 -3
  38. package/dist/charts/GraphChart.js.map +1 -1
  39. package/dist/charts/LineChart.js +3 -3
  40. package/dist/charts/LineChart.js.map +1 -1
  41. package/dist/charts/MapChart.js +7 -7
  42. package/dist/charts/MapChart.js.map +1 -1
  43. package/dist/charts/RadarChart.js +16 -15
  44. package/dist/charts/RadarChart.js.map +1 -1
  45. package/dist/charts/SankeyChart.js +3 -3
  46. package/dist/charts/SankeyChart.js.map +1 -1
  47. package/dist/charts/ScatterChart.js +3 -3
  48. package/dist/charts/ScatterChart.js.map +1 -1
  49. package/dist/charts/TimelineChart.js +6 -5
  50. package/dist/charts/TimelineChart.js.map +1 -1
  51. package/dist/charts/TreemapChart.js +3 -3
  52. package/dist/charts/TreemapChart.js.map +1 -1
  53. package/dist/charts/WaterfallChart.js +3 -3
  54. package/dist/charts/WaterfallChart.js.map +1 -1
  55. package/dist/charts/XYChart.js +9 -7
  56. package/dist/charts/XYChart.js.map +1 -1
  57. package/dist/charts/frame.js +10 -8
  58. package/dist/charts/frame.js.map +1 -1
  59. package/dist/charts/single.js +4 -3
  60. package/dist/charts/single.js.map +1 -1
  61. package/dist/code-editor/CodeEditor.d.ts +18 -0
  62. package/dist/code-editor/CodeEditor.js +57 -0
  63. package/dist/code-editor/CodeEditor.js.map +1 -0
  64. package/dist/code-editor/editor.d.ts +52 -0
  65. package/dist/code-editor/editor.js +225 -0
  66. package/dist/code-editor/editor.js.map +1 -0
  67. package/dist/code-editor/index.d.ts +9 -0
  68. package/dist/code-editor/index.js +3 -0
  69. package/dist/config/Provider.d.ts +3 -1
  70. package/dist/config/Provider.js +9 -4
  71. package/dist/config/Provider.js.map +1 -1
  72. package/dist/config/context.d.ts +18 -0
  73. package/dist/config/context.js +16 -1
  74. package/dist/config/context.js.map +1 -1
  75. package/dist/config/createUi.d.ts +20 -3
  76. package/dist/config/createUi.js +80 -49
  77. package/dist/config/createUi.js.map +1 -1
  78. package/dist/config/lang/en-US.js +21 -3
  79. package/dist/config/lang/en-US.js.map +1 -1
  80. package/dist/config/lang/format.d.ts +2 -1
  81. package/dist/config/lang/format.js +9 -2
  82. package/dist/config/lang/format.js.map +1 -1
  83. package/dist/config/lang/lang.d.ts +19 -6
  84. package/dist/config/lang/lang.js +11 -2
  85. package/dist/config/lang/lang.js.map +1 -1
  86. package/dist/config/lang/zh-CN.js +21 -3
  87. package/dist/config/lang/zh-CN.js.map +1 -1
  88. package/dist/config/layout/preference.d.ts +43 -0
  89. package/dist/config/layout/preference.js +108 -0
  90. package/dist/config/layout/preference.js.map +1 -0
  91. package/dist/date/Calendar.js +3 -3
  92. package/dist/date/Calendar.js.map +1 -1
  93. package/dist/date/CalendarBoard.js +9 -9
  94. package/dist/date/CalendarBoard.js.map +1 -1
  95. package/dist/date/CalendarView.js +7 -7
  96. package/dist/date/CalendarView.js.map +1 -1
  97. package/dist/date/DateField.js +3 -3
  98. package/dist/date/DateField.js.map +1 -1
  99. package/dist/date/DatePicker.js +5 -5
  100. package/dist/date/DatePicker.js.map +1 -1
  101. package/dist/date/DateRangePicker.js +5 -5
  102. package/dist/date/DateRangePicker.js.map +1 -1
  103. package/dist/date/DateSegmentGroup.js +5 -5
  104. package/dist/date/DateSegmentGroup.js.map +1 -1
  105. package/dist/date/QuarterCalendar.js +6 -6
  106. package/dist/date/QuarterCalendar.js.map +1 -1
  107. package/dist/date/RangeCalendar.js +3 -3
  108. package/dist/date/RangeCalendar.js.map +1 -1
  109. package/dist/date/SegmentedField.js +3 -3
  110. package/dist/date/SegmentedField.js.map +1 -1
  111. package/dist/date/TimeField.js +3 -3
  112. package/dist/date/TimeField.js.map +1 -1
  113. package/dist/date/TimePicker.js +4 -4
  114. package/dist/date/TimePicker.js.map +1 -1
  115. package/dist/date/date-segments.js +1 -1
  116. package/dist/date/date-segments.js.map +1 -1
  117. package/dist/date/picker-popover.js +3 -2
  118. package/dist/date/picker-popover.js.map +1 -1
  119. package/dist/diagram/Diagram.js +12 -12
  120. package/dist/diagram/Diagram.js.map +1 -1
  121. package/dist/diagram/DiagramLanes.js +3 -3
  122. package/dist/diagram/DiagramLanes.js.map +1 -1
  123. package/dist/diagram/DiagramMinimap.js +4 -4
  124. package/dist/diagram/DiagramMinimap.js.map +1 -1
  125. package/dist/diagram/index.d.ts +2 -1
  126. package/dist/diagram/index.js +2 -1
  127. package/dist/diagram/layout.d.ts +57 -0
  128. package/dist/diagram/layout.js +50 -0
  129. package/dist/diagram/layout.js.map +1 -0
  130. package/dist/display/Accordion.js +6 -6
  131. package/dist/display/Accordion.js.map +1 -1
  132. package/dist/display/AnimatedNumber.js +4 -4
  133. package/dist/display/AnimatedNumber.js.map +1 -1
  134. package/dist/display/Avatar.js +4 -4
  135. package/dist/display/Avatar.js.map +1 -1
  136. package/dist/display/Checklist.js +7 -7
  137. package/dist/display/Checklist.js.map +1 -1
  138. package/dist/display/Collapse.js +8 -5
  139. package/dist/display/Collapse.js.map +1 -1
  140. package/dist/display/Collapsible.js +3 -3
  141. package/dist/display/Collapsible.js.map +1 -1
  142. package/dist/display/Descriptions.js +5 -5
  143. package/dist/display/Descriptions.js.map +1 -1
  144. package/dist/display/Ellipsis.js +3 -3
  145. package/dist/display/Ellipsis.js.map +1 -1
  146. package/dist/display/FieldCompare.js +4 -4
  147. package/dist/display/FieldCompare.js.map +1 -1
  148. package/dist/display/Gauge.js +11 -11
  149. package/dist/display/Gauge.js.map +1 -1
  150. package/dist/display/Image.js +4 -4
  151. package/dist/display/Image.js.map +1 -1
  152. package/dist/display/Marquee.js +3 -3
  153. package/dist/display/Marquee.js.map +1 -1
  154. package/dist/display/ProportionBar.js +4 -4
  155. package/dist/display/ProportionBar.js.map +1 -1
  156. package/dist/display/Sortable.js +4 -4
  157. package/dist/display/Sortable.js.map +1 -1
  158. package/dist/display/Sparkline.js +6 -6
  159. package/dist/display/Sparkline.js.map +1 -1
  160. package/dist/display/Stat.js +3 -3
  161. package/dist/display/Stat.js.map +1 -1
  162. package/dist/display/Timeline.js +7 -7
  163. package/dist/display/Timeline.js.map +1 -1
  164. package/dist/display/Tree.js +10 -10
  165. package/dist/display/Tree.js.map +1 -1
  166. package/dist/display/VirtualList.js +7 -7
  167. package/dist/display/VirtualList.js.map +1 -1
  168. package/dist/display/Watermark.js +3 -3
  169. package/dist/display/Watermark.js.map +1 -1
  170. package/dist/docs-kit/CodeGroup.js +5 -5
  171. package/dist/docs-kit/CodeGroup.js.map +1 -1
  172. package/dist/docs-kit/CodePreview.js +6 -6
  173. package/dist/docs-kit/CodePreview.js.map +1 -1
  174. package/dist/docs-kit/PropsTable.js +4 -4
  175. package/dist/docs-kit/PropsTable.js.map +1 -1
  176. package/dist/feedback/Alert.js +5 -5
  177. package/dist/feedback/Alert.js.map +1 -1
  178. package/dist/feedback/Banner.js +5 -5
  179. package/dist/feedback/Banner.js.map +1 -1
  180. package/dist/feedback/Empty.js +4 -4
  181. package/dist/feedback/Empty.js.map +1 -1
  182. package/dist/feedback/LoadingBar.js +20 -13
  183. package/dist/feedback/LoadingBar.js.map +1 -1
  184. package/dist/feedback/LoadingOverlay.js +3 -3
  185. package/dist/feedback/LoadingOverlay.js.map +1 -1
  186. package/dist/feedback/Progress.js +14 -14
  187. package/dist/feedback/Progress.js.map +1 -1
  188. package/dist/feedback/Result.js +4 -4
  189. package/dist/feedback/Result.js.map +1 -1
  190. package/dist/feedback/SkeletonText.js +3 -3
  191. package/dist/feedback/SkeletonText.js.map +1 -1
  192. package/dist/feedback/Toast.js +6 -6
  193. package/dist/feedback/Toast.js.map +1 -1
  194. package/dist/form/Field.d.ts +7 -0
  195. package/dist/form/Field.js +20 -9
  196. package/dist/form/Field.js.map +1 -1
  197. package/dist/form/Form.js +3 -3
  198. package/dist/form/Form.js.map +1 -1
  199. package/dist/form/FormErrorSummary.js +3 -3
  200. package/dist/form/FormErrorSummary.js.map +1 -1
  201. package/dist/form/FormSection.js +6 -6
  202. package/dist/form/FormSection.js.map +1 -1
  203. package/dist/form/useForm.d.ts +4 -1
  204. package/dist/form/useForm.js +35 -13
  205. package/dist/form/useForm.js.map +1 -1
  206. package/dist/index.d.ts +18 -10
  207. package/dist/index.js +17 -9
  208. package/dist/input/Autocomplete.js +3 -3
  209. package/dist/input/Autocomplete.js.map +1 -1
  210. package/dist/input/Cascader.js +7 -7
  211. package/dist/input/Cascader.js.map +1 -1
  212. package/dist/input/CharacterCount.js +3 -3
  213. package/dist/input/CharacterCount.js.map +1 -1
  214. package/dist/input/Checkbox.js +5 -5
  215. package/dist/input/Checkbox.js.map +1 -1
  216. package/dist/input/ColorField.js +4 -4
  217. package/dist/input/ColorField.js.map +1 -1
  218. package/dist/input/Combobox.js +5 -5
  219. package/dist/input/Combobox.js.map +1 -1
  220. package/dist/input/ConditionBuilder.js +15 -14
  221. package/dist/input/ConditionBuilder.js.map +1 -1
  222. package/dist/input/FileDrop.js +3 -3
  223. package/dist/input/FileDrop.js.map +1 -1
  224. package/dist/input/Listbox.js +9 -9
  225. package/dist/input/Listbox.js.map +1 -1
  226. package/dist/input/Mentions.js +4 -4
  227. package/dist/input/Mentions.js.map +1 -1
  228. package/dist/input/NumberField.js +3 -3
  229. package/dist/input/NumberField.js.map +1 -1
  230. package/dist/input/NumberRangeField.js +5 -5
  231. package/dist/input/NumberRangeField.js.map +1 -1
  232. package/dist/input/OtpField.js +5 -5
  233. package/dist/input/OtpField.js.map +1 -1
  234. package/dist/input/PeoplePicker.js +6 -6
  235. package/dist/input/PeoplePicker.js.map +1 -1
  236. package/dist/input/PeoplePickerPanel.js +15 -15
  237. package/dist/input/PeoplePickerPanel.js.map +1 -1
  238. package/dist/input/Radio.js +4 -4
  239. package/dist/input/Radio.js.map +1 -1
  240. package/dist/input/Rating.js +5 -5
  241. package/dist/input/Rating.js.map +1 -1
  242. package/dist/input/Select.js +5 -5
  243. package/dist/input/Select.js.map +1 -1
  244. package/dist/input/SelectedTags.js +4 -4
  245. package/dist/input/SelectedTags.js.map +1 -1
  246. package/dist/input/Slider.js +6 -6
  247. package/dist/input/Slider.js.map +1 -1
  248. package/dist/input/Switch.js +3 -3
  249. package/dist/input/Switch.js.map +1 -1
  250. package/dist/input/TagsInput.js +5 -5
  251. package/dist/input/TagsInput.js.map +1 -1
  252. package/dist/input/TextField.js +5 -5
  253. package/dist/input/TextField.js.map +1 -1
  254. package/dist/input/Textarea.js +4 -4
  255. package/dist/input/Textarea.js.map +1 -1
  256. package/dist/input/ToggleGroup.js +4 -4
  257. package/dist/input/ToggleGroup.js.map +1 -1
  258. package/dist/input/Transfer.js +8 -8
  259. package/dist/input/Transfer.js.map +1 -1
  260. package/dist/input/TreeSelect.js +7 -7
  261. package/dist/input/TreeSelect.js.map +1 -1
  262. package/dist/input/Upload.js +10 -9
  263. package/dist/input/Upload.js.map +1 -1
  264. package/dist/input/condition.d.ts +1 -1
  265. package/dist/input/condition.js +32 -14
  266. package/dist/input/condition.js.map +1 -1
  267. package/dist/input/people.d.ts +15 -14
  268. package/dist/input/people.js +5 -5
  269. package/dist/input/people.js.map +1 -1
  270. package/dist/input/remote-items.d.ts +4 -2
  271. package/dist/input/remote-items.js +7 -2
  272. package/dist/input/remote-items.js.map +1 -1
  273. package/dist/layout/Affix.js +4 -4
  274. package/dist/layout/Affix.js.map +1 -1
  275. package/dist/layout/ResizeHandle.d.ts +6 -2
  276. package/dist/layout/ResizeHandle.js +32 -9
  277. package/dist/layout/ResizeHandle.js.map +1 -1
  278. package/dist/layout/ScrollArea.js +3 -3
  279. package/dist/layout/ScrollArea.js.map +1 -1
  280. package/dist/layout/Separator.js +3 -3
  281. package/dist/layout/Separator.js.map +1 -1
  282. package/dist/layout/Splitter.js +3 -3
  283. package/dist/layout/Splitter.js.map +1 -1
  284. package/dist/layout/ViewportFill.d.ts +2 -2
  285. package/dist/layout/ViewportFill.js +4 -4
  286. package/dist/layout/ViewportFill.js.map +1 -1
  287. package/dist/navigation/Breadcrumbs.js +4 -4
  288. package/dist/navigation/Breadcrumbs.js.map +1 -1
  289. package/dist/navigation/NavBar.js +6 -6
  290. package/dist/navigation/NavBar.js.map +1 -1
  291. package/dist/navigation/NavList.d.ts +1 -0
  292. package/dist/navigation/NavList.js +20 -12
  293. package/dist/navigation/NavList.js.map +1 -1
  294. package/dist/navigation/NavMenu.d.ts +27 -0
  295. package/dist/navigation/NavMenu.js +54 -0
  296. package/dist/navigation/NavMenu.js.map +1 -0
  297. package/dist/navigation/PageJump.js +3 -3
  298. package/dist/navigation/PageJump.js.map +1 -1
  299. package/dist/navigation/PageSizeSelect.js +4 -4
  300. package/dist/navigation/PageSizeSelect.js.map +1 -1
  301. package/dist/navigation/Pagination.js +6 -6
  302. package/dist/navigation/Pagination.js.map +1 -1
  303. package/dist/navigation/PaginationBar.js +5 -5
  304. package/dist/navigation/PaginationBar.js.map +1 -1
  305. package/dist/navigation/Steps.js +4 -4
  306. package/dist/navigation/Steps.js.map +1 -1
  307. package/dist/navigation/TableOfContents.js +5 -5
  308. package/dist/navigation/TableOfContents.js.map +1 -1
  309. package/dist/navigation/Tabs.js +7 -7
  310. package/dist/navigation/Tabs.js.map +1 -1
  311. package/dist/navigation/Toolbar.js +3 -3
  312. package/dist/navigation/Toolbar.js.map +1 -1
  313. package/dist/overlay/AlertDialog.js +4 -4
  314. package/dist/overlay/AlertDialog.js.map +1 -1
  315. package/dist/overlay/CommandPalette.js +4 -4
  316. package/dist/overlay/CommandPalette.js.map +1 -1
  317. package/dist/overlay/ContextMenu.js +3 -3
  318. package/dist/overlay/ContextMenu.js.map +1 -1
  319. package/dist/overlay/Dialog.js +4 -4
  320. package/dist/overlay/Dialog.js.map +1 -1
  321. package/dist/overlay/Drawer.js +5 -5
  322. package/dist/overlay/Drawer.js.map +1 -1
  323. package/dist/overlay/HoverCard.js +5 -3
  324. package/dist/overlay/HoverCard.js.map +1 -1
  325. package/dist/overlay/Lightbox.js +5 -5
  326. package/dist/overlay/Lightbox.js.map +1 -1
  327. package/dist/overlay/Menu.js +7 -7
  328. package/dist/overlay/Menu.js.map +1 -1
  329. package/dist/overlay/ModalCore.js +9 -9
  330. package/dist/overlay/ModalCore.js.map +1 -1
  331. package/dist/overlay/Popconfirm.js +6 -6
  332. package/dist/overlay/Popconfirm.js.map +1 -1
  333. package/dist/overlay/Popover.js +5 -3
  334. package/dist/overlay/Popover.js.map +1 -1
  335. package/dist/overlay/Tooltip.js +5 -3
  336. package/dist/overlay/Tooltip.js.map +1 -1
  337. package/dist/overlay/Tour.js +8 -8
  338. package/dist/overlay/Tour.js.map +1 -1
  339. package/dist/overlay/detached.d.ts +2 -0
  340. package/dist/overlay/detached.js +73 -42
  341. package/dist/overlay/detached.js.map +1 -1
  342. package/dist/patterns/ActionBar.js +3 -3
  343. package/dist/patterns/ActionBar.js.map +1 -1
  344. package/dist/patterns/AppShell.d.ts +28 -1
  345. package/dist/patterns/AppShell.js +158 -52
  346. package/dist/patterns/AppShell.js.map +1 -1
  347. package/dist/patterns/AuthLayout.d.ts +28 -0
  348. package/dist/patterns/AuthLayout.js +77 -0
  349. package/dist/patterns/AuthLayout.js.map +1 -0
  350. package/dist/patterns/CommentThread.js +9 -9
  351. package/dist/patterns/CommentThread.js.map +1 -1
  352. package/dist/patterns/DataImport.js +4 -4
  353. package/dist/patterns/DataImport.js.map +1 -1
  354. package/dist/patterns/DeadlineBadge.js +3 -3
  355. package/dist/patterns/DeadlineBadge.js.map +1 -1
  356. package/dist/patterns/FilterBar.d.ts +11 -1
  357. package/dist/patterns/FilterBar.js +39 -10
  358. package/dist/patterns/FilterBar.js.map +1 -1
  359. package/dist/patterns/FormDialog.d.ts +18 -0
  360. package/dist/patterns/FormDialog.js +46 -0
  361. package/dist/patterns/FormDialog.js.map +1 -0
  362. package/dist/patterns/KanbanBoard.js +8 -8
  363. package/dist/patterns/KanbanBoard.js.map +1 -1
  364. package/dist/patterns/LayoutSwitcher.d.ts +12 -0
  365. package/dist/patterns/LayoutSwitcher.js +79 -0
  366. package/dist/patterns/LayoutSwitcher.js.map +1 -0
  367. package/dist/patterns/NotificationCenter.js +8 -8
  368. package/dist/patterns/NotificationCenter.js.map +1 -1
  369. package/dist/patterns/PageTabs.d.ts +12 -7
  370. package/dist/patterns/PageTabs.js +41 -29
  371. package/dist/patterns/PageTabs.js.map +1 -1
  372. package/dist/patterns/QueryTable.d.ts +10 -1
  373. package/dist/patterns/QueryTable.js +128 -68
  374. package/dist/patterns/QueryTable.js.map +1 -1
  375. package/dist/patterns/SlideCaptcha.d.ts +80 -0
  376. package/dist/patterns/SlideCaptcha.js +354 -0
  377. package/dist/patterns/SlideCaptcha.js.map +1 -0
  378. package/dist/patterns/StepsForm.js +7 -7
  379. package/dist/patterns/StepsForm.js.map +1 -1
  380. package/dist/patterns/ThemeSwitcher.js +3 -3
  381. package/dist/patterns/ThemeSwitcher.js.map +1 -1
  382. package/dist/patterns/index.d.ts +7 -3
  383. package/dist/patterns/index.js +5 -1
  384. package/dist/patterns/messages.d.ts +39 -1
  385. package/dist/patterns/messages.js +40 -2
  386. package/dist/patterns/messages.js.map +1 -1
  387. package/dist/table/ColumnHeaderActions.js +3 -3
  388. package/dist/table/ColumnHeaderActions.js.map +1 -1
  389. package/dist/table/ColumnResizer.js +3 -3
  390. package/dist/table/ColumnResizer.js.map +1 -1
  391. package/dist/table/ColumnSettings.js +5 -5
  392. package/dist/table/ColumnSettings.js.map +1 -1
  393. package/dist/table/ColumnTable.js +8 -8
  394. package/dist/table/ColumnTable.js.map +1 -1
  395. package/dist/table/DataTable.js +8 -8
  396. package/dist/table/DataTable.js.map +1 -1
  397. package/dist/table/DataTableView.js +21 -21
  398. package/dist/table/DataTableView.js.map +1 -1
  399. package/dist/table/PivotTable.js +3 -3
  400. package/dist/table/PivotTable.js.map +1 -1
  401. package/dist/table/SelectionBar.js +4 -4
  402. package/dist/table/SelectionBar.js.map +1 -1
  403. package/dist/table/TreeDataTable.js +5 -5
  404. package/dist/table/TreeDataTable.js.map +1 -1
  405. package/dist/theme-customize/ThemeCustomizer.js +7 -6
  406. package/dist/theme-customize/ThemeCustomizer.js.map +1 -1
  407. package/dist/theme-customize/ThemeThumbnail.js +3 -3
  408. package/dist/theme-customize/ThemeThumbnail.js.map +1 -1
  409. package/dist/three/background/AuroraBackground.js +3 -3
  410. package/dist/three/background/AuroraBackground.js.map +1 -1
  411. package/dist/three/background/MeshGradient.js +3 -3
  412. package/dist/three/background/MeshGradient.js.map +1 -1
  413. package/dist/three/background/ShaderBackground.js +3 -3
  414. package/dist/three/background/ShaderBackground.js.map +1 -1
  415. package/dist/three/core/EffectSurface.js +3 -3
  416. package/dist/three/core/EffectSurface.js.map +1 -1
  417. package/dist/three/core/ThreeCanvas.js +4 -4
  418. package/dist/three/core/ThreeCanvas.js.map +1 -1
  419. package/dist/three/effects/Confetti.js +3 -3
  420. package/dist/three/effects/Confetti.js.map +1 -1
  421. package/dist/three/effects/ParticleField.js +3 -3
  422. package/dist/three/effects/ParticleField.js.map +1 -1
  423. package/dist/three/effects/WaveGrid.js +3 -3
  424. package/dist/three/effects/WaveGrid.js.map +1 -1
  425. package/dist/three/globe/Globe.js +3 -3
  426. package/dist/three/globe/Globe.js.map +1 -1
  427. package/dist/three/model/ModelViewer.js +3 -3
  428. package/dist/three/model/ModelViewer.js.map +1 -1
  429. package/dist/utils/data/clone.d.ts +8 -0
  430. package/dist/utils/data/clone.js +21 -0
  431. package/dist/utils/data/clone.js.map +1 -0
  432. package/dist/utils/data/date.d.ts +10 -0
  433. package/dist/utils/data/date.js +13 -1
  434. package/dist/utils/data/date.js.map +1 -1
  435. package/dist/utils/data/number.d.ts +5 -0
  436. package/dist/utils/data/number.js +8 -1
  437. package/dist/utils/data/number.js.map +1 -1
  438. package/dist/utils/data/numeric.d.ts +7 -0
  439. package/dist/utils/data/numeric.js +46 -1
  440. package/dist/utils/data/numeric.js.map +1 -1
  441. package/dist/utils/dom/download.d.ts +8 -1
  442. package/dist/utils/dom/download.js +19 -2
  443. package/dist/utils/dom/download.js.map +1 -1
  444. package/dist/utils/dom/element.d.ts +3 -1
  445. package/dist/utils/dom/element.js +8 -4
  446. package/dist/utils/dom/element.js.map +1 -1
  447. package/dist/utils/dom/fullscreen.d.ts +1 -1
  448. package/dist/utils/dom/fullscreen.js +12 -8
  449. package/dist/utils/dom/fullscreen.js.map +1 -1
  450. package/dist/utils/dom/mounted.d.ts +7 -0
  451. package/dist/utils/dom/mounted.js +16 -0
  452. package/dist/utils/dom/mounted.js.map +1 -0
  453. package/dist/utils/dom/overflow.js +2 -1
  454. package/dist/utils/dom/overflow.js.map +1 -1
  455. package/dist/utils/dom/pan-zoom.js +2 -1
  456. package/dist/utils/dom/pan-zoom.js.map +1 -1
  457. package/dist/utils/props.js +3 -13
  458. package/dist/utils/props.js.map +1 -1
  459. package/dist/utils/request/error-message.d.ts +17 -0
  460. package/dist/utils/request/error-message.js +50 -0
  461. package/dist/utils/request/error-message.js.map +1 -0
  462. package/dist/utils/request/http.d.ts +80 -4
  463. package/dist/utils/request/http.js +121 -24
  464. package/dist/utils/request/http.js.map +1 -1
  465. package/dist/utils/request/use-autosave.d.ts +35 -0
  466. package/dist/utils/request/use-autosave.js +69 -0
  467. package/dist/utils/request/use-autosave.js.map +1 -0
  468. package/dist/utils/request/use-request.js +4 -2
  469. package/dist/utils/request/use-request.js.map +1 -1
  470. package/package.json +57 -4
@@ -1 +1 @@
1
- {"version":3,"file":"Radio.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../src/input/Radio.tsx"],"sourcesContent":["/**\n * 单选组(role=\"radiogroup\")与单选项(原生 input type=\"radio\")。结构与样式见 choice-styles.ts。\n *\n * <Field label=\"配送方式\">\n * <RadioGroup _value={shipping}>\n * <Radio value=\"express\">快递</Radio>\n * <Radio value=\"pickup\">自提</Radio>\n * </RadioGroup>\n * </Field>\n *\n * 同一组的原生 radio 共用一个 name:Tab 只停在选中项(没有选中时停在第一项),方向键在组内移动并选中,\n * 这些都是浏览器的原生行为,不需要漫游焦点。组以 Field 的标签为名称(aria-labelledby),关联说明与错误。\n *\n * 部件(Radio):Root(label)、Control(叠放层)、Indicator(圆点)、Label(文字);未声明的属性落到 input 上。\n */\nimport { createContext, _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { useId, type VNodeChild } from 'vue';\nimport { useFieldControl } from '../form/Field';\nimport { toListboxOption, type ListboxOption, type OptionMapping } from './list-state';\nimport { hasContent, defaultLabelledBy, mergeAttrs, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport type { StatusTone } from '../utils/style/tone-styles';\nimport type { TextSize } from '../utils/style/typography';\nimport { useRecipe } from '../config/styles';\nimport {\n choiceInputStyles,\n choiceParts,\n choiceRecipe,\n useChoiceAppearance,\n type ChoiceOrientations,\n readonlyChoiceHandlers,\n syncChecked,\n} from './choice-styles';\nimport { t } from '../config/theme/tokens';\n\n/** RadioGroup 交给组内 Radio 的状态 */\nexport interface RadioGroupState {\n /** 选中的值 */\n readonly value: string | null;\n /** 原生单选框的 name:同组共用,方向键在组内移动 */\n readonly name: string;\n /** 整组不可用 */\n readonly disabled: boolean;\n /** 整组只读 */\n readonly readonly: boolean;\n /** 必填 */\n readonly required: boolean;\n /** 整组校验未通过 */\n readonly invalid: boolean;\n /** 字号档位;不写时继承 */\n readonly size: TextSize | undefined;\n /** 选中时的色调 */\n readonly tone: StatusTone;\n /** 选中一个值 */\n select(value: string): void;\n}\n\n/** RadioGroup 的上下文:自定义的单选项可以 inject 它接入组 */\nexport const RadioGroupContext = createContext<RadioGroupState>('RadioGroup');\n\n/** 未声明的属性落到 div(role=\"radiogroup\")上 */\nexport interface RadioGroupBaseProps<T> extends PartProps<'div', 'role'> {\n /** 选中项的值:父级写 _value={x};没有选中时是 null */\n _value?: string | null;\n /** 表单提交时的 name;不写时自动生成(同组的 radio 要共用一个 name 才互斥) */\n name?: string;\n /** 整组不可用 */\n disabled?: boolean;\n /** 整组只读:能聚焦、读屏念“只读”,选中项不能改(查看详情、审批时);外观照常 */\n readonly?: boolean;\n /** 必填 */\n required?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 字号档位;不写时继承上下文字号 */\n size?: TextSize;\n /** 选中时的色调(与 Button、Badge 等同一套),默认 accent;可以用 defaults.Choice 统一改 */\n tone?: StatusTone;\n /** 排列方向,默认 vertical */\n orientation?: keyof ChoiceOrientations;\n /** 各项:ListboxOption(值、文字、说明、不可用)、字符串,或任意数据加 toOption;写了 children 时不用 */\n items?: readonly T[];\n /** Radio;不写时按 items 生成 */\n children?: VNodeChild;\n}\n\n/** RadioGroup 的属性:items 是 ListboxOption、字符串时不用 toOption */\nexport type RadioGroupProps<T = ListboxOption> = RadioGroupBaseProps<T> & OptionMapping<T>;\n\n/** 单选组:value 是选中项的值 */\nexport const RadioGroup = _component(\n <T = ListboxOption,>({\n _value: value = _bindable<string | null>(null),\n name,\n disabled,\n readonly,\n required,\n invalid,\n size,\n tone,\n orientation = 'vertical',\n id,\n items,\n toOption,\n children,\n ...rest\n }: RadioGroupProps<T>) => {\n const generatedName = useId();\n const control = useFieldControl(() => ({ id, disabled, readonly, required, invalid }));\n const appearance = useChoiceAppearance(() => ({ size, tone }));\n RadioGroupContext.provide({\n get value() {\n return value;\n },\n get name() {\n return name ?? generatedName;\n },\n get disabled() {\n return control().disabled;\n },\n get readonly() {\n return control().readonly;\n },\n get required() {\n return control().required;\n },\n get invalid() {\n return control().invalid;\n },\n get size() {\n return appearance().size;\n },\n get tone() {\n return appearance().tone;\n },\n select: (next) => (value = next),\n });\n\n return () => {\n const state = control();\n return (\n <div\n {...mergeAttrs<'div'>(appearance().recipe({ orientation }).group, rest, {\n id: state.id,\n role: 'radiogroup',\n 'aria-labelledby': defaultLabelledBy(rest, state.labelledBy),\n 'aria-describedby': state.describedBy,\n 'aria-invalid': state.invalid || undefined,\n 'aria-required': state.required || undefined,\n 'aria-readonly': state.readonly || undefined,\n })}\n data-orientation={orientation}\n data-disabled={state.disabled || undefined}\n data-readonly={state.readonly || undefined}\n >\n {children ??\n items?.map((item) => {\n const option = toListboxOption(item, toOption);\n return (\n <Radio\n key={option.value}\n value={option.value}\n disabled={option.disabled || undefined}\n description={option.description}\n >\n {option.label}\n </Radio>\n );\n })}\n </div>\n );\n };\n },\n);\n\n/** 选中、名称与可用性由组管理 */\nexport type RadioManaged = 'type' | 'name' | 'checked' | 'required' | 'size' | 'value';\n\n/** 未声明的属性落到 input 上;外层 label 用 propsRoot */\nexport interface RadioProps extends PartProps<'input', RadioManaged> {\n /** 这一项的值 */\n value: string;\n /** 这一项不可用 */\n disabled?: boolean;\n /** 外层 label 的部件属性 */\n propsRoot?: PartProps<'label'>;\n /** 叠放层的部件属性 */\n propsControl?: PartProps<'span'>;\n /** 圆点的部件属性 */\n propsIndicator?: PartProps<'span'>;\n /** 文字的部件属性 */\n propsLabel?: PartProps<'span'>;\n /** 文字下方的说明(aria-describedby) */\n description?: VNodeChild;\n /** 说明的部件属性 */\n propsDescription?: PartProps<'span'>;\n /** 文字 */\n children?: VNodeChild;\n}\n\n/** RadioGroup、Radio 的样式:circle、dot、dotChecked */\nexport const radioStyles = css.create({\n circle: { width: '1.125em', height: '1.125em', borderRadius: '_full' },\n dot: {\n width: '0.45em',\n height: '0.45em',\n borderRadius: '_full',\n backgroundColor: 'var(--tone-on-fill)',\n transform: 'scale(0)',\n transition: `transform ${t.durations.sm} ${t.easings.standard}`,\n },\n dotChecked: { transform: 'none' },\n});\n\n/** 单选项:放在 RadioGroup 里 */\nexport const Radio = _component(\n ({\n value,\n disabled,\n propsRoot,\n propsControl,\n propsIndicator,\n propsLabel,\n description,\n propsDescription,\n children,\n ...rest\n }: RadioProps) => {\n const group = RadioGroupContext.inject();\n const descriptionId = `${useId()}-description`;\n const recipe = useRecipe(choiceRecipe);\n return () => {\n const checked = group.value === value;\n const off = disabled ?? group.disabled;\n const s = choiceParts(\n { size: group.size, tone: group.tone, recipe },\n { disabled: off, readonly: group.readonly },\n );\n return (\n <label\n {...mergeAttrs<'label'>(s.root, propsRoot)}\n data-state={checked ? 'checked' : 'unchecked'}\n data-disabled={off || undefined}\n data-readonly={group.readonly || undefined}\n >\n <span {...mergeAttrs<'span'>(s.control, propsControl)}>\n <input\n {...mergeAttrs<'input'>(\n {\n ...s.input,\n sx: [\n s.input.sx,\n focusRingStyles.tight,\n radioStyles.circle,\n checked && choiceInputStyles.checked,\n group.invalid && choiceInputStyles.invalid,\n ],\n },\n rest,\n {\n type: 'radio',\n name: group.name,\n value,\n checked,\n disabled: off,\n required: group.required,\n 'aria-describedby': hasContent(description) ? descriptionId : undefined,\n onChange: (event: Event) => {\n group.select(value);\n // 浏览器已经取消了同组原来选中的那个:整组一起对回父级的值\n const radios = (event.target as HTMLElement)\n .closest('[role=\"radiogroup\"]')\n ?.querySelectorAll<HTMLInputElement>('input[type=\"radio\"]');\n syncChecked([...(radios ?? [])], (input) => input.value === group.value);\n },\n ...(group.readonly && readonlyChoiceHandlers),\n },\n )}\n />\n <span\n {...mergeAttrs<'span'>(\n {\n ...s.indicator,\n sx: [s.indicator.sx, radioStyles.dot, checked && radioStyles.dotChecked],\n },\n propsIndicator,\n )}\n />\n </span>\n {(hasContent(children) || hasContent(description)) && (\n <span {...mergeAttrs<'span'>(s.label, propsLabel)}>\n {children}\n {hasContent(description) && (\n <span\n {...mergeAttrs<'span'>(s.description, propsDescription, {\n id: descriptionId,\n })}\n >\n {description}\n </span>\n )}\n </span>\n )}\n </label>\n );\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"Radio.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../src/input/Radio.tsx"],"sourcesContent":["/**\n * 单选组(role=\"radiogroup\")与单选项(原生 input type=\"radio\")。结构与样式见 choice-styles.ts。\n *\n * <Field label=\"配送方式\">\n * <RadioGroup _value={shipping}>\n * <Radio value=\"express\">快递</Radio>\n * <Radio value=\"pickup\">自提</Radio>\n * </RadioGroup>\n * </Field>\n *\n * 同一组的原生 radio 共用一个 name:Tab 只停在选中项(没有选中时停在第一项),方向键在组内移动并选中,\n * 这些都是浏览器的原生行为,不需要漫游焦点。组以 Field 的标签为名称(aria-labelledby),关联说明与错误。\n *\n * 部件(Radio):Root(label)、Control(叠放层)、Indicator(圆点)、Label(文字);未声明的属性落到 input 上。\n */\nimport { createContext, _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { useId, type VNodeChild } from 'vue';\nimport { useFieldControl } from '../form/Field';\nimport { toListboxOption, type ListboxOption, type OptionMapping } from './list-state';\nimport { hasContent, defaultLabelledBy, mergeAttrs, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport type { StatusTone } from '../utils/style/tone-styles';\nimport type { TextSize } from '../utils/style/typography';\nimport { useRecipe } from '../config/styles';\nimport {\n choiceInputStyles,\n choiceParts,\n choiceRecipe,\n useChoiceAppearance,\n type ChoiceOrientations,\n readonlyChoiceHandlers,\n syncChecked,\n} from './choice-styles';\nimport { t } from '../config/theme/tokens';\n\n/** RadioGroup 交给组内 Radio 的状态 */\nexport interface RadioGroupState {\n /** 选中的值 */\n readonly value: string | null;\n /** 原生单选框的 name:同组共用,方向键在组内移动 */\n readonly name: string;\n /** 整组不可用 */\n readonly disabled: boolean;\n /** 整组只读 */\n readonly readonly: boolean;\n /** 必填 */\n readonly required: boolean;\n /** 整组校验未通过 */\n readonly invalid: boolean;\n /** 字号档位;不写时继承 */\n readonly size: TextSize | undefined;\n /** 选中时的色调 */\n readonly tone: StatusTone;\n /** 选中一个值 */\n select(value: string): void;\n}\n\n/** RadioGroup 的上下文:自定义的单选项可以 inject 它接入组 */\nexport const RadioGroupContext = createContext<RadioGroupState>('RadioGroup');\n\n/** 未声明的属性落到 div(role=\"radiogroup\")上 */\nexport interface RadioGroupBaseProps<T> extends PartProps<'div', 'role'> {\n /** 选中项的值:父级写 _value={x};没有选中时是 null */\n _value?: string | null;\n /** 表单提交时的 name;不写时自动生成(同组的 radio 要共用一个 name 才互斥) */\n name?: string;\n /** 整组不可用 */\n disabled?: boolean;\n /** 整组只读:能聚焦、读屏念“只读”,选中项不能改(查看详情、审批时);外观照常 */\n readonly?: boolean;\n /** 必填 */\n required?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 字号档位;不写时继承上下文字号 */\n size?: TextSize;\n /** 选中时的色调(与 Button、Badge 等同一套),默认 accent;可以用 defaults.Choice 统一改 */\n tone?: StatusTone;\n /** 排列方向,默认 vertical */\n orientation?: keyof ChoiceOrientations;\n /** 各项:ListboxOption(值、文字、说明、不可用)、字符串,或任意数据加 toOption;写了 children 时不用 */\n items?: readonly T[];\n /** Radio;不写时按 items 生成 */\n children?: VNodeChild;\n}\n\n/** RadioGroup 的属性:items 是 ListboxOption、字符串时不用 toOption */\nexport type RadioGroupProps<T = ListboxOption> = RadioGroupBaseProps<T> & OptionMapping<T>;\n\n/** 单选组:value 是选中项的值 */\nexport const RadioGroup = _component(\n <T = ListboxOption,>({\n _value: value = _bindable<string | null>(null),\n name,\n disabled,\n readonly,\n required,\n invalid,\n size,\n tone,\n orientation = 'vertical',\n id,\n items,\n toOption,\n children,\n ...rest\n }: RadioGroupProps<T>) => {\n const generatedName = useId();\n const control = useFieldControl(() => ({ id, disabled, readonly, required, invalid }));\n const appearance = useChoiceAppearance(() => ({ size, tone }));\n RadioGroupContext.provide({\n get value() {\n return value;\n },\n get name() {\n return name ?? generatedName;\n },\n get disabled() {\n return control().disabled;\n },\n get readonly() {\n return control().readonly;\n },\n get required() {\n return control().required;\n },\n get invalid() {\n return control().invalid;\n },\n get size() {\n return appearance().size;\n },\n get tone() {\n return appearance().tone;\n },\n select: (next) => (value = next),\n });\n\n return () => {\n const state = control();\n return (\n <div\n {...mergeAttrs<'div'>(appearance().recipe({ orientation }).group, rest, {\n id: state.id,\n role: 'radiogroup',\n 'aria-labelledby': defaultLabelledBy(rest, state.labelledBy),\n 'aria-describedby': state.describedBy,\n 'aria-invalid': state.invalid || undefined,\n 'aria-required': state.required || undefined,\n 'aria-readonly': state.readonly || undefined,\n })}\n data-orientation={orientation}\n data-disabled={state.disabled || undefined}\n data-readonly={state.readonly || undefined}\n >\n {children ??\n items?.map((item) => {\n const option = toListboxOption(item, toOption);\n return (\n <Radio\n key={option.value}\n value={option.value}\n disabled={option.disabled || undefined}\n description={option.description}\n >\n {option.label}\n </Radio>\n );\n })}\n </div>\n );\n };\n },\n);\n\n/** 选中、名称与可用性由组管理 */\nexport type RadioManaged = 'type' | 'name' | 'checked' | 'required' | 'size' | 'value';\n\n/** 未声明的属性落到 input 上;外层 label 用 propsRoot */\nexport interface RadioProps extends PartProps<'input', RadioManaged> {\n /** 这一项的值 */\n value: string;\n /** 这一项不可用 */\n disabled?: boolean;\n /** 外层 label 的部件属性 */\n propsRoot?: PartProps<'label'>;\n /** 叠放层的部件属性 */\n propsControl?: PartProps<'span'>;\n /** 圆点的部件属性 */\n propsIndicator?: PartProps<'span'>;\n /** 文字的部件属性 */\n propsLabel?: PartProps<'span'>;\n /** 文字下方的说明(aria-describedby) */\n description?: VNodeChild;\n /** 说明的部件属性 */\n propsDescription?: PartProps<'span'>;\n /** 文字 */\n children?: VNodeChild;\n}\n\n/** RadioGroup、Radio 的样式:circle、dot、dotChecked */\nexport const radioStyles = css.create({\n circle: { width: '1.125em', height: '1.125em', borderRadius: '_full' },\n dot: {\n width: '0.45em',\n height: '0.45em',\n borderRadius: '_full',\n backgroundColor: 'var(--tone-on-fill)',\n transform: 'scale(0)',\n transition: `transform ${t.durations.sm} ${t.easings.standard}`,\n },\n dotChecked: { transform: 'none' },\n});\n\n/** 单选项:放在 RadioGroup 里 */\nexport const Radio = _component(\n ({\n value,\n disabled,\n propsRoot,\n propsControl,\n propsIndicator,\n propsLabel,\n description,\n propsDescription,\n children,\n ...rest\n }: RadioProps) => {\n const group = RadioGroupContext.inject();\n const descriptionId = `${useId()}-description`;\n const recipe = useRecipe(choiceRecipe);\n return () => {\n const checked = group.value === value;\n const off = disabled ?? group.disabled;\n const s = choiceParts(\n { size: group.size, tone: group.tone, recipe },\n { disabled: off, readonly: group.readonly },\n );\n return (\n <label\n {...mergeAttrs<'label'>(s.root, propsRoot)}\n data-state={checked ? 'checked' : 'unchecked'}\n data-disabled={off || undefined}\n data-readonly={group.readonly || undefined}\n >\n <span {...mergeAttrs<'span'>(s.control, propsControl)}>\n <input\n {...mergeAttrs<'input'>(\n {\n ...s.input,\n sx: [\n s.input.sx,\n focusRingStyles.tight,\n radioStyles.circle,\n checked && choiceInputStyles.checked,\n group.invalid && choiceInputStyles.invalid,\n ],\n },\n rest,\n {\n type: 'radio',\n name: group.name,\n value,\n checked,\n disabled: off,\n required: group.required,\n 'aria-describedby': hasContent(description) ? descriptionId : undefined,\n onChange: (event: Event) => {\n group.select(value);\n // 浏览器已经取消了同组原来选中的那个:整组一起对回父级的值\n const radios = (event.target as HTMLElement)\n .closest('[role=\"radiogroup\"]')\n ?.querySelectorAll<HTMLInputElement>('input[type=\"radio\"]');\n syncChecked([...(radios ?? [])], (input) => input.value === group.value);\n },\n ...(group.readonly && readonlyChoiceHandlers),\n },\n )}\n />\n <span\n {...mergeAttrs<'span'>(\n {\n ...s.indicator,\n sx: [s.indicator.sx, radioStyles.dot, checked && radioStyles.dotChecked],\n },\n propsIndicator,\n )}\n />\n </span>\n {(hasContent(children) || hasContent(description)) && (\n <span {...mergeAttrs<'span'>(s.label, propsLabel)}>\n {children}\n {hasContent(description) && (\n <span\n {...mergeAttrs<'span'>(s.description, propsDescription, {\n id: descriptionId,\n })}\n >\n {description}\n </span>\n )}\n </span>\n )}\n </label>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -6,8 +6,8 @@ import { focusRingStyles } from "../utils/style/styles.js";
6
6
  import { Icon } from "../base/Icon.js";
7
7
  import { visuallyHiddenStyles } from "../base/VisuallyHidden.js";
8
8
  import { useFieldControl } from "../form/Field.js";
9
- import { createVNode, mergeProps, ref, useId } from "vue";
10
- import { _component, bindable, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
9
+ import { createVNode, ref, useId } from "vue";
10
+ import { _component, bindable, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
11
11
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
12
12
  import { Star } from "@lucide/icons";
13
13
  //#region src/input/Rating.tsx
@@ -168,12 +168,12 @@ var Rating = /*#__PURE__*/ _component((_props, _ctx) => {
168
168
  id: state.id,
169
169
  role: "img",
170
170
  "aria-label": lang.ratingSummary(value.value, count.value)
171
- }), [stars.map((index) => createVNode("span", mergeProps({
171
+ }), [stars.map((index) => createVNode("span", mergeJsxProps({
172
172
  "key": index,
173
173
  "aria-hidden": "true"
174
174
  }, mergeAttrs({ sx: [ratingStyles.star, ratingStyles.readonly] }, propsStar.value)), [starIcon(filled(value.value, index))]))]);
175
175
  const shown = hover.value ?? value.value;
176
- const radio = (score, sx) => createVNode("label", mergeProps(css.attrs(sx), { "onPointerenter": () => hover.value = score }), [createVNode("input", mergeProps({
176
+ const radio = (score, sx) => createVNode("label", mergeJsxProps(css.attrs(sx), { "onPointerenter": () => hover.value = score }), [createVNode("input", mergeJsxProps({
177
177
  "type": "radio",
178
178
  "name": name.value ?? generatedName,
179
179
  "value": String(score),
@@ -195,7 +195,7 @@ var Rating = /*#__PURE__*/ _component((_props, _ctx) => {
195
195
  "aria-describedby": state.describedBy,
196
196
  "aria-disabled": state.disabled || void 0,
197
197
  onPointerleave: () => hover.value = null
198
- }), [stars.map((index) => createVNode("span", mergeProps({ "key": index }, mergeAttrs({ sx: [ratingStyles.star, focusRingStyles.within] }, propsStar.value), { "data-state": filled(value.value, index) === 100 ? "full" : filled(value.value, index) ? "half" : "empty" }), [
198
+ }), [stars.map((index) => createVNode("span", mergeJsxProps({ "key": index }, mergeAttrs({ sx: [ratingStyles.star, focusRingStyles.within] }, propsStar.value), { "data-state": filled(value.value, index) === 100 ? "full" : filled(value.value, index) ? "half" : "empty" }), [
199
199
  starIcon(filled(shown, index)),
200
200
  allowHalf.value && radio(index - .5, ratingStyles.startHalf),
201
201
  radio(index, allowHalf.value ? ratingStyles.endHalf : ratingStyles.whole)
@@ -1 +1 @@
1
- {"version":3,"file":"Rating.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_ref","_createVNode","_mergeProps"],"sources":["../../src/input/Rating.tsx"],"sourcesContent":["/**\n * 评分:几颗星(或别的图标)里选一个分数,供应商评价、满意度、优先级。可以半星,可以只读显示。\n *\n * <Field label=\"交付质量\"><Rating _value={score} /></Field>\n * <Rating value={4.5} readonly /> 只读:一个 role=\"img\",读“4.5 星,满分 5 星”\n * <Rating _value={score} allowHalf count={10} icon={Heart} tone=\"danger\" />\n *\n * 可编辑时是单选组(role=\"radiogroup\"):每颗星是一个原生 radio(视觉上隐藏),方向键、表单提交、读屏都是原生的;\n * 名称是“3 星”这样的文字(lang.ratingStar)。指针悬停时预览将要选的分数;再点一次已选的分数清空(clearable,默认开)。\n * 半星:每颗星左右各一半,各是一个 radio。部件:Root(div)、Star(span,每颗星)、Icon。\n */\nimport { Star } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { SxStyles } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { useId } from 'vue';\nimport { Icon, type IconData } from '../base/Icon';\nimport { visuallyHiddenStyles } from '../base/VisuallyHidden';\nimport { useLang } from '../config/context';\nimport { useFieldControl } from '../form/Field';\nimport { defaultLabelledBy, mergeAttrs, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\nimport type { StatusTone } from '../utils/style/tone-styles';\nimport { t } from '../config/theme/tokens';\n\n/** 角色由组件管理 */\nexport type RatingManaged = 'role';\n\n/** 未声明的属性落到外层 div 上;名称写 aria-label,或放在 Field 里 */\nexport interface RatingProps extends PartProps<'div', RatingManaged> {\n /** 分数:父级写 _value={score};没有评分时是 null */\n _value?: number | null;\n /** 一共几颗星,默认 5 */\n count?: number;\n /** 可以选半颗 */\n allowHalf?: boolean;\n /** 再点一次已选的分数时清空,默认 true */\n clearable?: boolean;\n /** 图标,默认星星 */\n icon?: IconData;\n /** 选中的颜色,默认 warning(金黄) */\n tone?: StatusTone;\n /** 字号档位:图标随之缩放 */\n size?: TextSize;\n /** 只读:只显示分数(一个 role=\"img\") */\n readonly?: boolean;\n /** 不可用(不写时取 Field 的) */\n disabled?: boolean;\n /** 表单提交时的 name */\n name?: string;\n /** 每颗星的部件属性 */\n propsStar?: PartProps<'span'>;\n}\n\n/** Rating 的样式:root、star、readonly、icon、empty、fill、clip、clipIcon、whole、startHalf、endHalf、disabled */\nexport const ratingStyles = css.create({\n root: { display: 'inline-flex', alignItems: 'center', gap: '0.15em', lineHeight: 1 },\n // 每颗星:空心图标打底,填色的那层按比例裁出;radio 盖满(半星时左右各一半)\n star: {\n position: 'relative',\n display: 'inline-grid',\n width: '1.35em',\n height: '1.35em',\n borderRadius: '_sm',\n cursor: 'pointer',\n transition: `scale ${t.durations.sm} ${t.easings.standard}`,\n scale: { default: null, ':hover': '1.12' },\n },\n readonly: { cursor: 'default', scale: null },\n icon: { gridArea: '1 / 1', width: '100%', height: '100%' },\n empty: { color: '_borderStrong' },\n // 填色的那层:currentColor 填满图标\n fill: { fill: 'currentColor' },\n clip: { gridArea: '1 / 1', overflow: 'hidden', pointerEvents: 'none' },\n // 裁出来的那层按整颗星的大小画,不随裁出的宽度缩小\n clipIcon: { display: 'block', width: '1.35em', height: '1.35em', maxWidth: 'none' },\n // 点击区域:整颗;半星时起始边一半、结束边一半\n whole: { position: 'absolute', inset: 0 },\n startHalf: { position: 'absolute', insetBlock: 0, insetInlineStart: 0, width: '50%' },\n endHalf: { position: 'absolute', insetBlock: 0, insetInlineEnd: 0, width: '50%' },\n disabled: { opacity: '_disabled', cursor: 'not-allowed' },\n});\n\n// 选中的颜色用各色调的实色(金黄的星、红色的心):实心与空心靠形状区分,不只靠颜色;Windows 高对比下用系统高亮色\n/** Rating 的颜色:neutral、accent、info、success、warning、danger */\nexport const ratingToneStyles = css.create({\n neutral: { color: { default: '_textMuted', '@media (forced-colors: active)': 'Highlight' } },\n accent: { color: { default: '_accent', '@media (forced-colors: active)': 'Highlight' } },\n info: { color: { default: '_info', '@media (forced-colors: active)': 'Highlight' } },\n success: { color: { default: '_success', '@media (forced-colors: active)': 'Highlight' } },\n warning: { color: { default: '_warning', '@media (forced-colors: active)': 'Highlight' } },\n danger: { color: { default: '_danger', '@media (forced-colors: active)': 'Highlight' } },\n});\n\n/** 填色那层的宽度 */\nexport const ratingClipStyles = css.create({\n width: (percent: string) => ({ width: percent }),\n});\n\n/** 评分:一排可以点的星 */\nexport const Rating = _component(\n ({\n _value: value = _bindable<number | null>(null),\n count = 5,\n allowHalf = false,\n clearable = true,\n icon = Star,\n tone = 'warning',\n size,\n readonly,\n disabled,\n name,\n id,\n propsStar,\n ...rest\n }: RatingProps) => {\n const lang = useLang();\n const generatedName = useId();\n const control = useFieldControl(() => ({ id, disabled, readonly }));\n // 指针悬停时预览的分数\n let hover = _state<number | null>(null);\n\n /** 第 index 颗星(从 1 开始)填了多少:0、50、100 */\n const filled = (shown: number | null, index: number) =>\n shown == null ? 0 : shown >= index ? 100 : shown >= index - 0.5 ? 50 : 0;\n\n function pick(next: number) {\n value = clearable && value === next ? null : next;\n hover = null;\n }\n\n const starIcon = (percent: number) => [\n <Icon icon={icon} sx={[ratingStyles.icon, ratingStyles.empty]} />,\n percent > 0 && (\n <span {...css.attrs(ratingStyles.clip, ratingClipStyles.width(`${percent}%`))}>\n <Icon\n icon={icon}\n sx={[ratingStyles.clipIcon, ratingStyles.fill, ratingToneStyles[tone]]}\n />\n </span>\n ),\n ];\n\n return () => {\n const state = control();\n const stars = Array.from({ length: count }, (_, index) => index + 1);\n\n if (state.readonly) {\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [ratingStyles.root, size && fontSizeStyles[size]],\n 'aria-labelledby': defaultLabelledBy(rest, state.labelledBy),\n },\n rest,\n { id: state.id, role: 'img', 'aria-label': lang.ratingSummary(value, count) },\n )}\n >\n {stars.map((index) => (\n <span\n key={index}\n aria-hidden=\"true\"\n {...mergeAttrs<'span'>(\n { sx: [ratingStyles.star, ratingStyles.readonly] },\n propsStar,\n )}\n >\n {starIcon(filled(value, index))}\n </span>\n ))}\n </div>\n );\n }\n\n const shown = hover ?? value;\n const radio = (score: number, sx: SxStyles) => (\n <label {...css.attrs(sx)} onPointerenter={() => (hover = score)}>\n <input\n type=\"radio\"\n name={name ?? generatedName}\n value={String(score)}\n checked={value === score}\n disabled={state.disabled}\n aria-label={lang.ratingStar(score)}\n onClick={() => pick(score)}\n {...css.attrs(visuallyHiddenStyles.hidden)}\n />\n </label>\n );\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n ratingStyles.root,\n size && fontSizeStyles[size],\n state.disabled && ratingStyles.disabled,\n ],\n 'aria-labelledby': defaultLabelledBy(rest, state.labelledBy),\n },\n rest,\n {\n id: state.id,\n role: 'radiogroup',\n 'aria-describedby': state.describedBy,\n 'aria-disabled': state.disabled || undefined,\n onPointerleave: () => (hover = null),\n },\n )}\n >\n {stars.map((index) => (\n <span\n key={index}\n {...mergeAttrs<'span'>(\n {\n sx: [ratingStyles.star, focusRingStyles.within],\n },\n propsStar,\n )}\n data-state={\n filled(value, index) === 100 ? 'full' : filled(value, index) ? 'half' : 'empty'\n }\n >\n {starIcon(filled(shown, index))}\n {allowHalf && radio(index - 0.5, ratingStyles.startHalf)}\n {radio(index, allowHalf ? ratingStyles.endHalf : ratingStyles.whole)}\n </span>\n ))}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"Rating.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_ref","_createVNode","_mergeProps"],"sources":["../../src/input/Rating.tsx"],"sourcesContent":["/**\n * 评分:几颗星(或别的图标)里选一个分数,供应商评价、满意度、优先级。可以半星,可以只读显示。\n *\n * <Field label=\"交付质量\"><Rating _value={score} /></Field>\n * <Rating value={4.5} readonly /> 只读:一个 role=\"img\",读“4.5 星,满分 5 星”\n * <Rating _value={score} allowHalf count={10} icon={Heart} tone=\"danger\" />\n *\n * 可编辑时是单选组(role=\"radiogroup\"):每颗星是一个原生 radio(视觉上隐藏),方向键、表单提交、读屏都是原生的;\n * 名称是“3 星”这样的文字(lang.ratingStar)。指针悬停时预览将要选的分数;再点一次已选的分数清空(clearable,默认开)。\n * 半星:每颗星左右各一半,各是一个 radio。部件:Root(div)、Star(span,每颗星)、Icon。\n */\nimport { Star } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { SxStyles } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { useId } from 'vue';\nimport { Icon, type IconData } from '../base/Icon';\nimport { visuallyHiddenStyles } from '../base/VisuallyHidden';\nimport { useLang } from '../config/context';\nimport { useFieldControl } from '../form/Field';\nimport { defaultLabelledBy, mergeAttrs, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\nimport type { StatusTone } from '../utils/style/tone-styles';\nimport { t } from '../config/theme/tokens';\n\n/** 角色由组件管理 */\nexport type RatingManaged = 'role';\n\n/** 未声明的属性落到外层 div 上;名称写 aria-label,或放在 Field 里 */\nexport interface RatingProps extends PartProps<'div', RatingManaged> {\n /** 分数:父级写 _value={score};没有评分时是 null */\n _value?: number | null;\n /** 一共几颗星,默认 5 */\n count?: number;\n /** 可以选半颗 */\n allowHalf?: boolean;\n /** 再点一次已选的分数时清空,默认 true */\n clearable?: boolean;\n /** 图标,默认星星 */\n icon?: IconData;\n /** 选中的颜色,默认 warning(金黄) */\n tone?: StatusTone;\n /** 字号档位:图标随之缩放 */\n size?: TextSize;\n /** 只读:只显示分数(一个 role=\"img\") */\n readonly?: boolean;\n /** 不可用(不写时取 Field 的) */\n disabled?: boolean;\n /** 表单提交时的 name */\n name?: string;\n /** 每颗星的部件属性 */\n propsStar?: PartProps<'span'>;\n}\n\n/** Rating 的样式:root、star、readonly、icon、empty、fill、clip、clipIcon、whole、startHalf、endHalf、disabled */\nexport const ratingStyles = css.create({\n root: { display: 'inline-flex', alignItems: 'center', gap: '0.15em', lineHeight: 1 },\n // 每颗星:空心图标打底,填色的那层按比例裁出;radio 盖满(半星时左右各一半)\n star: {\n position: 'relative',\n display: 'inline-grid',\n width: '1.35em',\n height: '1.35em',\n borderRadius: '_sm',\n cursor: 'pointer',\n transition: `scale ${t.durations.sm} ${t.easings.standard}`,\n scale: { default: null, ':hover': '1.12' },\n },\n readonly: { cursor: 'default', scale: null },\n icon: { gridArea: '1 / 1', width: '100%', height: '100%' },\n empty: { color: '_borderStrong' },\n // 填色的那层:currentColor 填满图标\n fill: { fill: 'currentColor' },\n clip: { gridArea: '1 / 1', overflow: 'hidden', pointerEvents: 'none' },\n // 裁出来的那层按整颗星的大小画,不随裁出的宽度缩小\n clipIcon: { display: 'block', width: '1.35em', height: '1.35em', maxWidth: 'none' },\n // 点击区域:整颗;半星时起始边一半、结束边一半\n whole: { position: 'absolute', inset: 0 },\n startHalf: { position: 'absolute', insetBlock: 0, insetInlineStart: 0, width: '50%' },\n endHalf: { position: 'absolute', insetBlock: 0, insetInlineEnd: 0, width: '50%' },\n disabled: { opacity: '_disabled', cursor: 'not-allowed' },\n});\n\n// 选中的颜色用各色调的实色(金黄的星、红色的心):实心与空心靠形状区分,不只靠颜色;Windows 高对比下用系统高亮色\n/** Rating 的颜色:neutral、accent、info、success、warning、danger */\nexport const ratingToneStyles = css.create({\n neutral: { color: { default: '_textMuted', '@media (forced-colors: active)': 'Highlight' } },\n accent: { color: { default: '_accent', '@media (forced-colors: active)': 'Highlight' } },\n info: { color: { default: '_info', '@media (forced-colors: active)': 'Highlight' } },\n success: { color: { default: '_success', '@media (forced-colors: active)': 'Highlight' } },\n warning: { color: { default: '_warning', '@media (forced-colors: active)': 'Highlight' } },\n danger: { color: { default: '_danger', '@media (forced-colors: active)': 'Highlight' } },\n});\n\n/** 填色那层的宽度 */\nexport const ratingClipStyles = css.create({\n width: (percent: string) => ({ width: percent }),\n});\n\n/** 评分:一排可以点的星 */\nexport const Rating = _component(\n ({\n _value: value = _bindable<number | null>(null),\n count = 5,\n allowHalf = false,\n clearable = true,\n icon = Star,\n tone = 'warning',\n size,\n readonly,\n disabled,\n name,\n id,\n propsStar,\n ...rest\n }: RatingProps) => {\n const lang = useLang();\n const generatedName = useId();\n const control = useFieldControl(() => ({ id, disabled, readonly }));\n // 指针悬停时预览的分数\n let hover = _state<number | null>(null);\n\n /** 第 index 颗星(从 1 开始)填了多少:0、50、100 */\n const filled = (shown: number | null, index: number) =>\n shown == null ? 0 : shown >= index ? 100 : shown >= index - 0.5 ? 50 : 0;\n\n function pick(next: number) {\n value = clearable && value === next ? null : next;\n hover = null;\n }\n\n const starIcon = (percent: number) => [\n <Icon icon={icon} sx={[ratingStyles.icon, ratingStyles.empty]} />,\n percent > 0 && (\n <span {...css.attrs(ratingStyles.clip, ratingClipStyles.width(`${percent}%`))}>\n <Icon\n icon={icon}\n sx={[ratingStyles.clipIcon, ratingStyles.fill, ratingToneStyles[tone]]}\n />\n </span>\n ),\n ];\n\n return () => {\n const state = control();\n const stars = Array.from({ length: count }, (_, index) => index + 1);\n\n if (state.readonly) {\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [ratingStyles.root, size && fontSizeStyles[size]],\n 'aria-labelledby': defaultLabelledBy(rest, state.labelledBy),\n },\n rest,\n { id: state.id, role: 'img', 'aria-label': lang.ratingSummary(value, count) },\n )}\n >\n {stars.map((index) => (\n <span\n key={index}\n aria-hidden=\"true\"\n {...mergeAttrs<'span'>(\n { sx: [ratingStyles.star, ratingStyles.readonly] },\n propsStar,\n )}\n >\n {starIcon(filled(value, index))}\n </span>\n ))}\n </div>\n );\n }\n\n const shown = hover ?? value;\n const radio = (score: number, sx: SxStyles) => (\n <label {...css.attrs(sx)} onPointerenter={() => (hover = score)}>\n <input\n type=\"radio\"\n name={name ?? generatedName}\n value={String(score)}\n checked={value === score}\n disabled={state.disabled}\n aria-label={lang.ratingStar(score)}\n onClick={() => pick(score)}\n {...css.attrs(visuallyHiddenStyles.hidden)}\n />\n </label>\n );\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n ratingStyles.root,\n size && fontSizeStyles[size],\n state.disabled && ratingStyles.disabled,\n ],\n 'aria-labelledby': defaultLabelledBy(rest, state.labelledBy),\n },\n rest,\n {\n id: state.id,\n role: 'radiogroup',\n 'aria-describedby': state.describedBy,\n 'aria-disabled': state.disabled || undefined,\n onPointerleave: () => (hover = null),\n },\n )}\n >\n {stars.map((index) => (\n <span\n key={index}\n {...mergeAttrs<'span'>(\n {\n sx: [ratingStyles.star, focusRingStyles.within],\n },\n propsStar,\n )}\n data-state={\n filled(value, index) === 100 ? 'full' : filled(value, index) ? 'half' : 'empty'\n }\n >\n {starIcon(filled(shown, index))}\n {allowHalf && radio(index - 0.5, ratingStyles.startHalf)}\n {radio(index, allowHalf ? ratingStyles.endHalf : ratingStyles.whole)}\n </span>\n ))}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -16,8 +16,8 @@ import { ListPopover } from "./ListPopover.js";
16
16
  import { useRemoteItems } from "./remote-items.js";
17
17
  import { SelectedTags } from "./SelectedTags.js";
18
18
  import { TextField } from "./TextField.js";
19
- import { Fragment, createVNode, mergeProps, shallowRef, useId, watch } from "vue";
20
- import { _component, bindable, childrenProp, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
19
+ import { Fragment, createVNode, shallowRef, useId, watch } from "vue";
20
+ import { _component, bindable, childrenProp, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
21
21
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
22
22
  import { ChevronDown, Plus, Search } from "@lucide/icons";
23
23
  //#region src/input/Select.tsx
@@ -314,7 +314,7 @@ var Select = /*#__PURE__*/ _component((_props, _ctx) => {
314
314
  propsTag: propsTag.value
315
315
  }, propsTags.value), null);
316
316
  const s = controlParts(appearance(), state);
317
- return createVNode(Fragment, null, [createVNode("div", mergeProps(mergeAttrs({
317
+ return createVNode(Fragment, null, [createVNode("div", mergeJsxProps(mergeAttrs({
318
318
  ...s.root,
319
319
  sx: [s.root.sx, selectStyles.root]
320
320
  }, propsRoot.value, {
@@ -377,7 +377,7 @@ var Select = /*#__PURE__*/ _component((_props, _ctx) => {
377
377
  "label": rest["aria-label"],
378
378
  "loading": loading.value || remote.loading(),
379
379
  "onPick": _cache[0] || (_cache[0] = () => picked()),
380
- "header": withSearch() && createVNode(TextField, mergeProps(mergePartProps({
380
+ "header": withSearch() && createVNode(TextField, mergeJsxProps(mergePartProps({
381
381
  icon: Search,
382
382
  variant: "soft",
383
383
  placeholder: lang.selectSearch,
@@ -394,7 +394,7 @@ var Select = /*#__PURE__*/ _component((_props, _ctx) => {
394
394
  "listbox": {
395
395
  list,
396
396
  id: listId,
397
- empty: remote.error() ? lang.listLoadFailed : search.value ? lang.selectNoMatch : empty.value,
397
+ empty: remote.failure() ?? (search.value ? lang.selectNoMatch : empty.value),
398
398
  renderOption: children.value && ((item, state) => item instanceof Creation ? lang.selectCreate(item.text) : children.value(item, state)),
399
399
  multiple: multiple()
400
400
  },
@@ -1 +1 @@
1
- {"version":3,"file":"Select.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_childrenProp","_vtp_restProps","_vue_shallowRef","_createVNode","_Fragment","_mergeProps"],"sources":["../../src/input/Select.tsx"],"sourcesContent":["/**\n * 下拉选择(WAI-ARIA 的 select-only combobox):点触发框弹出选项列表,单选或多选。\n *\n * <Field label=\"城市\"><Select items={['北京', '上海', '广州']} _value={city} placeholder=\"选择城市\" /></Field>\n * <Select items={tags} selectionMode=\"multiple\" _value={picked} clearable aria-label=\"标签\" />\n * <Select items={users} toOption={(user) => ({ value: user.id, label: user.name })} _value={id} />\n * <Select items={suppliers} searchable _value={supplier} /> 选项多时:弹出层顶部带搜索框\n *\n * <Select items={tags} selectionMode=\"multiple\" maxTagCount=\"responsive\" creatable onCreate={(text) => tags.push(text)} … />\n *\n * 组合已有的部件:外壳是输入框外壳(controlParts),弹出层用 useAnchoredPopover(与外壳同宽、最高到视口剩余空间),\n * 列表是 ListboxView(状态与键盘见 list-state.ts)。焦点一直在触发按钮上,高亮项经 aria-activedescendant 告诉读屏。\n *\n * 多选时已选的项是触发按钮前面的一排 Tag(不能放进 button 里:按钮里不能有按钮),各带移除按钮。\n * 这排标签只给指针用(aria-hidden、移除按钮不进 Tab 顺序):读屏从触发按钮里念出全部已选内容,\n * 键盘在列表里取消勾选,或在触发按钮(及空的搜索框)里按 Backspace 移除最后一项(同 TagsInput)。\n * maxTagCount 是数字时只显示前几个,'responsive' 时排成一行按宽度放,其余收进“+N”(SelectedTags,TreeSelect 共用)。\n *\n * 键盘:关闭时 ↓ / Enter / 空格打开(↑ 打开并高亮最后一项),单选时直接按字母选中以它开头的项(同原生 select);\n * 打开时 ↑↓、Home / End、Page Up / Down 移动,Enter / 空格选中(单选随后关闭),Esc、Tab 关闭。\n * 写了 name 时用隐藏的 input 随表单提交(多选时每个值一个)。\n *\n * searchable 时弹出层顶部有搜索框:打开后焦点在搜索框里,输入就过滤选项(按显示文字,忽略大小写与重音,或用 filter),\n * ↑↓ 移动、Enter 选中、Esc 关闭并把焦点还给触发按钮。已选的项被过滤掉、或 items 换了(远程搜索)时,\n * 触发框里仍显示它的文字(useSelectedOptions)。\n *\n * 远程选项:给 load 时打开就按搜索词请求,输入停下 300 ms 再请求,只采用最后一次(remote-items.ts);\n * 自己管请求时写 _search={keyword} 拿到搜索词、filter={false} 关掉本地过滤,items 与 loading 自己给。\n *\n * <Select searchable load={(q, signal) => http.get<User[]>('/users', { query: { q }, signal })} toOption={…} _value={owner} />\n *\n * creatable 时自带搜索框,输入的文字没有对应的选项时列表末尾多一项“新建“…””:选中后值就是这段文字,onCreate 报告它。\n *\n * 部件:Root(外壳)、Tags(多选时的那排标签)、Tag、Trigger(button,主元素)、Value、Clear、Chevron、Popover、\n * Search(TextField)、Listbox。\n */\nimport { ChevronDown, Plus, Search } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { useId, watch, type VNodeChild } from 'vue';\nimport type { PresetIconButtonProps } from '../base/CloseButton';\nimport { buttonBaseStyles } from '../base/button-core';\nimport { Icon, type IconProps } from '../base/Icon';\nimport type { TagProps } from '../base/Tag';\nimport { visuallyHiddenStyles } from '../base/VisuallyHidden';\nimport { useLang, useTextMatcher } from '../config/context';\nimport { useAnchoredPopover, type FloatingPlacement } from '../utils/dom/floating';\nimport { openSetter, type OpenChangeProps } from '../utils/dom/open-change';\nimport { ListPopover } from './ListPopover';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { selectedValues, type SelectionProps } from '../utils/data/selection';\nimport {\n controlClear,\n controlParts,\n clickOnShell,\n focusOnShell,\n controlIcon,\n useControlAppearance,\n type ControlIconOptions,\n type ControlOptions,\n} from './control';\nimport { useFieldControl } from '../form/Field';\nimport { FormValue } from '../form/FormValue';\nimport { disclosureStyles } from '../utils/style/transitions';\nimport { activeOptionId, type ListboxViewProps, type OptionRenderState } from './Listbox';\nimport {\n handleListKeydown,\n useListState,\n useResultAnnouncement,\n useSelectedOptions,\n type ListboxOption,\n type OptionMapping,\n toListboxOption,\n} from './list-state';\nimport { useRemoteItems, type OptionsLoader } from './remote-items';\nimport { SelectedTags, type SelectedTagsProps } from './SelectedTags';\nimport { TextField, type TextFieldProps } from './TextField';\n\n/** 角色、展开状态与可用性由组件管理 */\nexport type SelectManaged =\n | 'type'\n | 'role'\n | 'value'\n | 'disabled'\n | 'aria-haspopup'\n | 'aria-expanded'\n | 'aria-controls'\n | 'aria-activedescendant'\n | 'aria-invalid'\n | 'aria-required'\n | 'aria-describedby';\n\n/** 下拉选择共有的属性;未声明的属性落到触发按钮(主元素)上,外壳用 propsRoot */\nexport interface SelectBaseProps<T>\n extends PartProps<'button', SelectManaged>, ControlOptions, ControlIconOptions, OpenChangeProps {\n /** 数据:ListboxOption、字符串,或任意数据加 toOption;有 load 时是第一次加载之前的选项(编辑页放上已选的那一项) */\n items?: readonly T[];\n /** 没有选择时显示的文字,默认取语言包(请选择) */\n placeholder?: string;\n /** 是否打开:父级可以写 _open={x} */\n _open?: boolean;\n /** 弹出位置,默认 bottom-start */\n placement?: FloatingPlacement;\n /** 有选择时显示清空按钮 */\n clearable?: boolean;\n /** 弹出层顶部带搜索框,输入过滤选项:选项多(供应商、人员、件号)时用 */\n searchable?: boolean;\n /** 搜索时怎样算匹配;默认显示文字包含输入(忽略大小写与重音)。false 时不在本地过滤(服务端按 search 过滤) */\n filter?: false | ((item: T, query: string) => boolean);\n /** 搜索框里的文字:打开时清空;父级写 _search={x} 拿到它(自己发请求时) */\n _search?: string;\n /** 远程选项:打开时与搜索词停下 300 ms 后调用,结果代替 items;只采用最后一次,被顶掉的请求 signal 中止 */\n load?: OptionsLoader<T>;\n /**\n * 可以新建选项(自带搜索框):输入的文字没有对应的选项时,列表末尾多一项“新建“…””,选中后值就是这段文字。\n * 在 onCreate 里把它加进 items(或存到服务端);不加时触发框里照样显示这段文字\n */\n creatable?: boolean;\n /** 新建了一项(creatable 时):参数是输入的文字,也就是选中的值 */\n onCreate?: (text: string) => void;\n /** 多选时触发框里最多显示几个标签,其余收进“+N”;'responsive' 时排成一行、按宽度放,放不下的收起 */\n maxTagCount?: number | 'responsive';\n /** 表单提交时的 name(用隐藏的 input) */\n name?: string;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:能聚焦、能看到已选的内容,不能打开、不能清空 */\n readonly?: boolean;\n /** 必填 */\n required?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 自定义选项内容:`{(option, { selected, active }) => …}` */\n children?: (item: T, state: OptionRenderState) => VNodeChild;\n /** 自定义触发框里显示的内容(已选的选项);默认单选显示文字、多选显示标签 */\n renderValue?: (selected: readonly T[]) => VNodeChild;\n /** 正在取选项(异步加载):没有选项时列表里是骨架行,已有选项时顶部显示进度条 */\n loading?: boolean;\n /** 没有选项时列表里显示的内容 */\n empty?: VNodeChild;\n /** 外壳的部件属性 */\n propsRoot?: PartProps<'div'>;\n /** 已选内容那一层的部件属性 */\n propsValue?: PartProps<'span'>;\n /** 多选时每个标签的部件属性 */\n propsTag?: Partial<TagProps>;\n /** 多选时那排标签的部件属性 */\n propsTags?: Partial<SelectedTagsProps>;\n /** 清空按钮的部件属性 */\n propsClear?: Partial<PresetIconButtonProps>;\n /** 下拉箭头的部件属性 */\n propsChevron?: Partial<IconProps>;\n /** 弹出层的部件属性 */\n propsPopover?: PartProps<'div', 'id' | 'popover'>;\n /** 列表的部件属性 */\n propsListbox?: Partial<ListboxViewProps<T>>;\n /** 搜索框的部件属性(searchable 时) */\n propsSearch?: Partial<TextFieldProps>;\n}\n\n/** 单选或多选;items 不是 ListboxOption 或字符串时要给 toOption */\nexport type SelectProps<T = ListboxOption> = SelectBaseProps<T> & SelectionProps & OptionMapping<T>;\n\n/** Select 的样式:root、trigger、value、placeholder、chevronOpen 等 */\nexport const selectStyles = css.create({\n // 在 ControlGroup 里也按内容宽(输入框才分剩余宽度)\n root: { cursor: 'pointer', flexGrow: 0 },\n // 去掉按钮默认外观用 buttonBaseStyles;像输入框一样没有自己的焦点环与波纹(焦点环画在外壳上)\n trigger: {\n display: 'flex',\n alignItems: 'center',\n flexGrow: 1,\n minWidth: 0,\n alignSelf: 'stretch',\n textAlign: 'start',\n cursor: 'inherit',\n outlineStyle: 'none',\n },\n value: {\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n gap: '_xs',\n minWidth: 0,\n paddingBlock: '_xs',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n // 是真正的文字(不是原生 placeholder),要满足 4.5:1:用 textMuted 而不是 textPlaceholder\n placeholder: { color: '_textMuted' },\n // 多选时标签排在触发按钮前面(SelectedTags)占剩余宽度,触发按钮里只剩读屏用的文字\n triggerBehindTags: { flexGrow: 0 },\n chevronOpen: { rotate: '180deg' },\n // 弹出层顶部的搜索框占满宽度\n search: { width: '_full' },\n});\n\n/** creatable 时列表末尾那一项“新建“…””:不是 items 里的数据 */\nclass Creation {\n readonly text: string;\n constructor(text: string) {\n this.text = text;\n }\n}\n\n/** 下拉选择:触发框 + 弹出的选项列表 */\nexport const Select = _component(\n <T,>({\n items = [],\n toOption,\n selectionMode = 'single',\n _value: value = _bindable<string | string[] | null>(null),\n _open: open = _bindable(false),\n onOpenChange,\n placeholder,\n placement = 'bottom-start',\n clearable = false,\n searchable = false,\n filter,\n _search: search = _bindable(''),\n load,\n creatable = false,\n onCreate,\n maxTagCount,\n name,\n variant,\n size,\n radius,\n disabled,\n readonly,\n required,\n invalid,\n id,\n icon,\n children,\n renderValue,\n empty,\n loading = false,\n propsRoot,\n propsIcon,\n propsValue,\n propsTag,\n propsTags,\n propsClear,\n propsChevron,\n propsPopover,\n propsListbox,\n propsSearch,\n ...rest\n }: SelectProps<T>) => {\n const lang = useLang();\n const textMatcher = useTextMatcher();\n const listId = useId();\n const appearance = useControlAppearance(() => ({ variant, size, radius }));\n const control = useFieldControl(() => ({ id, invalid, required, disabled, readonly }));\n const multiple = () => selectionMode === 'multiple';\n const optionOf = (item: T) => toListboxOption(item, toOption);\n const remote = useRemoteItems({\n load: () => load,\n query: () => search,\n open: () => open,\n items: () => items,\n });\n // 本地过滤:有 load 或 filter={false} 时交给服务端\n const localFilter = () => !load && filter !== false;\n const matches = (item: T, text: string) =>\n filter ? filter(item, text) : textMatcher()(optionOf(item).label, text);\n // creatable 自带搜索框\n const withSearch = () => searchable || creatable;\n // creatable:输入的文字没有同名(或同值)的选项时,列表末尾多一项“新建”\n const creation = () => {\n const text = search.trim();\n if (!creatable || !text) return undefined;\n const exists = remote.items().some((item) => {\n const option = optionOf(item);\n return option.value === text || option.label.toLowerCase() === text.toLowerCase();\n });\n return exists ? undefined : new Creation(text);\n };\n const list = useListState<T | Creation>({\n items: () => {\n const all = remote.items();\n const shown =\n withSearch() && search && localFilter()\n ? all.filter((item) => matches(item, search))\n : all;\n const created = creation();\n return created ? [...shown, created] : shown;\n },\n toOption: (item) =>\n item instanceof Creation\n ? { value: item.text, label: lang.selectCreate(item.text), icon: Plus }\n : optionOf(item),\n selected: () => selectedValues(value),\n mode: () => selectionMode,\n onChange: (next) => {\n const created = creation();\n if (created && next.includes(created.text)) {\n onCreate?.(created.text);\n search = '';\n }\n value = multiple() ? [...next] : (next[0] ?? null);\n },\n // 单选时再点已选的一项不取消(同原生 select);要清空用清除按钮\n required: () => !multiple(),\n });\n // 已选项的文字取自全部 items(过滤掉的、远程搜索换掉的也在)\n const selectedOptions = useSelectedOptions({ items: remote.items, toOption: optionOf });\n let shell = _state.raw<HTMLElement | null>(null);\n let trigger = _state.raw<HTMLElement | null>(null);\n let panel = _state.raw<HTMLElement | null>(null);\n const setOpen = openSetter(\n () => open,\n (next) => (open = next),\n () => onOpenChange,\n );\n\n /** 多选时移除一项(标签的移除按钮、Backspace) */\n function remove(target: string) {\n value = selectedValues(value).filter((item) => item !== target);\n }\n\n function removeLast() {\n const last = selectedValues(value).at(-1);\n if (last !== undefined) remove(last);\n }\n\n function show(highlight: 'default' | 'last' = 'default', event?: Event) {\n search = '';\n list.activateDefault();\n if (highlight === 'last' && selectedValues(value).length === 0) list.move('last');\n setOpen(true, 'trigger', event);\n }\n\n useResultAnnouncement(() => ({ query: search, count: list.options.length }));\n\n // 输入搜索词:高亮第一个匹配的。打开时清空搜索词不算:那时高亮的是已选项\n watch(\n () => search,\n (text) => text && list.move('first'),\n );\n\n // 选中一项:单选时关闭\n function picked(event?: Event) {\n if (!multiple()) setOpen(false, 'select', event);\n }\n\n /** Ctrl / Cmd / Alt 组合键是浏览器的(刷新、复制、查找),不做按字母跳转 */\n const hasModifier = (event: KeyboardEvent) => event.altKey || event.ctrlKey || event.metaKey;\n\n function onKeydown(event: KeyboardEvent) {\n if (control().disabled || control().readonly) return;\n if (event.key === 'Backspace' && multiple()) {\n event.preventDefault();\n removeLast();\n return;\n }\n if (!open) {\n if (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n show('default', event);\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n show('last', event);\n } else if (!multiple() && !hasModifier(event) && list.typeahead(event.key)) {\n // 同原生 select:关闭时按字母直接选中\n event.preventDefault();\n if (list.active !== undefined && !list.isSelected(list.active)) list.select(list.active);\n }\n return;\n }\n if (event.key === 'Tab') {\n setOpen(false, 'focus', event);\n return;\n }\n if (handleListKeydown(list, event, { space: true, typeahead: true }, () => picked(event))) {\n event.preventDefault();\n }\n }\n\n // 搜索框里:↑↓ 移动、Enter 选中(Home / End、空格留给输入),Tab 关闭后照常移到下一个;\n // 多选时空的搜索框里按 Backspace 移除最后一项\n function onSearchKeydown(event: KeyboardEvent) {\n if (event.key === 'Tab') {\n setOpen(false, 'focus', event);\n return;\n }\n if (event.key === 'Backspace' && !search && multiple()) {\n event.preventDefault();\n removeLast();\n return;\n }\n if (handleListKeydown(list, event, { homeEnd: false }, () => picked(event)))\n event.preventDefault();\n }\n\n function clear() {\n value = multiple() ? [] : null;\n trigger?.focus();\n }\n\n // 弹层贴着外壳、与它同宽;焦点一直在触发按钮上,关闭时不用归还(searchable 时见 onPanelToggle)\n const { onToggle } = useAnchoredPopover(\n () => ({\n open,\n anchor: shell,\n panel,\n floating: { placement, matchWidth: true, fitHeight: true },\n restoreFocus: false,\n }),\n { close: (reason, event) => setOpen(false, reason, event) },\n );\n\n // searchable:打开后焦点进搜索框;关闭时焦点还在弹层里(Esc、选中、点外面)就还给触发按钮\n function onPanelToggle(event: ToggleEvent) {\n onToggle(event);\n if (!withSearch()) return;\n if (event.newState === 'open') {\n panel?.querySelector<HTMLInputElement>('input[type=\"search\"]')?.focus();\n return;\n }\n const active = document.activeElement;\n if (!active || active === document.body || panel?.contains(active)) trigger?.focus();\n }\n\n return () => {\n const state = control();\n const values = selectedValues(value);\n const selected = selectedOptions(values);\n const off = state.disabled;\n // 只读:能聚焦,不能打开、不能改\n const locked = off || state.readonly;\n // 多选的默认显示:触发按钮前面一排标签,按钮里只留给读屏的文字\n const tagged = multiple() && !renderValue && selected.length > 0;\n const shown = tagged ? (\n <span {...css.attrs(visuallyHiddenStyles.hidden)}>\n {lang.selectSummary(selected.map((option) => option.label))}\n </span>\n ) : (\n (renderValue?.(\n selected.flatMap((option) => (option.item === undefined ? [] : [option.item])),\n ) ??\n (selected.length === 0 ? (\n <span {...css.attrs(selectStyles.placeholder)}>\n {placeholder ?? lang.selectPlaceholder}\n </span>\n ) : (\n selected[0]!.label\n )))\n );\n const tags = tagged && (\n <SelectedTags\n {...mergePartProps<SelectedTagsProps>(\n {\n tags: selected,\n maxTagCount,\n onRemove: locked ? undefined : remove,\n propsTag,\n },\n propsTags,\n )}\n />\n );\n const s = controlParts(appearance(), state);\n return (\n <>\n <div\n {...mergeAttrs<'div'>({ ...s.root, sx: [s.root.sx, selectStyles.root] }, propsRoot, {\n ref: _toRef(shell),\n // 点在外壳空白处(含多选的标签):焦点交给触发按钮,并与点触发按钮一样切换打开(只读时只聚焦)\n onPointerdown: off ? undefined : focusOnShell(() => trigger),\n onClick: locked\n ? undefined\n : clickOnShell(\n () => trigger,\n (event) => (open ? setOpen(false, 'trigger', event) : show('default', event)),\n ),\n })}\n data-state={open ? 'open' : 'closed'}\n data-invalid={state.invalid || undefined}\n data-disabled={off || undefined}\n >\n {controlIcon(s, icon, propsIcon)}\n {tags}\n <button\n {...mergeAttrs<'button'>(\n {\n sx: [\n buttonBaseStyles.root,\n selectStyles.trigger,\n tagged && selectStyles.triggerBehindTags,\n ],\n },\n rest,\n {\n ref: _toRef(trigger),\n id: state.id,\n type: 'button',\n role: 'combobox',\n disabled: off,\n 'aria-haspopup': 'listbox',\n 'aria-expanded': open,\n 'aria-controls': listId,\n 'aria-activedescendant': open ? activeOptionId(list, listId) : undefined,\n 'aria-invalid': state.invalid || undefined,\n 'aria-required': state.required || undefined,\n 'aria-readonly': state.readonly || undefined,\n 'aria-describedby': state.describedBy,\n onClick: (event: MouseEvent) => {\n // Safari 点击按钮不会聚焦它:焦点要在触发按钮上,键盘与 aria-activedescendant 才有效\n trigger?.focus();\n if (locked) return;\n if (open) setOpen(false, 'trigger', event);\n else show('default', event);\n },\n onKeydown,\n },\n )}\n >\n <span {...mergeAttrs<'span'>({ sx: selectStyles.value }, propsValue)}>{shown}</span>\n </button>\n {clearable && values.length > 0 && !locked && controlClear(s, propsClear, clear)}\n <Icon\n {...mergePartProps<IconProps>(\n {\n ...s.icon,\n icon: ChevronDown,\n sx: [s.icon.sx, disclosureStyles.icon, open && selectStyles.chevronOpen],\n },\n propsChevron,\n )}\n />\n <FormValue name={name} value={values} disabled={state.disabled} />\n </div>\n <ListPopover\n panelRef={_toRef(panel)}\n onToggle={onPanelToggle}\n size={appearance().size}\n labelledBy={state.labelledBy}\n label={rest['aria-label']}\n loading={loading || remote.loading()}\n onPick={() => picked()}\n header={\n withSearch() && (\n <TextField\n {...mergePartProps<TextFieldProps>(\n {\n icon: Search,\n variant: 'soft',\n placeholder: lang.selectSearch,\n 'aria-label': lang.selectSearch,\n propsRoot: { sx: selectStyles.search },\n },\n propsSearch,\n )}\n type=\"search\"\n _value={search}\n aria-controls={listId}\n aria-activedescendant={open ? activeOptionId(list, listId) : undefined}\n onKeydown={onSearchKeydown}\n />\n )\n }\n listbox={{\n list,\n id: listId,\n empty: remote.error() ? lang.listLoadFailed : search ? lang.selectNoMatch : empty,\n renderOption:\n children &&\n ((item: T | Creation, state: OptionRenderState) =>\n item instanceof Creation ? lang.selectCreate(item.text) : children(item, state)),\n multiple: multiple(),\n }}\n // 使用方按 T 写列表的部件属性;creatable 时多出的“新建”那一项由上面的 renderOption 处理\n propsListbox={propsListbox as Partial<ListboxViewProps<T | Creation>> | undefined}\n propsPopover={propsPopover}\n />\n </>\n );\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"Select.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_childrenProp","_vtp_restProps","_vue_shallowRef","_createVNode","_Fragment","_mergeProps"],"sources":["../../src/input/Select.tsx"],"sourcesContent":["/**\n * 下拉选择(WAI-ARIA 的 select-only combobox):点触发框弹出选项列表,单选或多选。\n *\n * <Field label=\"城市\"><Select items={['北京', '上海', '广州']} _value={city} placeholder=\"选择城市\" /></Field>\n * <Select items={tags} selectionMode=\"multiple\" _value={picked} clearable aria-label=\"标签\" />\n * <Select items={users} toOption={(user) => ({ value: user.id, label: user.name })} _value={id} />\n * <Select items={suppliers} searchable _value={supplier} /> 选项多时:弹出层顶部带搜索框\n *\n * <Select items={tags} selectionMode=\"multiple\" maxTagCount=\"responsive\" creatable onCreate={(text) => tags.push(text)} … />\n *\n * 组合已有的部件:外壳是输入框外壳(controlParts),弹出层用 useAnchoredPopover(与外壳同宽、最高到视口剩余空间),\n * 列表是 ListboxView(状态与键盘见 list-state.ts)。焦点一直在触发按钮上,高亮项经 aria-activedescendant 告诉读屏。\n *\n * 多选时已选的项是触发按钮前面的一排 Tag(不能放进 button 里:按钮里不能有按钮),各带移除按钮。\n * 这排标签只给指针用(aria-hidden、移除按钮不进 Tab 顺序):读屏从触发按钮里念出全部已选内容,\n * 键盘在列表里取消勾选,或在触发按钮(及空的搜索框)里按 Backspace 移除最后一项(同 TagsInput)。\n * maxTagCount 是数字时只显示前几个,'responsive' 时排成一行按宽度放,其余收进“+N”(SelectedTags,TreeSelect 共用)。\n *\n * 键盘:关闭时 ↓ / Enter / 空格打开(↑ 打开并高亮最后一项),单选时直接按字母选中以它开头的项(同原生 select);\n * 打开时 ↑↓、Home / End、Page Up / Down 移动,Enter / 空格选中(单选随后关闭),Esc、Tab 关闭。\n * 写了 name 时用隐藏的 input 随表单提交(多选时每个值一个)。\n *\n * searchable 时弹出层顶部有搜索框:打开后焦点在搜索框里,输入就过滤选项(按显示文字,忽略大小写与重音,或用 filter),\n * ↑↓ 移动、Enter 选中、Esc 关闭并把焦点还给触发按钮。已选的项被过滤掉、或 items 换了(远程搜索)时,\n * 触发框里仍显示它的文字(useSelectedOptions)。\n *\n * 远程选项:给 load 时打开就按搜索词请求,输入停下 300 ms 再请求,只采用最后一次(remote-items.ts);\n * 自己管请求时写 _search={keyword} 拿到搜索词、filter={false} 关掉本地过滤,items 与 loading 自己给。\n *\n * <Select searchable load={(q, signal) => http.get<User[]>('/users', { query: { q }, signal })} toOption={…} _value={owner} />\n *\n * creatable 时自带搜索框,输入的文字没有对应的选项时列表末尾多一项“新建“…””:选中后值就是这段文字,onCreate 报告它。\n *\n * 部件:Root(外壳)、Tags(多选时的那排标签)、Tag、Trigger(button,主元素)、Value、Clear、Chevron、Popover、\n * Search(TextField)、Listbox。\n */\nimport { ChevronDown, Plus, Search } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { useId, watch, type VNodeChild } from 'vue';\nimport type { PresetIconButtonProps } from '../base/CloseButton';\nimport { buttonBaseStyles } from '../base/button-core';\nimport { Icon, type IconProps } from '../base/Icon';\nimport type { TagProps } from '../base/Tag';\nimport { visuallyHiddenStyles } from '../base/VisuallyHidden';\nimport { useLang, useTextMatcher } from '../config/context';\nimport { useAnchoredPopover, type FloatingPlacement } from '../utils/dom/floating';\nimport { openSetter, type OpenChangeProps } from '../utils/dom/open-change';\nimport { ListPopover } from './ListPopover';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { selectedValues, type SelectionProps } from '../utils/data/selection';\nimport {\n controlClear,\n controlParts,\n clickOnShell,\n focusOnShell,\n controlIcon,\n useControlAppearance,\n type ControlIconOptions,\n type ControlOptions,\n} from './control';\nimport { useFieldControl } from '../form/Field';\nimport { FormValue } from '../form/FormValue';\nimport { disclosureStyles } from '../utils/style/transitions';\nimport { activeOptionId, type ListboxViewProps, type OptionRenderState } from './Listbox';\nimport {\n handleListKeydown,\n useListState,\n useResultAnnouncement,\n useSelectedOptions,\n type ListboxOption,\n type OptionMapping,\n toListboxOption,\n} from './list-state';\nimport { useRemoteItems, type OptionsLoader } from './remote-items';\nimport { SelectedTags, type SelectedTagsProps } from './SelectedTags';\nimport { TextField, type TextFieldProps } from './TextField';\n\n/** 角色、展开状态与可用性由组件管理 */\nexport type SelectManaged =\n | 'type'\n | 'role'\n | 'value'\n | 'disabled'\n | 'aria-haspopup'\n | 'aria-expanded'\n | 'aria-controls'\n | 'aria-activedescendant'\n | 'aria-invalid'\n | 'aria-required'\n | 'aria-describedby';\n\n/** 下拉选择共有的属性;未声明的属性落到触发按钮(主元素)上,外壳用 propsRoot */\nexport interface SelectBaseProps<T>\n extends PartProps<'button', SelectManaged>, ControlOptions, ControlIconOptions, OpenChangeProps {\n /** 数据:ListboxOption、字符串,或任意数据加 toOption;有 load 时是第一次加载之前的选项(编辑页放上已选的那一项) */\n items?: readonly T[];\n /** 没有选择时显示的文字,默认取语言包(请选择) */\n placeholder?: string;\n /** 是否打开:父级可以写 _open={x} */\n _open?: boolean;\n /** 弹出位置,默认 bottom-start */\n placement?: FloatingPlacement;\n /** 有选择时显示清空按钮 */\n clearable?: boolean;\n /** 弹出层顶部带搜索框,输入过滤选项:选项多(供应商、人员、件号)时用 */\n searchable?: boolean;\n /** 搜索时怎样算匹配;默认显示文字包含输入(忽略大小写与重音)。false 时不在本地过滤(服务端按 search 过滤) */\n filter?: false | ((item: T, query: string) => boolean);\n /** 搜索框里的文字:打开时清空;父级写 _search={x} 拿到它(自己发请求时) */\n _search?: string;\n /** 远程选项:打开时与搜索词停下 300 ms 后调用,结果代替 items;只采用最后一次,被顶掉的请求 signal 中止 */\n load?: OptionsLoader<T>;\n /**\n * 可以新建选项(自带搜索框):输入的文字没有对应的选项时,列表末尾多一项“新建“…””,选中后值就是这段文字。\n * 在 onCreate 里把它加进 items(或存到服务端);不加时触发框里照样显示这段文字\n */\n creatable?: boolean;\n /** 新建了一项(creatable 时):参数是输入的文字,也就是选中的值 */\n onCreate?: (text: string) => void;\n /** 多选时触发框里最多显示几个标签,其余收进“+N”;'responsive' 时排成一行、按宽度放,放不下的收起 */\n maxTagCount?: number | 'responsive';\n /** 表单提交时的 name(用隐藏的 input) */\n name?: string;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:能聚焦、能看到已选的内容,不能打开、不能清空 */\n readonly?: boolean;\n /** 必填 */\n required?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 自定义选项内容:`{(option, { selected, active }) => …}` */\n children?: (item: T, state: OptionRenderState) => VNodeChild;\n /** 自定义触发框里显示的内容(已选的选项);默认单选显示文字、多选显示标签 */\n renderValue?: (selected: readonly T[]) => VNodeChild;\n /** 正在取选项(异步加载):没有选项时列表里是骨架行,已有选项时顶部显示进度条 */\n loading?: boolean;\n /** 没有选项时列表里显示的内容 */\n empty?: VNodeChild;\n /** 外壳的部件属性 */\n propsRoot?: PartProps<'div'>;\n /** 已选内容那一层的部件属性 */\n propsValue?: PartProps<'span'>;\n /** 多选时每个标签的部件属性 */\n propsTag?: Partial<TagProps>;\n /** 多选时那排标签的部件属性 */\n propsTags?: Partial<SelectedTagsProps>;\n /** 清空按钮的部件属性 */\n propsClear?: Partial<PresetIconButtonProps>;\n /** 下拉箭头的部件属性 */\n propsChevron?: Partial<IconProps>;\n /** 弹出层的部件属性 */\n propsPopover?: PartProps<'div', 'id' | 'popover'>;\n /** 列表的部件属性 */\n propsListbox?: Partial<ListboxViewProps<T>>;\n /** 搜索框的部件属性(searchable 时) */\n propsSearch?: Partial<TextFieldProps>;\n}\n\n/** 单选或多选;items 不是 ListboxOption 或字符串时要给 toOption */\nexport type SelectProps<T = ListboxOption> = SelectBaseProps<T> & SelectionProps & OptionMapping<T>;\n\n/** Select 的样式:root、trigger、value、placeholder、chevronOpen 等 */\nexport const selectStyles = css.create({\n // 在 ControlGroup 里也按内容宽(输入框才分剩余宽度)\n root: { cursor: 'pointer', flexGrow: 0 },\n // 去掉按钮默认外观用 buttonBaseStyles;像输入框一样没有自己的焦点环与波纹(焦点环画在外壳上)\n trigger: {\n display: 'flex',\n alignItems: 'center',\n flexGrow: 1,\n minWidth: 0,\n alignSelf: 'stretch',\n textAlign: 'start',\n cursor: 'inherit',\n outlineStyle: 'none',\n },\n value: {\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n gap: '_xs',\n minWidth: 0,\n paddingBlock: '_xs',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n // 是真正的文字(不是原生 placeholder),要满足 4.5:1:用 textMuted 而不是 textPlaceholder\n placeholder: { color: '_textMuted' },\n // 多选时标签排在触发按钮前面(SelectedTags)占剩余宽度,触发按钮里只剩读屏用的文字\n triggerBehindTags: { flexGrow: 0 },\n chevronOpen: { rotate: '180deg' },\n // 弹出层顶部的搜索框占满宽度\n search: { width: '_full' },\n});\n\n/** creatable 时列表末尾那一项“新建“…””:不是 items 里的数据 */\nclass Creation {\n readonly text: string;\n constructor(text: string) {\n this.text = text;\n }\n}\n\n/** 下拉选择:触发框 + 弹出的选项列表 */\nexport const Select = _component(\n <T,>({\n items = [],\n toOption,\n selectionMode = 'single',\n _value: value = _bindable<string | string[] | null>(null),\n _open: open = _bindable(false),\n onOpenChange,\n placeholder,\n placement = 'bottom-start',\n clearable = false,\n searchable = false,\n filter,\n _search: search = _bindable(''),\n load,\n creatable = false,\n onCreate,\n maxTagCount,\n name,\n variant,\n size,\n radius,\n disabled,\n readonly,\n required,\n invalid,\n id,\n icon,\n children,\n renderValue,\n empty,\n loading = false,\n propsRoot,\n propsIcon,\n propsValue,\n propsTag,\n propsTags,\n propsClear,\n propsChevron,\n propsPopover,\n propsListbox,\n propsSearch,\n ...rest\n }: SelectProps<T>) => {\n const lang = useLang();\n const textMatcher = useTextMatcher();\n const listId = useId();\n const appearance = useControlAppearance(() => ({ variant, size, radius }));\n const control = useFieldControl(() => ({ id, invalid, required, disabled, readonly }));\n const multiple = () => selectionMode === 'multiple';\n const optionOf = (item: T) => toListboxOption(item, toOption);\n const remote = useRemoteItems({\n load: () => load,\n query: () => search,\n open: () => open,\n items: () => items,\n });\n // 本地过滤:有 load 或 filter={false} 时交给服务端\n const localFilter = () => !load && filter !== false;\n const matches = (item: T, text: string) =>\n filter ? filter(item, text) : textMatcher()(optionOf(item).label, text);\n // creatable 自带搜索框\n const withSearch = () => searchable || creatable;\n // creatable:输入的文字没有同名(或同值)的选项时,列表末尾多一项“新建”\n const creation = () => {\n const text = search.trim();\n if (!creatable || !text) return undefined;\n const exists = remote.items().some((item) => {\n const option = optionOf(item);\n return option.value === text || option.label.toLowerCase() === text.toLowerCase();\n });\n return exists ? undefined : new Creation(text);\n };\n const list = useListState<T | Creation>({\n items: () => {\n const all = remote.items();\n const shown =\n withSearch() && search && localFilter()\n ? all.filter((item) => matches(item, search))\n : all;\n const created = creation();\n return created ? [...shown, created] : shown;\n },\n toOption: (item) =>\n item instanceof Creation\n ? { value: item.text, label: lang.selectCreate(item.text), icon: Plus }\n : optionOf(item),\n selected: () => selectedValues(value),\n mode: () => selectionMode,\n onChange: (next) => {\n const created = creation();\n if (created && next.includes(created.text)) {\n onCreate?.(created.text);\n search = '';\n }\n value = multiple() ? [...next] : (next[0] ?? null);\n },\n // 单选时再点已选的一项不取消(同原生 select);要清空用清除按钮\n required: () => !multiple(),\n });\n // 已选项的文字取自全部 items(过滤掉的、远程搜索换掉的也在)\n const selectedOptions = useSelectedOptions({ items: remote.items, toOption: optionOf });\n let shell = _state.raw<HTMLElement | null>(null);\n let trigger = _state.raw<HTMLElement | null>(null);\n let panel = _state.raw<HTMLElement | null>(null);\n const setOpen = openSetter(\n () => open,\n (next) => (open = next),\n () => onOpenChange,\n );\n\n /** 多选时移除一项(标签的移除按钮、Backspace) */\n function remove(target: string) {\n value = selectedValues(value).filter((item) => item !== target);\n }\n\n function removeLast() {\n const last = selectedValues(value).at(-1);\n if (last !== undefined) remove(last);\n }\n\n function show(highlight: 'default' | 'last' = 'default', event?: Event) {\n search = '';\n list.activateDefault();\n if (highlight === 'last' && selectedValues(value).length === 0) list.move('last');\n setOpen(true, 'trigger', event);\n }\n\n useResultAnnouncement(() => ({ query: search, count: list.options.length }));\n\n // 输入搜索词:高亮第一个匹配的。打开时清空搜索词不算:那时高亮的是已选项\n watch(\n () => search,\n (text) => text && list.move('first'),\n );\n\n // 选中一项:单选时关闭\n function picked(event?: Event) {\n if (!multiple()) setOpen(false, 'select', event);\n }\n\n /** Ctrl / Cmd / Alt 组合键是浏览器的(刷新、复制、查找),不做按字母跳转 */\n const hasModifier = (event: KeyboardEvent) => event.altKey || event.ctrlKey || event.metaKey;\n\n function onKeydown(event: KeyboardEvent) {\n if (control().disabled || control().readonly) return;\n if (event.key === 'Backspace' && multiple()) {\n event.preventDefault();\n removeLast();\n return;\n }\n if (!open) {\n if (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n show('default', event);\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n show('last', event);\n } else if (!multiple() && !hasModifier(event) && list.typeahead(event.key)) {\n // 同原生 select:关闭时按字母直接选中\n event.preventDefault();\n if (list.active !== undefined && !list.isSelected(list.active)) list.select(list.active);\n }\n return;\n }\n if (event.key === 'Tab') {\n setOpen(false, 'focus', event);\n return;\n }\n if (handleListKeydown(list, event, { space: true, typeahead: true }, () => picked(event))) {\n event.preventDefault();\n }\n }\n\n // 搜索框里:↑↓ 移动、Enter 选中(Home / End、空格留给输入),Tab 关闭后照常移到下一个;\n // 多选时空的搜索框里按 Backspace 移除最后一项\n function onSearchKeydown(event: KeyboardEvent) {\n if (event.key === 'Tab') {\n setOpen(false, 'focus', event);\n return;\n }\n if (event.key === 'Backspace' && !search && multiple()) {\n event.preventDefault();\n removeLast();\n return;\n }\n if (handleListKeydown(list, event, { homeEnd: false }, () => picked(event)))\n event.preventDefault();\n }\n\n function clear() {\n value = multiple() ? [] : null;\n trigger?.focus();\n }\n\n // 弹层贴着外壳、与它同宽;焦点一直在触发按钮上,关闭时不用归还(searchable 时见 onPanelToggle)\n const { onToggle } = useAnchoredPopover(\n () => ({\n open,\n anchor: shell,\n panel,\n floating: { placement, matchWidth: true, fitHeight: true },\n restoreFocus: false,\n }),\n { close: (reason, event) => setOpen(false, reason, event) },\n );\n\n // searchable:打开后焦点进搜索框;关闭时焦点还在弹层里(Esc、选中、点外面)就还给触发按钮\n function onPanelToggle(event: ToggleEvent) {\n onToggle(event);\n if (!withSearch()) return;\n if (event.newState === 'open') {\n panel?.querySelector<HTMLInputElement>('input[type=\"search\"]')?.focus();\n return;\n }\n const active = document.activeElement;\n if (!active || active === document.body || panel?.contains(active)) trigger?.focus();\n }\n\n return () => {\n const state = control();\n const values = selectedValues(value);\n const selected = selectedOptions(values);\n const off = state.disabled;\n // 只读:能聚焦,不能打开、不能改\n const locked = off || state.readonly;\n // 多选的默认显示:触发按钮前面一排标签,按钮里只留给读屏的文字\n const tagged = multiple() && !renderValue && selected.length > 0;\n const shown = tagged ? (\n <span {...css.attrs(visuallyHiddenStyles.hidden)}>\n {lang.selectSummary(selected.map((option) => option.label))}\n </span>\n ) : (\n (renderValue?.(\n selected.flatMap((option) => (option.item === undefined ? [] : [option.item])),\n ) ??\n (selected.length === 0 ? (\n <span {...css.attrs(selectStyles.placeholder)}>\n {placeholder ?? lang.selectPlaceholder}\n </span>\n ) : (\n selected[0]!.label\n )))\n );\n const tags = tagged && (\n <SelectedTags\n {...mergePartProps<SelectedTagsProps>(\n {\n tags: selected,\n maxTagCount,\n onRemove: locked ? undefined : remove,\n propsTag,\n },\n propsTags,\n )}\n />\n );\n const s = controlParts(appearance(), state);\n return (\n <>\n <div\n {...mergeAttrs<'div'>({ ...s.root, sx: [s.root.sx, selectStyles.root] }, propsRoot, {\n ref: _toRef(shell),\n // 点在外壳空白处(含多选的标签):焦点交给触发按钮,并与点触发按钮一样切换打开(只读时只聚焦)\n onPointerdown: off ? undefined : focusOnShell(() => trigger),\n onClick: locked\n ? undefined\n : clickOnShell(\n () => trigger,\n (event) => (open ? setOpen(false, 'trigger', event) : show('default', event)),\n ),\n })}\n data-state={open ? 'open' : 'closed'}\n data-invalid={state.invalid || undefined}\n data-disabled={off || undefined}\n >\n {controlIcon(s, icon, propsIcon)}\n {tags}\n <button\n {...mergeAttrs<'button'>(\n {\n sx: [\n buttonBaseStyles.root,\n selectStyles.trigger,\n tagged && selectStyles.triggerBehindTags,\n ],\n },\n rest,\n {\n ref: _toRef(trigger),\n id: state.id,\n type: 'button',\n role: 'combobox',\n disabled: off,\n 'aria-haspopup': 'listbox',\n 'aria-expanded': open,\n 'aria-controls': listId,\n 'aria-activedescendant': open ? activeOptionId(list, listId) : undefined,\n 'aria-invalid': state.invalid || undefined,\n 'aria-required': state.required || undefined,\n 'aria-readonly': state.readonly || undefined,\n 'aria-describedby': state.describedBy,\n onClick: (event: MouseEvent) => {\n // Safari 点击按钮不会聚焦它:焦点要在触发按钮上,键盘与 aria-activedescendant 才有效\n trigger?.focus();\n if (locked) return;\n if (open) setOpen(false, 'trigger', event);\n else show('default', event);\n },\n onKeydown,\n },\n )}\n >\n <span {...mergeAttrs<'span'>({ sx: selectStyles.value }, propsValue)}>{shown}</span>\n </button>\n {clearable && values.length > 0 && !locked && controlClear(s, propsClear, clear)}\n <Icon\n {...mergePartProps<IconProps>(\n {\n ...s.icon,\n icon: ChevronDown,\n sx: [s.icon.sx, disclosureStyles.icon, open && selectStyles.chevronOpen],\n },\n propsChevron,\n )}\n />\n <FormValue name={name} value={values} disabled={state.disabled} />\n </div>\n <ListPopover\n panelRef={_toRef(panel)}\n onToggle={onPanelToggle}\n size={appearance().size}\n labelledBy={state.labelledBy}\n label={rest['aria-label']}\n loading={loading || remote.loading()}\n onPick={() => picked()}\n header={\n withSearch() && (\n <TextField\n {...mergePartProps<TextFieldProps>(\n {\n icon: Search,\n variant: 'soft',\n placeholder: lang.selectSearch,\n 'aria-label': lang.selectSearch,\n propsRoot: { sx: selectStyles.search },\n },\n propsSearch,\n )}\n type=\"search\"\n _value={search}\n aria-controls={listId}\n aria-activedescendant={open ? activeOptionId(list, listId) : undefined}\n onKeydown={onSearchKeydown}\n />\n )\n }\n listbox={{\n list,\n id: listId,\n empty: remote.failure() ?? (search ? lang.selectNoMatch : empty),\n renderOption:\n children &&\n ((item: T | Creation, state: OptionRenderState) =>\n item instanceof Creation ? lang.selectCreate(item.text) : children(item, state)),\n multiple: multiple(),\n }}\n // 使用方按 T 写列表的部件属性;creatable 时多出的“新建”那一项由上面的 renderOption 处理\n propsListbox={propsListbox as Partial<ListboxViewProps<T | Creation>> | undefined}\n propsPopover={propsPopover}\n />\n </>\n );\n };\n },\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoKA,IAAa,eAAe,IAAI,OAAO;CAErC,MAAM;EAAE,QAAQ;EAAW,UAAU;CAAE;CAEvC,SAAS;EACP,SAAS;EACT,YAAY;EACZ,UAAU;EACV,UAAU;EACV,WAAW;EACX,WAAW;EACX,QAAQ;EACR,cAAc;CAChB;CACA,OAAO;EACL,SAAS;EACT,UAAU;EACV,YAAY;EACZ,KAAK;EACL,UAAU;EACV,cAAc;EACd,UAAU;EACV,cAAc;EACd,YAAY;CACd;CAEA,aAAa,EAAE,OAAO,aAAa;CAEnC,mBAAmB,EAAE,UAAU,EAAE;CACjC,aAAa,EAAE,QAAQ,SAAS;CAEhC,QAAQ,EAAE,OAAO,QAAQ;AAC3B,CAAC;;AAGD,IAAM,WAAN,MAAe;CACJ;CACT,YAAY,MAAc;EACxB,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,SAAS,0BACpB,QAAA,SA0CsB;CAAA,MAAA,SAAA,CAAA;CAAA,MAAA,QAAAA,aAAA,QAAA,eAzCZ,CAAA,CAAE;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,gBAAAA,aAAA,QAAA,iBAEM,QAAQ;CAAA,MAAA,QAAAC,SAAA,QAAA,gBAC4B,MAAI,KAAA,IAAA;CAAA,MAAA,OAAAA,SAAA,QAAA,eAChC,OAAK,KAAA,IAAA;CAAA,MAAA,eAAAD,aAAA,QAAA,cAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,YAAAA,aAAA,QAAA,aAGjB,cAAc;CAAA,MAAA,YAAAA,aAAA,QAAA,aACd,KAAK;CAAA,MAAA,aAAAA,aAAA,QAAA,cACJ,KAAK;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,SAAAC,SAAA,QAAA,iBAEU,IAAE,KAAA,IAAA;CAAA,MAAA,OAAAD,aAAA,QAAA,MAAA;CAAA,MAAA,YAAAA,aAAA,QAAA,aAElB,KAAK;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,OAAAA,aAAA,QAAA,MAAA;CAAA,MAAA,UAAAA,aAAA,QAAA,SAAA;CAAA,MAAA,OAAAA,aAAA,QAAA,MAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,UAAAA,aAAA,QAAA,SAAA;CAAA,MAAA,KAAAA,aAAA,QAAA,IAAA;CAAA,MAAA,OAAAA,aAAA,QAAA,MAAA;CAAA,MAAA,WAAAE,aAAA,MAAA;CAAA,MAAA,cAAAF,aAAA,QAAA,aAAA;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,UAAAA,aAAA,QAAA,WAgBP,KAAK;CAAA,MAAA,YAAAA,aAAA,QAAA,WAAA;CAAA,MAAA,YAAAA,aAAA,QAAA,WAAA;CAAA,MAAA,aAAAA,aAAA,QAAA,YAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,YAAAA,aAAA,QAAA,WAAA;CAAA,MAAA,aAAAA,aAAA,QAAA,YAAA;CAAA,MAAA,eAAAA,aAAA,QAAA,cAAA;CAAA,MAAA,eAAAA,aAAA,QAAA,cAAA;CAAA,MAAA,eAAAA,aAAA,QAAA,cAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAWZ,OAAIG,UAAA,QAAA,MAAA,KAAA;CAEP,MAAM,OAAO,QAAQ;CACrB,MAAM,cAAc,eAAe;CACnC,MAAM,SAAS,MAAM;CACrB,MAAM,aAAa,4BAA4B;EAAE,SAAO,QAAA;EAAE,MAAI,KAAA;EAAE,QAAM,OAAA;CAAC,EAAE;CACzE,MAAM,UAAU,uBAAuB;EAAE,IAAE,GAAA;EAAE,SAAO,QAAA;EAAE,UAAQ,SAAA;EAAE,UAAQ,SAAA;EAAE,UAAQ,SAAA;CAAC,EAAE;CACrF,MAAM,iBAAiB,cAAA,UAAkB;CACzC,MAAM,YAAY,SAAY,gBAAgB,MAAI,SAAA,KAAU;CAC5D,MAAM,SAAS,eAAe;EAC5B,YAAM,KAAA;EACN,aAAO,OAAA;EACP,YAAM,KAAA;EACN,aAAO,MAAA;CACT,CAAC;CAED,MAAM,oBAAoB,CAAA,KAAA,SAAS,OAAA,UAAW;CAC9C,MAAM,WAAW,MAAS,SACxB,OAAA,QAAS,OAAA,MAAO,MAAM,IAAI,IAAI,YAAY,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,OAAO,IAAI;CAExE,MAAM,mBAAmB,WAAA,SAAA,UAAA;CAEzB,MAAM,iBAAiB;EACrB,MAAM,OAAO,OAAA,MAAO,KAAK;EACzB,IAAI,CAAA,UAAA,SAAc,CAAC,MAAM,OAAO,KAAA;EAKhC,OAJe,OAAO,MAAM,CAAC,CAAC,MAAM,SAAS;GAC3C,MAAM,SAAS,SAAS,IAAI;GAC5B,OAAO,OAAO,UAAU,QAAQ,OAAO,MAAM,YAAY,MAAM,KAAK,YAAY;EAClF,CACO,IAAS,KAAA,IAAY,IAAI,SAAS,IAAI;CAC/C;CACA,MAAM,OAAO,aAA2B;EACtC,aAAa;GACX,MAAM,MAAM,OAAO,MAAM;GACzB,MAAM,QACJ,WAAW,KAAC,OAAA,SAAc,YAAY,IAClC,IAAI,QAAQ,SAAS,QAAQ,MAAI,OAAA,KAAQ,CAAC,IAC1C;GACN,MAAM,UAAU,SAAS;GACzB,OAAO,UAAU,CAAC,GAAG,OAAO,OAAO,IAAI;EACzC;EACA,WAAW,SACT,gBAAgB,WACZ;GAAE,OAAO,KAAK;GAAM,OAAO,KAAK,aAAa,KAAK,IAAI;GAAG,MAAM;EAAK,IACpE,SAAS,IAAI;EACnB,gBAAgB,eAAc,MAAA,KAAM;EACpC,YAAM,cAAA;EACN,WAAW,SAAS;GAClB,MAAM,UAAU,SAAS;GACzB,IAAI,WAAW,KAAK,SAAS,QAAQ,IAAI,GAAG;IAC1C,SAAA,QAAW,QAAQ,IAAI;IACvB,OAAA,QAAS;GACX;GACA,MAAA,QAAQ,SAAS,IAAI,CAAC,GAAG,IAAI,IAAK,KAAK,MAAM;EAC/C;EAEA,gBAAgB,CAAC,SAAS;CAC5B,CAAC;CAED,MAAM,kBAAkB,mBAAmB;EAAE,OAAO,OAAO;EAAO,UAAU;CAAS,CAAC;CACtF,IAAI,QAAKC,WAAkC,IAAI;CAC/C,IAAI,UAAOA,WAAkC,IAAI;CACjD,IAAI,QAAKA,WAAkC,IAAI;CAC/C,MAAM,UAAU,iBACd,KAAA,QACC,SAAU,KAAA,QAAO,YAClB,aAAA,KACF;;CAGA,SAAS,OAAO,QAAgB;EAC9B,MAAA,QAAQ,eAAc,MAAA,KAAM,CAAC,CAAC,QAAQ,SAAS,SAAS,MAAM;CAChE;CAEA,SAAS,aAAa;EACpB,MAAM,OAAO,eAAc,MAAA,KAAM,CAAC,CAAC,GAAG,EAAE;EACxC,IAAI,SAAS,KAAA,GAAW,OAAO,IAAI;CACrC;CAEA,SAAS,KAAK,YAAgC,WAAW,OAAe;EACtE,OAAA,QAAS;EACT,KAAK,gBAAgB;EACrB,IAAI,cAAc,UAAU,eAAc,MAAA,KAAM,CAAC,CAAC,WAAW,GAAG,KAAK,KAAK,MAAM;EAChF,QAAQ,MAAM,WAAW,KAAK;CAChC;CAEA,6BAA6B;EAAE,OAAK,OAAA;EAAU,OAAO,KAAK,QAAQ;CAAO,EAAE;CAG3E,YACE,OAAA,QACC,SAAS,QAAQ,KAAK,KAAK,OAAO,CACrC;CAGA,SAAS,OAAO,OAAe;EAC7B,IAAI,CAAC,SAAS,GAAG,QAAQ,OAAO,UAAU,KAAK;CACjD;;CAGA,MAAM,eAAe,UAAyB,MAAM,UAAU,MAAM,WAAW,MAAM;CAErF,SAAS,UAAU,OAAsB;EACvC,IAAI,QAAQ,CAAC,CAAC,YAAY,QAAQ,CAAC,CAAC,UAAU;EAC9C,IAAI,MAAM,QAAQ,eAAe,SAAS,GAAG;GAC3C,MAAM,eAAe;GACrB,WAAW;GACX;EACF;EACA,IAAI,CAAA,KAAA,OAAO;GACT,IAAI,MAAM,QAAQ,eAAe,MAAM,QAAQ,WAAW,MAAM,QAAQ,KAAK;IAC3E,MAAM,eAAe;IACrB,KAAK,WAAW,KAAK;GACvB,OAAO,IAAI,MAAM,QAAQ,WAAW;IAClC,MAAM,eAAe;IACrB,KAAK,QAAQ,KAAK;GACpB,OAAO,IAAI,CAAC,SAAS,KAAK,CAAC,YAAY,KAAK,KAAK,KAAK,UAAU,MAAM,GAAG,GAAG;IAE1E,MAAM,eAAe;IACrB,IAAI,KAAK,WAAW,KAAA,KAAa,CAAC,KAAK,WAAW,KAAK,MAAM,GAAG,KAAK,OAAO,KAAK,MAAM;GACzF;GACA;EACF;EACA,IAAI,MAAM,QAAQ,OAAO;GACvB,QAAQ,OAAO,SAAS,KAAK;GAC7B;EACF;EACA,IAAI,kBAAkB,MAAM,OAAO;GAAE,OAAO;GAAM,WAAW;EAAK,SAAS,OAAO,KAAK,CAAC,GACtF,MAAM,eAAe;CAEzB;CAIA,SAAS,gBAAgB,OAAsB;EAC7C,IAAI,MAAM,QAAQ,OAAO;GACvB,QAAQ,OAAO,SAAS,KAAK;GAC7B;EACF;EACA,IAAI,MAAM,QAAQ,eAAe,CAAA,OAAA,SAAW,SAAS,GAAG;GACtD,MAAM,eAAe;GACrB,WAAW;GACX;EACF;EACA,IAAI,kBAAkB,MAAM,OAAO,EAAE,SAAS,MAAM,SAAS,OAAO,KAAK,CAAC,GACxE,MAAM,eAAe;CACzB;CAEA,SAAS,QAAQ;EACf,MAAA,QAAQ,SAAS,IAAI,CAAA,IAAK;EAC1B,QAAA,OAAS,MAAM;CACjB;CAGA,MAAM,EAAE,aAAa,0BACZ;EACL,MAAI,KAAA;EACJ,QAAM,MAAA;EACN,OAAK,MAAA;EACL,UAAU;GAAE,WAAS,UAAA;GAAE,YAAY;GAAM,WAAW;EAAK;EACzD,cAAc;CAChB,IACA,EAAE,QAAQ,QAAQ,UAAU,QAAQ,OAAO,QAAQ,KAAK,EAAE,CAC5D;CAGA,SAAS,cAAc,OAAoB;EACzC,SAAS,KAAK;EACd,IAAI,CAAC,WAAW,GAAG;EACnB,IAAI,MAAM,aAAa,QAAQ;GAC7B,MAAA,OAAO,cAAgC,wBAAsB,CAAC,EAAE,MAAM;GACtE;EACF;EACA,MAAM,SAAS,SAAS;EACxB,IAAI,CAAC,UAAU,WAAW,SAAS,QAAQ,MAAA,OAAO,SAAS,MAAM,GAAG,QAAA,OAAS,MAAM;CACrF;CAEA,aAAa;EACX,MAAM,QAAQ,QAAQ;EACtB,MAAM,SAAS,eAAc,MAAA,KAAM;EACnC,MAAM,WAAW,gBAAgB,MAAM;EACvC,MAAM,MAAM,MAAM;EAElB,MAAM,SAAS,OAAO,MAAM;EAE5B,MAAM,SAAS,SAAS,KAAK,CAAA,YAAA,SAAgB,SAAS,SAAS;EAC/D,MAAM,QAAQ,SAAMC,YAAA,QACR,IAAI,MAAM,qBAAqB,MAAM,GAAC,CAC7C,KAAK,cAAc,SAAS,KAAK,WAAW,OAAO,KAAK,CAAC,CAAC,CAAA,IAG5D,YAAA,QACC,SAAS,SAAS,WAAY,OAAO,SAAS,KAAA,IAAY,CAAA,IAAK,CAAC,OAAO,IAAI,CAAE,CAC/E,MACC,SAAS,WAAW,IAACA,YAAA,QACV,IAAI,MAAM,aAAa,WAAW,GAAC,CAC1C,YAAA,SAAe,KAAK,iBAAiB,CAAA,IAGxC,SAAS,EAAE,CAAE;EAGjB,MAAM,OAAO,UAAMA,YAAA,cAEX,eACF;GACE,MAAM;GACN,aAAW,YAAA;GACX,UAAU,SAAS,KAAA,IAAY;GAC/B,UAAQ,SAAA;EACV,GAAC,UAAA,KAEH,GAAC,IAAA;EAGL,MAAM,IAAI,aAAa,WAAW,GAAG,KAAK;EAC1C,OAAAA,YAAAC,UAAA,MAAA,CAAAD,YAAA,OAAAE,cAGU,WAAkB;GAAE,GAAG,EAAE;GAAM,IAAI,CAAC,EAAE,KAAK,IAAI,aAAa,IAAI;EAAE,GAAC,UAAA,OAAa;GAClF,KAAG;GAEH,eAAe,MAAM,KAAA,IAAY,mBAAa,QAAA,KAAa;GAC3D,SAAS,SACL,KAAA,IACA,mBACE,QAAA,QACC,UAAW,KAAA,QAAO,QAAQ,OAAO,WAAW,KAAK,IAAI,KAAK,WAAW,KAAK,CAC7E;EACN,CAAC,GAAC;GAAA,cACU,KAAA,QAAO,SAAS;GAAQ,gBACtB,MAAM,WAAW,KAAA;GAAS,iBACzB,OAAO,KAAA;EAAS,CAAA,GAAA;GAE9B,YAAY,GAAC,KAAA,OAAA,UAAA,KAAiB;GAC9B;GAAIF,YAAA,UAEC,WACF,EACE,IAAI;IACF,iBAAiB;IACjB,aAAa;IACb,UAAU,aAAa;GAAiB,EAE5C,GACA,MACA;IACE,KAAG;IACH,IAAI,MAAM;IACV,MAAM;IACN,MAAM;IACN,UAAU;IACV,iBAAiB;IACjB,iBAAe,KAAA;IACf,iBAAiB;IACjB,yBAAyB,KAAA,QAAO,eAAe,MAAM,MAAM,IAAI,KAAA;IAC/D,gBAAgB,MAAM,WAAW,KAAA;IACjC,iBAAiB,MAAM,YAAY,KAAA;IACnC,iBAAiB,MAAM,YAAY,KAAA;IACnC,oBAAoB,MAAM;IAC1B,UAAU,UAAsB;KAE9B,QAAA,OAAS,MAAM;KACf,IAAI,QAAQ;KACZ,IAAA,KAAA,OAAU,QAAQ,OAAO,WAAW,KAAK;UACpC,KAAK,WAAW,KAAK;IAC5B;IACA;GACF,CACF,GAAC,CAAAA,YAAA,QAES,WAAmB,EAAE,IAAI,aAAa,MAAM,GAAC,WAAA,KAAY,GAAC,CAAG,KAAK,CAAA,CAAA,CAAA;GAE7E,UAAA,SAAa,OAAO,SAAS,KAAK,CAAC,UAAU,aAAa,GAAC,WAAA,OAAc,KAAK;GAACA,YAAA,MAE1E,eACF;IACE,GAAG,EAAE;IACL,MAAM;IACN,IAAI;KAAC,EAAE,KAAK;KAAI,iBAAiB;KAAM,KAAA,SAAQ,aAAa;IAAW;GACzE,GAAC,aAAA,KAEH,GAAC,IAAA;GAAAA,YAAA,WAAA;IAAA,QAAA,KAAA;IAAA,SAE2B;IAAM,YAAY,MAAM;GAAQ,GAAA,IAAA;EAAA,CAAA,GAAAA,YAAA,aAAA;GAAA,YAAA;GAAA,YAIpD;GAAa,QACjB,WAAW,CAAC,CAAC;GAAI,cACX,MAAM;GAAU,SACrB,KAAK;GAAa,WAChB,QAAA,SAAW,OAAO,QAAQ;GAAC,UAAA,OAAA,OAAA,OAAA,WACtB,OAAO;GAAC,UAEpB,WAAW,KAACA,YAAA,WAAAE,cAEJ,eACF;IACE,MAAM;IACN,SAAS;IACT,aAAa,KAAK;IAClB,cAAc,KAAK;IACnB,WAAW,EAAE,IAAI,aAAa,OAAO;GACvC,GAAC,YAAA,KAEH,GAAC;IAAA,QAAA;IAAA,UAAA,OAAA;IAAA,mBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,OAAA,QAAA;IAAA,iBAGc;IAAM,yBACE,KAAA,QAAO,eAAe,MAAM,MAAM,IAAI,KAAA;IAAS,aAC3D;GAAe,CAAA,GAAA,IAAA;GAE7B,WAEM;IACP;IACA,IAAI;IACJ,OAAO,OAAO,QAAQ,MAAM,OAAA,QAAS,KAAK,gBAAa,MAAA;IACvD,cACE,SAAA,WACE,MAAoB,UACpB,gBAAgB,WAAW,KAAK,aAAa,KAAK,IAAI,IAAI,SAAA,MAAS,MAAM,KAAK;IAClF,UAAU,SAAS;GACrB;GAAC,gBAAA,aAAA;GAAA,gBAAA,aAAA;EAAA,GAAA,IAAA,CAAA,CAAA;CAOT;AACF,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
@@ -2,8 +2,8 @@ import { useLang } from "../config/context.js";
2
2
  import { mergeAttrs, mergePartProps } from "../utils/props.js";
3
3
  import { Tag } from "../base/Tag.js";
4
4
  import { useOverflowItems } from "../utils/dom/overflow.js";
5
- import { createVNode, isVNode, mergeProps, shallowRef } from "vue";
6
- import { _component, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
5
+ import { createVNode, isVNode, shallowRef } from "vue";
6
+ import { _component, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
7
7
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
8
8
  //#region src/input/SelectedTags.tsx
9
9
  /** 一个已选的标签 */
@@ -53,7 +53,7 @@ var SelectedTags = /*#__PURE__*/ _component((_props, _ctx) => {
53
53
  return createVNode("span", mergeAttrs({ sx: [selectedTagsStyles.root, responsive && selectedTagsStyles.line] }, rest, {
54
54
  ref: row,
55
55
  "aria-hidden": "true"
56
- }), [shown.map((tag, index) => createVNode(Tag, mergeProps({ "key": tag.value }, mergePartProps({
56
+ }), [shown.map((tag, index) => createVNode(Tag, mergeJsxProps({ "key": tag.value }, mergePartProps({
57
57
  size: "sm",
58
58
  variant: "soft",
59
59
  onRemove: onRemove.value && (() => onRemove.value(tag.value)),
@@ -61,7 +61,7 @@ var SelectedTags = /*#__PURE__*/ _component((_props, _ctx) => {
61
61
  tabindex: -1,
62
62
  onPointerdown: keepFocus
63
63
  }
64
- }, propsTag.value), responsive ? overflow.itemProps(index) : {}), { default: () => [tag.label] })), (responsive || hiddenCount > 0) && createVNode(Tag, mergeProps({
64
+ }, propsTag.value), responsive ? overflow.itemProps(index) : {}), { default: () => [tag.label] })), (responsive || hiddenCount > 0) && createVNode(Tag, mergeJsxProps({
65
65
  "size": "sm",
66
66
  "variant": "soft"
67
67
  }, responsive ? overflow.restProps() : {}), _isSlot(_slot = lang.selectMoreTags(hiddenCount)) ? _slot : { default: () => [_slot] })]);
@@ -1 +1 @@
1
- {"version":3,"file":"SelectedTags.js","names":["_isVNode","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../src/input/SelectedTags.tsx"],"sourcesContent":["/**\n * 多选下拉的触发按钮前面那一排已选标签:Select、TreeSelect 共用。\n *\n * <SelectedTags tags={selected} maxTagCount=\"responsive\" onRemove={(value) => remove(value)} />\n *\n * 标签不能放进触发按钮里(按钮里不能有按钮),所以排在它前面。这排标签只给指针用:aria-hidden、移除按钮不进 Tab 顺序、\n * 按下时不抢焦点;读屏从触发按钮里念全部已选(lang.selectSummary),键盘在列表里取消勾选,或在触发按钮上按 Backspace。\n * maxTagCount 是数字时只显示前几个,'responsive' 时排成一行按宽度放(useOverflowItems),其余收进“+N”。\n * 未声明的属性落到这一排的 span 上。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { Tag, type TagProps } from '../base/Tag';\nimport { useLang } from '../config/context';\nimport { useOverflowItems } from '../utils/dom/overflow';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\n\n/** 一个已选的标签 */\nexport interface SelectedTag {\n /** 值:移除时交给 onRemove */\n value: string;\n /** 显示的文字 */\n label: string;\n}\n\n/** 未声明的属性落到这一排的 span 上 */\nexport interface SelectedTagsProps extends PartProps<'span', 'aria-hidden'> {\n /** 要显示的标签 */\n tags: readonly SelectedTag[];\n /** 最多显示几个,其余收进“+N”;'responsive' 时排成一行、按宽度放 */\n maxTagCount?: number | 'responsive';\n /** 点标签的移除按钮;不写时(只读、不可用)标签没有移除按钮 */\n onRemove?: (value: string) => void;\n /** 每个标签的部件属性 */\n propsTag?: Partial<TagProps>;\n}\n\n/** SelectedTags 的样式:root、line */\nexport const selectedTagsStyles = css.create({\n // 占触发框里剩下的宽度;触发按钮里只剩读屏用的文字\n root: {\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n gap: '_xs',\n flexGrow: 1,\n minWidth: 0,\n paddingBlock: '_xs',\n },\n // responsive:一行,放不下的移出排版(useOverflowItems 要求容器 position: relative);\n // contain: inline-size 让这一行不按内容撑宽外壳(不然按内容宽度排版的祖先会被整行标签撑开,永远“放得下”)\n line: { flexWrap: 'nowrap', position: 'relative', overflow: 'hidden', contain: 'inline-size' },\n});\n\n/** 移除按钮按下时不抢焦点:焦点留在触发按钮上 */\nconst keepFocus = (event: PointerEvent) => event.preventDefault();\n\n/** 多选下拉的已选标签:可移除,可按数量或宽度收起 */\nexport const SelectedTags = _component(\n ({ tags, maxTagCount, onRemove, propsTag, ...rest }: SelectedTagsProps) => {\n const lang = useLang();\n let row = _state.raw<HTMLElement | null>(null);\n const overflow = useOverflowItems({\n container: () => (maxTagCount === 'responsive' ? row : null),\n count: () => tags.length,\n min: () => 1,\n });\n return () => {\n const responsive = maxTagCount === 'responsive';\n const shown =\n typeof maxTagCount === 'number' ? tags.slice(0, Math.max(0, maxTagCount)) : tags;\n const hiddenCount = responsive ? overflow.hidden : tags.length - shown.length;\n return (\n <span\n {...mergeAttrs<'span'>(\n { sx: [selectedTagsStyles.root, responsive && selectedTagsStyles.line] },\n rest,\n { ref: _toRef(row), 'aria-hidden': 'true' },\n )}\n >\n {shown.map((tag, index) => (\n <Tag\n key={tag.value}\n {...mergePartProps<TagProps>(\n {\n size: 'sm',\n variant: 'soft',\n onRemove: onRemove && (() => onRemove(tag.value)),\n propsRemove: { tabindex: -1, onPointerdown: keepFocus },\n },\n propsTag,\n )}\n {...(responsive ? overflow.itemProps(index) : {})}\n >\n {tag.label}\n </Tag>\n ))}\n {/* responsive 时“+N”一直在(没有折起的项时藏起来,但仍要量它的宽度) */}\n {(responsive || hiddenCount > 0) && (\n <Tag size=\"sm\" variant=\"soft\" {...(responsive ? overflow.restProps() : {})}>\n {lang.selectMoreTags(hiddenCount)}\n </Tag>\n )}\n </span>\n );\n };\n },\n);\n"],"mappings":";;;;;;;;;;AAyBA,SAAA,QAAA,GAAA;CAAA,OAAA,OAAA,MAAA,cAAA,OAAA,UAAA,SAAA,KAAA,CAAA,MAAA,qBAAA,CAAAA,QAAA,CAAA;AAAA;;AAaA,IAAa,qBAAqB,IAAI,OAAO;CAE3C,MAAM;EACJ,SAAS;EACT,UAAU;EACV,YAAY;EACZ,KAAK;EACL,UAAU;EACV,UAAU;EACV,cAAc;CAChB;CAGA,MAAM;EAAE,UAAU;EAAU,UAAU;EAAY,UAAU;EAAU,SAAS;CAAc;AAC/F,CAAC;;AAGD,IAAM,aAAa,UAAwB,MAAM,eAAe;;AAGhE,IAAa,eAAe,0BAC1B,QAAA,SAA2E;CAAA,MAAA,OAAAC,aAAA,QAAA,MAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAA9B,OAAIC,UAAA,QAAA,MAAA,IAAA;CAC/C,MAAM,OAAO,QAAQ;CACrB,IAAI,MAAGC,WAAkC,IAAI;CAC7C,MAAM,WAAW,iBAAiB;EAChC,iBAAkB,YAAA,UAAgB,eAAY,IAAA,QAAS;EACvD,aAAa,KAAA,MAAK;EAClB,WAAW;CACb,CAAC;CACD,aAAa;EAAA,IAAA;EACX,MAAM,aAAa,YAAA,UAAgB;EACnC,MAAM,QACJ,OAAA,YAAA,UAAuB,WAAW,KAAA,MAAK,MAAM,GAAG,KAAK,IAAI,GAAC,YAAA,KAAa,CAAC,IAAC,KAAA;EAC3E,MAAM,cAAc,aAAa,SAAS,SAAS,KAAA,MAAK,SAAS,MAAM;EACvE,OAAAC,YAAA,QAEQ,WACF,EAAE,IAAI,CAAC,mBAAmB,MAAM,cAAc,mBAAmB,IAAI,EAAE,GACvE,MACA;GAAE,KAAG;GAAe,eAAe;EAAO,CAC5C,GAAC,CAEA,MAAM,KAAK,KAAK,UAAKA,YAAA,KAAAC,WAAA,EAAA,OAEb,IAAI,MAAK,GACV,eACF;GACE,MAAM;GACN,SAAS;GACT,UAAU,SAAA,gBAAmB,SAAA,MAAS,IAAI,KAAK;GAC/C,aAAa;IAAE,UAAU;IAAI,eAAe;GAAU;EACxD,GAAC,SAAA,KAEH,GACK,aAAa,SAAS,UAAU,KAAK,IAAI,CAAC,CAAC,GAAA,EAAA,eAAA,CAE/C,IAAI,KAAK,EAAA,CAAA,CAEb,IAEC,cAAc,cAAc,MAACD,YAAA,KAAAC,WAAA;GAAA,QAAA;GAAA,WAAA;EAAA,GACM,aAAa,SAAS,UAAU,IAAI,CAAC,CAAC,GAAA,QAAA,QACtE,KAAK,eAAe,WAAW,CAAC,IAAA,QAAA,EAAA,eAAA,CAAA,KAAA,EAAA,CAAA,CAEpC,CAAA;CAGP;AACF,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
1
+ {"version":3,"file":"SelectedTags.js","names":["_isVNode","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../src/input/SelectedTags.tsx"],"sourcesContent":["/**\n * 多选下拉的触发按钮前面那一排已选标签:Select、TreeSelect 共用。\n *\n * <SelectedTags tags={selected} maxTagCount=\"responsive\" onRemove={(value) => remove(value)} />\n *\n * 标签不能放进触发按钮里(按钮里不能有按钮),所以排在它前面。这排标签只给指针用:aria-hidden、移除按钮不进 Tab 顺序、\n * 按下时不抢焦点;读屏从触发按钮里念全部已选(lang.selectSummary),键盘在列表里取消勾选,或在触发按钮上按 Backspace。\n * maxTagCount 是数字时只显示前几个,'responsive' 时排成一行按宽度放(useOverflowItems),其余收进“+N”。\n * 未声明的属性落到这一排的 span 上。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { Tag, type TagProps } from '../base/Tag';\nimport { useLang } from '../config/context';\nimport { useOverflowItems } from '../utils/dom/overflow';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\n\n/** 一个已选的标签 */\nexport interface SelectedTag {\n /** 值:移除时交给 onRemove */\n value: string;\n /** 显示的文字 */\n label: string;\n}\n\n/** 未声明的属性落到这一排的 span 上 */\nexport interface SelectedTagsProps extends PartProps<'span', 'aria-hidden'> {\n /** 要显示的标签 */\n tags: readonly SelectedTag[];\n /** 最多显示几个,其余收进“+N”;'responsive' 时排成一行、按宽度放 */\n maxTagCount?: number | 'responsive';\n /** 点标签的移除按钮;不写时(只读、不可用)标签没有移除按钮 */\n onRemove?: (value: string) => void;\n /** 每个标签的部件属性 */\n propsTag?: Partial<TagProps>;\n}\n\n/** SelectedTags 的样式:root、line */\nexport const selectedTagsStyles = css.create({\n // 占触发框里剩下的宽度;触发按钮里只剩读屏用的文字\n root: {\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n gap: '_xs',\n flexGrow: 1,\n minWidth: 0,\n paddingBlock: '_xs',\n },\n // responsive:一行,放不下的移出排版(useOverflowItems 要求容器 position: relative);\n // contain: inline-size 让这一行不按内容撑宽外壳(不然按内容宽度排版的祖先会被整行标签撑开,永远“放得下”)\n line: { flexWrap: 'nowrap', position: 'relative', overflow: 'hidden', contain: 'inline-size' },\n});\n\n/** 移除按钮按下时不抢焦点:焦点留在触发按钮上 */\nconst keepFocus = (event: PointerEvent) => event.preventDefault();\n\n/** 多选下拉的已选标签:可移除,可按数量或宽度收起 */\nexport const SelectedTags = _component(\n ({ tags, maxTagCount, onRemove, propsTag, ...rest }: SelectedTagsProps) => {\n const lang = useLang();\n let row = _state.raw<HTMLElement | null>(null);\n const overflow = useOverflowItems({\n container: () => (maxTagCount === 'responsive' ? row : null),\n count: () => tags.length,\n min: () => 1,\n });\n return () => {\n const responsive = maxTagCount === 'responsive';\n const shown =\n typeof maxTagCount === 'number' ? tags.slice(0, Math.max(0, maxTagCount)) : tags;\n const hiddenCount = responsive ? overflow.hidden : tags.length - shown.length;\n return (\n <span\n {...mergeAttrs<'span'>(\n { sx: [selectedTagsStyles.root, responsive && selectedTagsStyles.line] },\n rest,\n { ref: _toRef(row), 'aria-hidden': 'true' },\n )}\n >\n {shown.map((tag, index) => (\n <Tag\n key={tag.value}\n {...mergePartProps<TagProps>(\n {\n size: 'sm',\n variant: 'soft',\n onRemove: onRemove && (() => onRemove(tag.value)),\n propsRemove: { tabindex: -1, onPointerdown: keepFocus },\n },\n propsTag,\n )}\n {...(responsive ? overflow.itemProps(index) : {})}\n >\n {tag.label}\n </Tag>\n ))}\n {/* responsive 时“+N”一直在(没有折起的项时藏起来,但仍要量它的宽度) */}\n {(responsive || hiddenCount > 0) && (\n <Tag size=\"sm\" variant=\"soft\" {...(responsive ? overflow.restProps() : {})}>\n {lang.selectMoreTags(hiddenCount)}\n </Tag>\n )}\n </span>\n );\n };\n },\n);\n"],"mappings":";;;;;;;;;;AAyBA,SAAA,QAAA,GAAA;CAAA,OAAA,OAAA,MAAA,cAAA,OAAA,UAAA,SAAA,KAAA,CAAA,MAAA,qBAAA,CAAAA,QAAA,CAAA;AAAA;;AAaA,IAAa,qBAAqB,IAAI,OAAO;CAE3C,MAAM;EACJ,SAAS;EACT,UAAU;EACV,YAAY;EACZ,KAAK;EACL,UAAU;EACV,UAAU;EACV,cAAc;CAChB;CAGA,MAAM;EAAE,UAAU;EAAU,UAAU;EAAY,UAAU;EAAU,SAAS;CAAc;AAC/F,CAAC;;AAGD,IAAM,aAAa,UAAwB,MAAM,eAAe;;AAGhE,IAAa,eAAe,0BAC1B,QAAA,SAA2E;CAAA,MAAA,OAAAC,aAAA,QAAA,MAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAA9B,OAAIC,UAAA,QAAA,MAAA,IAAA;CAC/C,MAAM,OAAO,QAAQ;CACrB,IAAI,MAAGC,WAAkC,IAAI;CAC7C,MAAM,WAAW,iBAAiB;EAChC,iBAAkB,YAAA,UAAgB,eAAY,IAAA,QAAS;EACvD,aAAa,KAAA,MAAK;EAClB,WAAW;CACb,CAAC;CACD,aAAa;EAAA,IAAA;EACX,MAAM,aAAa,YAAA,UAAgB;EACnC,MAAM,QACJ,OAAA,YAAA,UAAuB,WAAW,KAAA,MAAK,MAAM,GAAG,KAAK,IAAI,GAAC,YAAA,KAAa,CAAC,IAAC,KAAA;EAC3E,MAAM,cAAc,aAAa,SAAS,SAAS,KAAA,MAAK,SAAS,MAAM;EACvE,OAAAC,YAAA,QAEQ,WACF,EAAE,IAAI,CAAC,mBAAmB,MAAM,cAAc,mBAAmB,IAAI,EAAE,GACvE,MACA;GAAE,KAAG;GAAe,eAAe;EAAO,CAC5C,GAAC,CAEA,MAAM,KAAK,KAAK,UAAKA,YAAA,KAAAC,cAAA,EAAA,OAEb,IAAI,MAAK,GACV,eACF;GACE,MAAM;GACN,SAAS;GACT,UAAU,SAAA,gBAAmB,SAAA,MAAS,IAAI,KAAK;GAC/C,aAAa;IAAE,UAAU;IAAI,eAAe;GAAU;EACxD,GAAC,SAAA,KAEH,GACK,aAAa,SAAS,UAAU,KAAK,IAAI,CAAC,CAAC,GAAA,EAAA,eAAA,CAE/C,IAAI,KAAK,EAAA,CAAA,CAEb,IAEC,cAAc,cAAc,MAACD,YAAA,KAAAC,cAAA;GAAA,QAAA;GAAA,WAAA;EAAA,GACM,aAAa,SAAS,UAAU,IAAI,CAAC,CAAC,GAAA,QAAA,QACtE,KAAK,eAAe,WAAW,CAAC,IAAA,QAAA,EAAA,eAAA,CAAA,KAAA,EAAA,CAAA,CAEpC,CAAA;CAGP;AACF,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
@@ -10,8 +10,8 @@ import { inlineArrows, isRtl } from "../utils/dom/direction.js";
10
10
  import { toneFillStyles } from "../utils/style/tone-styles.js";
11
11
  import { useFieldControl } from "../form/Field.js";
12
12
  import { FormValue } from "../form/FormValue.js";
13
- import { createVNode, isVNode, mergeProps, shallowRef, useId } from "vue";
14
- import { _component, bindable, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
13
+ import { createVNode, isVNode, shallowRef, 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
  //#region src/input/Slider.tsx
17
17
  /** 滑块方向 */
@@ -247,7 +247,7 @@ var Slider = /*#__PURE__*/ _component((_props, _ctx) => {
247
247
  const part = range ? index === 0 ? lang.sliderMin : lang.sliderMax : void 0;
248
248
  const ownLabel = rest["aria-label"];
249
249
  const labelledBy = defaultLabelledBy(rest, field.labelledBy);
250
- return createVNode("div", mergeProps({ "key": index }, mergeAttrs({ sx: [
250
+ return createVNode("div", mergeJsxProps({ "key": index }, mergeAttrs({ sx: [
251
251
  sliderStyles.thumb,
252
252
  focusRingStyles.visible,
253
253
  vertical ? sliderStyles.thumbVertical : sliderStyles.thumbHorizontal,
@@ -271,7 +271,7 @@ var Slider = /*#__PURE__*/ _component((_props, _ctx) => {
271
271
  onKeydown: (event) => onKeydown(index, event)
272
272
  }), { "data-index": range ? index : void 0 }), [part && labelledBy && createVNode(VisuallyHidden, { "id": `${labelId}-${index}` }, _isSlot(part) ? part : { default: () => [part] })]);
273
273
  };
274
- return createVNode("div", mergeProps(mergeAttrs({ sx: [
274
+ return createVNode("div", mergeJsxProps(mergeAttrs({ sx: [
275
275
  sliderStyles.root,
276
276
  vertical ? sliderStyles.vertical : sliderStyles.horizontal,
277
277
  labelled && (vertical ? sliderStyles.labelledVertical : sliderStyles.labelledHorizontal),
@@ -289,7 +289,7 @@ var Slider = /*#__PURE__*/ _component((_props, _ctx) => {
289
289
  createVNode("div", mergeAttrs({ sx: [sliderStyles.track, vertical ? sliderStyles.trackVertical : sliderStyles.trackHorizontal] }, propsTrack.value, { ref: track }), [createVNode("div", mergeAttrs({ sx: [sliderStyles.range, vertical ? sliderStyles.rangeVertical : sliderStyles.rangeHorizontal] }, propsRange.value, { sx: [position(start), vertical ? css.bind(sliderPositionStyles.height, () => [`${end - start}%`]) : css.bind(sliderPositionStyles.width, () => [`${end - start}%`])] }), null), normalized.map((mark) => {
290
290
  const percent = percentOf(mark.value);
291
291
  const own = typeof propsMark.value === "function" ? propsMark.value(mark) : propsMark.value;
292
- return createVNode("span", mergeProps({ "key": mark.value }, mergeAttrs({ sx: [
292
+ return createVNode("span", mergeJsxProps({ "key": mark.value }, mergeAttrs({ sx: [
293
293
  sliderStyles.mark,
294
294
  vertical ? sliderStyles.markVertical : sliderStyles.markHorizontal,
295
295
  percent >= start && percent <= end && sliderStyles.markActive
@@ -299,7 +299,7 @@ var Slider = /*#__PURE__*/ _component((_props, _ctx) => {
299
299
  normalized.map((mark) => {
300
300
  if (mark.label == null) return null;
301
301
  const own = typeof propsMarkLabel.value === "function" ? propsMarkLabel.value(mark) : propsMarkLabel.value;
302
- return createVNode("span", mergeProps({ "key": mark.value }, mergeAttrs({ sx: [sliderStyles.markLabel, vertical ? sliderStyles.markLabelVertical : sliderStyles.markLabelHorizontal] }, own, {
302
+ return createVNode("span", mergeJsxProps({ "key": mark.value }, mergeAttrs({ sx: [sliderStyles.markLabel, vertical ? sliderStyles.markLabelVertical : sliderStyles.markLabelHorizontal] }, own, {
303
303
  sx: position(percentOf(mark.value)),
304
304
  "aria-hidden": true
305
305
  })), [mark.label]);