@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":"Slider.js","names":["_isVNode","_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../src/input/Slider.tsx"],"sourcesContent":["/**\n * 滑块:在一个范围里拖动选值(音量、进度、价格)。WAI-ARIA 的 Slider 模式:滑块是 role=\"slider\",\n * 方向键 ±step,Page Up / Page Down ±bigStep,Home / End 到两端;从右到左排版时横向的方向键反过来。\n * 点击轨道任意位置直接跳过去并接着拖动。参考 Radix Slider、React Aria useSlider。\n *\n * <Slider _value={volume} aria-label=\"音量\" />\n * <Slider _value={price} min={0} max={1000} step={50} valueText={(v) => `${v} 元`} />\n * <Slider _value={range} aria-label=\"价格\" marks={[0, { value: 500, label: '500' }, 1000]} /> 范围:[低, 高]\n *\n * value 是数组 [低, 高] 时是范围选择:两个滑块各自可聚焦、可拖动,不能交叉;点击轨道移动离得近的那个。\n * 两个滑块的名称在 aria-label(或 Field 的标签)后面加上“最小值”“最大值”,取值范围互相限制(同 WAI-ARIA 多滑块)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { useId, type VNodeChild } from 'vue';\nimport { VisuallyHidden } from '../base/VisuallyHidden';\nimport { useLang } from '../config/context';\nimport { startMove } from '../utils/dom/move';\nimport { defaultLabelledBy, mergeAttrs, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { toneFillStyles, type StatusTone } from '../utils/style/tone-styles';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\nimport { clamp, snapToStep } from '../utils/data/number';\nimport { inlineArrows, isRtl } from '../utils/dom/direction';\nimport { useFieldControl } from '../form/Field';\nimport { FormValue } from '../form/FormValue';\nimport { t } from '../config/theme/tokens';\n\n/** 滑块方向 */\nexport interface SliderOrientations {\n /** 横向(默认):起始端是最小值 */\n horizontal: unknown;\n /** 纵向:底端是最小值;高度由使用方给,默认 10em */\n vertical: unknown;\n}\n\n/** 单值,或范围 [低, 高] */\nexport type SliderValue = number | readonly [number, number];\n\n/** 轨道上的一个刻度 */\nexport interface SliderMark {\n /** 刻度所在的值 */\n value: number;\n /** 刻度下方(纵向时右侧)的文字 */\n label?: VNodeChild;\n}\n\n/** 角色、取值与可聚焦由组件管理 */\nexport type SliderManaged =\n | 'role'\n | 'tabindex'\n | 'aria-valuemin'\n | 'aria-valuemax'\n | 'aria-valuenow'\n | 'aria-valuetext'\n | 'aria-orientation'\n | 'aria-disabled';\n\n/** 未声明的属性落到滑块(role=\"slider\" 的主元素,范围时两个都有)上,名称写 aria-label;外层用 propsRoot */\nexport interface SliderProps<V extends SliderValue = number> extends PartProps<\n 'div',\n SliderManaged\n> {\n /** 当前值:父级写 _value={x} 双向绑定,拖动中实时写回;数组 [低, 高] 时是范围选择 */\n _value?: V;\n /** 最小值,默认 0 */\n min?: number;\n /** 最大值,默认 100 */\n max?: number;\n /** 步长,默认 1;取值总是对齐到 min + n × step */\n step?: number;\n /** Page Up / Page Down 的步长,默认为范围的十分之一(至少一个 step) */\n bigStep?: number;\n /** 方向,默认 horizontal */\n orientation?: keyof SliderOrientations;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:滑块能聚焦、读屏念“只读”,拖动与方向键不改值(查看详情、审批时);外观照常 */\n readonly?: boolean;\n /** 字号档位,滑块与轨道随之缩放;不写时继承 */\n size?: TextSize;\n /** 已选范围与滑块描边的色调(与 Button、Badge 等同一套),默认 accent */\n tone?: StatusTone;\n /** 刻度:数字或带文字的 { value, label };有文字时滑块下方(纵向时右侧)留出位置 */\n marks?: readonly (number | SliderMark)[];\n /** 读屏念的取值文字(aria-valuetext),如 `(v) => \\`${v}%\\``;不写时念数字 */\n valueText?: (value: number) => string;\n /** 表单字段名:给了就带隐藏的 input(范围时两个同名),随表单提交 */\n name?: string;\n /** 一次操作结束(松开、按键)时的值:保存、发请求放在这里,不必每次移动都发 */\n onValueCommit?: (value: V) => void;\n /** 外层(轨道与滑块的容器)的部件属性 */\n propsRoot?: PartProps<'div'>;\n /** 轨道的部件属性 */\n propsTrack?: PartProps<'div'>;\n /** 已选范围(轨道上着色的部分)的部件属性;位置与长度由组件写 */\n propsRange?: PartProps<'div'>;\n /** 刻度点的部件属性 */\n propsMark?: PartProps<'span'> | ((mark: SliderMark) => PartProps<'span'>);\n /** 刻度文字的部件属性 */\n propsMarkLabel?: PartProps<'span'> | ((mark: SliderMark) => PartProps<'span'>);\n}\n\n/** Slider 的样式:root、horizontal、vertical、disabled、readonly、track、range、thumb、mark、markLabel 等 */\nexport const sliderStyles = css.create({\n root: {\n position: 'relative',\n display: 'flex',\n alignItems: 'center',\n // 触摸拖动不触发页面滚动\n touchAction: 'none',\n userSelect: 'none',\n cursor: 'pointer',\n },\n // 点击区域至少 24px(WCAG 2.5.8)。滑块的中心对准取值,两端各留半个滑块的外边距:\n // 滑块在最小、最大值时不伸出组件的盒子,不压到旁边的控件\n horizontal: {\n width: `calc(100% - ${t.space.lg} - ${t.space.xs})`,\n marginInline: `calc((${t.space.lg} + ${t.space.xs}) / 2)`,\n minHeight: '_minTarget',\n },\n vertical: {\n flexDirection: 'column',\n height: '10em',\n marginBlock: `calc((${t.space.lg} + ${t.space.xs}) / 2)`,\n minWidth: '_minTarget',\n },\n // 刻度文字放在轨道下方(纵向时右侧),给它留出位置\n labelledHorizontal: { paddingBlockEnd: '1.5em' },\n labelledVertical: { paddingInlineEnd: '3em' },\n disabled: { opacity: '_disabled', cursor: 'not-allowed' },\n readonly: { cursor: 'default' },\n track: {\n position: 'relative',\n flexGrow: 1,\n borderRadius: '_full',\n backgroundColor: '_fill',\n overflow: 'hidden',\n },\n trackHorizontal: { height: `calc(${t.space.xs} * 1.5)` },\n trackVertical: { width: `calc(${t.space.xs} * 1.5)` },\n range: { position: 'absolute', backgroundColor: 'var(--tone-fill)' },\n rangeHorizontal: { insetBlock: 0 },\n rangeVertical: { insetInline: 0 },\n thumb: {\n position: 'absolute',\n boxSizing: 'border-box',\n width: `calc(${t.space.lg} + ${t.space.xs})`,\n height: `calc(${t.space.lg} + ${t.space.xs})`,\n borderWidth: '_sm',\n borderStyle: 'solid',\n borderColor: 'var(--tone-fill)',\n borderRadius: '_full',\n backgroundColor: '_surface',\n boxShadow: '_sm',\n cursor: 'grab',\n },\n // 用逻辑方向的外边距把滑块的中心对准取值位置:从右到左排版时也对\n thumbHorizontal: { marginInlineStart: `calc((${t.space.lg} + ${t.space.xs}) / -2)` },\n thumbVertical: { marginBottom: `calc((${t.space.lg} + ${t.space.xs}) / -2)` },\n // 轨道里的小圆点;在已选范围里时换成反色\n mark: {\n position: 'absolute',\n width: '_space.xs',\n height: '_space.xs',\n borderRadius: '_full',\n backgroundColor: '_borderStrong',\n pointerEvents: 'none',\n },\n markHorizontal: { top: '50%', translate: { default: '-50% -50%', ':dir(rtl)': '50% -50%' } },\n markVertical: { left: '50%', translate: '-50% 50%' },\n markActive: { backgroundColor: 'var(--tone-on-fill)' },\n markLabel: {\n position: 'absolute',\n fontSize: '_sm',\n lineHeight: '_tight',\n color: '_textMuted',\n whiteSpace: 'nowrap',\n pointerEvents: 'none',\n },\n markLabelHorizontal: {\n top: `calc(50% + ${t.space.sm})`,\n translate: { default: '-50% -0.75em', ':dir(rtl)': '50% -0.75em' },\n },\n markLabelVertical: { left: `calc(50% + ${t.space.md})`, translate: '0 50%' },\n});\n\n// 位置是任意值,用动态样式(编译为 CSS 变量);单独一个 create,见 COMPONENTS.md §4\n/** Slider 的样式:inline(横向的起点)、size(横向的长度)、bottom、height(纵向) */\nexport const sliderPositionStyles = css.create({\n inline: (percent: string) => ({ insetInlineStart: percent }),\n width: (percent: string) => ({ width: percent }),\n bottom: (percent: string) => ({ bottom: percent }),\n height: (percent: string) => ({ height: percent }),\n});\n\n/** 滑块:在 min–max 之间按 step 拖动或用键盘选值;value 为 [低, 高] 时选一个范围 */\nexport const Slider = _component(\n <V extends SliderValue = number>({\n _value: value = _bindable<V>(0 as V),\n min = 0,\n max = 100,\n step = 1,\n bigStep,\n orientation = 'horizontal',\n disabled,\n readonly,\n size,\n tone = 'accent',\n marks,\n valueText,\n name,\n onValueCommit,\n propsRoot,\n propsTrack,\n propsRange,\n propsMark,\n propsMarkLabel,\n id,\n ...rest\n }: SliderProps<V>) => {\n const lang = useLang();\n // 在 Field 里时:标签作为名称、关联说明与错误、沿用不可用与只读\n const control = useFieldControl(() => ({ id, disabled, readonly }));\n /** 不接受改值:不可用或只读 */\n const off = () => control().disabled || control().readonly;\n const labelId = useId();\n let track = _state.raw<HTMLElement | null>(null);\n const thumbs: (HTMLElement | null)[] = [null, null];\n\n const isRange = () => Array.isArray(value);\n /** 各滑块的值(单值时只有一个) */\n const values = (): number[] => (Array.isArray(value) ? [...value] : [value as number]);\n /** 夹在范围内并对齐到步长 */\n const snap = (raw: number) => snapToStep(raw, step, min, max);\n const rtl = () => orientation === 'horizontal' && !!track && isRtl(track);\n\n /** 第 index 个滑块能取的范围:范围选择时不能越过另一个 */\n function bounds(index: number): [number, number] {\n if (!isRange()) return [min, max];\n const [low, high] = values() as [number, number];\n return index === 0 ? [min, high] : [low, max];\n }\n\n /** 改第 index 个滑块的值 */\n function set(index: number, raw: number) {\n const [lower, upper] = bounds(index);\n const next = clamp(snap(raw), lower, upper);\n if (!isRange()) {\n value = next as V;\n return;\n }\n const pair = values() as [number, number];\n pair[index] = next;\n value = pair as unknown as V;\n }\n\n /** 指针位置对应的值 */\n function valueAt(clientX: number, clientY: number) {\n const rect = track!.getBoundingClientRect();\n let ratio =\n orientation === 'vertical'\n ? (rect.bottom - clientY) / rect.height\n : (clientX - rect.left) / rect.width;\n if (rtl()) ratio = 1 - ratio;\n return snap(min + clamp(ratio, 0, 1) * (max - min));\n }\n\n /** 离 target 最近的滑块;两个重合时按方向选(往高处去的拿高的那个) */\n function nearest(target: number) {\n if (!isRange()) return 0;\n const [low, high] = values() as [number, number];\n if (low === high) return target > high ? 1 : 0;\n return Math.abs(target - low) <= Math.abs(target - high) ? 0 : 1;\n }\n\n function grab(event: PointerEvent) {\n if (off() || event.button !== 0 || !track) return;\n // 不让浏览器把焦点放到别处、开始选中文字;焦点交给滑块,键盘接着可以微调\n event.preventDefault();\n const target = valueAt(event.clientX, event.clientY);\n const index = nearest(target);\n thumbs[index]?.focus();\n set(index, target);\n startMove(event, {\n onMove: ({ clientX, clientY }) => set(index, valueAt(clientX, clientY)),\n onEnd: () => onValueCommit?.(value),\n });\n }\n\n function onKeydown(index: number, event: KeyboardEvent) {\n if (off()) return;\n const current = values()[index]!;\n const big = bigStep ?? Math.max(step, (max - min) / 10);\n // 从右到左排版时,横向的左右键反过来(右边是起点)\n const { forward, backward } = inlineArrows(rtl());\n const [lower, upper] = bounds(index);\n const next: Record<string, number> = {\n [forward]: current + step,\n ArrowUp: current + step,\n [backward]: current - step,\n ArrowDown: current - step,\n PageUp: current + big,\n PageDown: current - big,\n Home: lower,\n End: upper,\n };\n if (!(event.key in next)) return;\n event.preventDefault();\n set(index, next[event.key]!);\n onValueCommit?.(value);\n }\n\n const percentOf = (number: number) =>\n max > min ? ((clamp(number, min, max) - min) / (max - min)) * 100 : 0;\n\n return () => {\n const vertical = orientation === 'vertical';\n const field = control();\n const range = isRange();\n // 父级传入超出范围的值时按范围内显示(不改父级的值),滑块不会跑出轨道\n const shown = values().map((number) => clamp(number, min, max));\n const [start, end] = range\n ? [percentOf(shown[0]!), percentOf(shown[1]!)]\n : [0, percentOf(shown[0]!)];\n const normalized = (marks ?? []).map((mark) =>\n typeof mark === 'number' ? { value: mark } : mark,\n );\n const labelled = normalized.some((mark) => mark.label != null);\n const position = (percent: number) =>\n vertical\n ? sliderPositionStyles.bottom(`${percent}%`)\n : sliderPositionStyles.inline(`${percent}%`);\n\n const renderThumb = (number: number, index: number) => {\n const [lower, upper] = bounds(index);\n const part = range ? (index === 0 ? lang.sliderMin : lang.sliderMax) : undefined;\n const ownLabel = rest['aria-label'];\n // 范围时每个滑块的名称后面加“最小值 / 最大值”:有 aria-label 时拼在一起,用 Field 的标签时连上隐藏的文字\n const labelledBy = defaultLabelledBy(rest, field.labelledBy);\n return (\n <div\n key={index}\n {...mergeAttrs<'div'>(\n {\n sx: [\n sliderStyles.thumb,\n focusRingStyles.visible,\n vertical ? sliderStyles.thumbVertical : sliderStyles.thumbHorizontal,\n position(percentOf(number)),\n ],\n },\n rest,\n {\n ref: (element: unknown) => (thumbs[index] = element as HTMLElement | null),\n role: 'slider',\n id: index === 0 ? field.id : undefined,\n tabindex: field.disabled ? undefined : 0,\n 'aria-valuemin': lower,\n 'aria-valuemax': upper,\n 'aria-valuenow': number,\n 'aria-valuetext': valueText?.(number),\n 'aria-orientation': orientation,\n 'aria-disabled': field.disabled || undefined,\n 'aria-readonly': field.readonly || undefined,\n 'aria-label': part && ownLabel != null ? `${ownLabel} ${part}` : ownLabel,\n 'aria-labelledby':\n part && labelledBy ? `${labelledBy} ${labelId}-${index}` : labelledBy,\n 'aria-describedby': field.describedBy,\n 'aria-invalid': field.invalid || undefined,\n onKeydown: (event: KeyboardEvent) => onKeydown(index, event),\n },\n )}\n data-index={range ? index : undefined}\n >\n {part && labelledBy && (\n <VisuallyHidden id={`${labelId}-${index}`}>{part}</VisuallyHidden>\n )}\n </div>\n );\n };\n\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n sliderStyles.root,\n vertical ? sliderStyles.vertical : sliderStyles.horizontal,\n labelled &&\n (vertical ? sliderStyles.labelledVertical : sliderStyles.labelledHorizontal),\n toneFillStyles[tone],\n size && fontSizeStyles[size],\n ],\n },\n propsRoot,\n {\n sx: [\n field.readonly && sliderStyles.readonly,\n field.disabled && sliderStyles.disabled,\n ],\n onPointerdown: grab,\n },\n )}\n data-disabled={field.disabled || undefined}\n data-readonly={field.readonly || undefined}\n data-orientation={orientation}\n data-range={range || undefined}\n >\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n sliderStyles.track,\n vertical ? sliderStyles.trackVertical : sliderStyles.trackHorizontal,\n ],\n },\n propsTrack,\n { ref: _toRef(track) },\n )}\n >\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n sliderStyles.range,\n vertical ? sliderStyles.rangeVertical : sliderStyles.rangeHorizontal,\n ],\n },\n propsRange,\n {\n sx: [\n position(start),\n vertical\n ? sliderPositionStyles.height(`${end - start}%`)\n : sliderPositionStyles.width(`${end - start}%`),\n ],\n },\n )}\n />\n {normalized.map((mark) => {\n const percent = percentOf(mark.value);\n const own = typeof propsMark === 'function' ? propsMark(mark) : propsMark;\n return (\n <span\n key={mark.value}\n {...mergeAttrs<'span'>(\n {\n sx: [\n sliderStyles.mark,\n vertical ? sliderStyles.markVertical : sliderStyles.markHorizontal,\n percent >= start && percent <= end && sliderStyles.markActive,\n ],\n },\n own,\n { sx: position(percent) },\n )}\n />\n );\n })}\n </div>\n {shown.map(renderThumb)}\n {normalized.map((mark) => {\n if (mark.label == null) return null;\n const own =\n typeof propsMarkLabel === 'function' ? propsMarkLabel(mark) : propsMarkLabel;\n return (\n <span\n key={mark.value}\n {...mergeAttrs<'span'>(\n {\n sx: [\n sliderStyles.markLabel,\n vertical ? sliderStyles.markLabelVertical : sliderStyles.markLabelHorizontal,\n ],\n },\n own,\n { sx: position(percentOf(mark.value)), 'aria-hidden': true },\n )}\n >\n {mark.label}\n </span>\n );\n })}\n <FormValue name={name} value={range ? shown : shown[0]} disabled={control().disabled} />\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"Slider.js","names":["_isVNode","_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../src/input/Slider.tsx"],"sourcesContent":["/**\n * 滑块:在一个范围里拖动选值(音量、进度、价格)。WAI-ARIA 的 Slider 模式:滑块是 role=\"slider\",\n * 方向键 ±step,Page Up / Page Down ±bigStep,Home / End 到两端;从右到左排版时横向的方向键反过来。\n * 点击轨道任意位置直接跳过去并接着拖动。参考 Radix Slider、React Aria useSlider。\n *\n * <Slider _value={volume} aria-label=\"音量\" />\n * <Slider _value={price} min={0} max={1000} step={50} valueText={(v) => `${v} 元`} />\n * <Slider _value={range} aria-label=\"价格\" marks={[0, { value: 500, label: '500' }, 1000]} /> 范围:[低, 高]\n *\n * value 是数组 [低, 高] 时是范围选择:两个滑块各自可聚焦、可拖动,不能交叉;点击轨道移动离得近的那个。\n * 两个滑块的名称在 aria-label(或 Field 的标签)后面加上“最小值”“最大值”,取值范围互相限制(同 WAI-ARIA 多滑块)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { useId, type VNodeChild } from 'vue';\nimport { VisuallyHidden } from '../base/VisuallyHidden';\nimport { useLang } from '../config/context';\nimport { startMove } from '../utils/dom/move';\nimport { defaultLabelledBy, mergeAttrs, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { toneFillStyles, type StatusTone } from '../utils/style/tone-styles';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\nimport { clamp, snapToStep } from '../utils/data/number';\nimport { inlineArrows, isRtl } from '../utils/dom/direction';\nimport { useFieldControl } from '../form/Field';\nimport { FormValue } from '../form/FormValue';\nimport { t } from '../config/theme/tokens';\n\n/** 滑块方向 */\nexport interface SliderOrientations {\n /** 横向(默认):起始端是最小值 */\n horizontal: unknown;\n /** 纵向:底端是最小值;高度由使用方给,默认 10em */\n vertical: unknown;\n}\n\n/** 单值,或范围 [低, 高] */\nexport type SliderValue = number | readonly [number, number];\n\n/** 轨道上的一个刻度 */\nexport interface SliderMark {\n /** 刻度所在的值 */\n value: number;\n /** 刻度下方(纵向时右侧)的文字 */\n label?: VNodeChild;\n}\n\n/** 角色、取值与可聚焦由组件管理 */\nexport type SliderManaged =\n | 'role'\n | 'tabindex'\n | 'aria-valuemin'\n | 'aria-valuemax'\n | 'aria-valuenow'\n | 'aria-valuetext'\n | 'aria-orientation'\n | 'aria-disabled';\n\n/** 未声明的属性落到滑块(role=\"slider\" 的主元素,范围时两个都有)上,名称写 aria-label;外层用 propsRoot */\nexport interface SliderProps<V extends SliderValue = number> extends PartProps<\n 'div',\n SliderManaged\n> {\n /** 当前值:父级写 _value={x} 双向绑定,拖动中实时写回;数组 [低, 高] 时是范围选择 */\n _value?: V;\n /** 最小值,默认 0 */\n min?: number;\n /** 最大值,默认 100 */\n max?: number;\n /** 步长,默认 1;取值总是对齐到 min + n × step */\n step?: number;\n /** Page Up / Page Down 的步长,默认为范围的十分之一(至少一个 step) */\n bigStep?: number;\n /** 方向,默认 horizontal */\n orientation?: keyof SliderOrientations;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:滑块能聚焦、读屏念“只读”,拖动与方向键不改值(查看详情、审批时);外观照常 */\n readonly?: boolean;\n /** 字号档位,滑块与轨道随之缩放;不写时继承 */\n size?: TextSize;\n /** 已选范围与滑块描边的色调(与 Button、Badge 等同一套),默认 accent */\n tone?: StatusTone;\n /** 刻度:数字或带文字的 { value, label };有文字时滑块下方(纵向时右侧)留出位置 */\n marks?: readonly (number | SliderMark)[];\n /** 读屏念的取值文字(aria-valuetext),如 `(v) => \\`${v}%\\``;不写时念数字 */\n valueText?: (value: number) => string;\n /** 表单字段名:给了就带隐藏的 input(范围时两个同名),随表单提交 */\n name?: string;\n /** 一次操作结束(松开、按键)时的值:保存、发请求放在这里,不必每次移动都发 */\n onValueCommit?: (value: V) => void;\n /** 外层(轨道与滑块的容器)的部件属性 */\n propsRoot?: PartProps<'div'>;\n /** 轨道的部件属性 */\n propsTrack?: PartProps<'div'>;\n /** 已选范围(轨道上着色的部分)的部件属性;位置与长度由组件写 */\n propsRange?: PartProps<'div'>;\n /** 刻度点的部件属性 */\n propsMark?: PartProps<'span'> | ((mark: SliderMark) => PartProps<'span'>);\n /** 刻度文字的部件属性 */\n propsMarkLabel?: PartProps<'span'> | ((mark: SliderMark) => PartProps<'span'>);\n}\n\n/** Slider 的样式:root、horizontal、vertical、disabled、readonly、track、range、thumb、mark、markLabel 等 */\nexport const sliderStyles = css.create({\n root: {\n position: 'relative',\n display: 'flex',\n alignItems: 'center',\n // 触摸拖动不触发页面滚动\n touchAction: 'none',\n userSelect: 'none',\n cursor: 'pointer',\n },\n // 点击区域至少 24px(WCAG 2.5.8)。滑块的中心对准取值,两端各留半个滑块的外边距:\n // 滑块在最小、最大值时不伸出组件的盒子,不压到旁边的控件\n horizontal: {\n width: `calc(100% - ${t.space.lg} - ${t.space.xs})`,\n marginInline: `calc((${t.space.lg} + ${t.space.xs}) / 2)`,\n minHeight: '_minTarget',\n },\n vertical: {\n flexDirection: 'column',\n height: '10em',\n marginBlock: `calc((${t.space.lg} + ${t.space.xs}) / 2)`,\n minWidth: '_minTarget',\n },\n // 刻度文字放在轨道下方(纵向时右侧),给它留出位置\n labelledHorizontal: { paddingBlockEnd: '1.5em' },\n labelledVertical: { paddingInlineEnd: '3em' },\n disabled: { opacity: '_disabled', cursor: 'not-allowed' },\n readonly: { cursor: 'default' },\n track: {\n position: 'relative',\n flexGrow: 1,\n borderRadius: '_full',\n backgroundColor: '_fill',\n overflow: 'hidden',\n },\n trackHorizontal: { height: `calc(${t.space.xs} * 1.5)` },\n trackVertical: { width: `calc(${t.space.xs} * 1.5)` },\n range: { position: 'absolute', backgroundColor: 'var(--tone-fill)' },\n rangeHorizontal: { insetBlock: 0 },\n rangeVertical: { insetInline: 0 },\n thumb: {\n position: 'absolute',\n boxSizing: 'border-box',\n width: `calc(${t.space.lg} + ${t.space.xs})`,\n height: `calc(${t.space.lg} + ${t.space.xs})`,\n borderWidth: '_sm',\n borderStyle: 'solid',\n borderColor: 'var(--tone-fill)',\n borderRadius: '_full',\n backgroundColor: '_surface',\n boxShadow: '_sm',\n cursor: 'grab',\n },\n // 用逻辑方向的外边距把滑块的中心对准取值位置:从右到左排版时也对\n thumbHorizontal: { marginInlineStart: `calc((${t.space.lg} + ${t.space.xs}) / -2)` },\n thumbVertical: { marginBottom: `calc((${t.space.lg} + ${t.space.xs}) / -2)` },\n // 轨道里的小圆点;在已选范围里时换成反色\n mark: {\n position: 'absolute',\n width: '_space.xs',\n height: '_space.xs',\n borderRadius: '_full',\n backgroundColor: '_borderStrong',\n pointerEvents: 'none',\n },\n markHorizontal: { top: '50%', translate: { default: '-50% -50%', ':dir(rtl)': '50% -50%' } },\n markVertical: { left: '50%', translate: '-50% 50%' },\n markActive: { backgroundColor: 'var(--tone-on-fill)' },\n markLabel: {\n position: 'absolute',\n fontSize: '_sm',\n lineHeight: '_tight',\n color: '_textMuted',\n whiteSpace: 'nowrap',\n pointerEvents: 'none',\n },\n markLabelHorizontal: {\n top: `calc(50% + ${t.space.sm})`,\n translate: { default: '-50% -0.75em', ':dir(rtl)': '50% -0.75em' },\n },\n markLabelVertical: { left: `calc(50% + ${t.space.md})`, translate: '0 50%' },\n});\n\n// 位置是任意值,用动态样式(编译为 CSS 变量);单独一个 create,见 COMPONENTS.md §4\n/** Slider 的样式:inline(横向的起点)、size(横向的长度)、bottom、height(纵向) */\nexport const sliderPositionStyles = css.create({\n inline: (percent: string) => ({ insetInlineStart: percent }),\n width: (percent: string) => ({ width: percent }),\n bottom: (percent: string) => ({ bottom: percent }),\n height: (percent: string) => ({ height: percent }),\n});\n\n/** 滑块:在 min–max 之间按 step 拖动或用键盘选值;value 为 [低, 高] 时选一个范围 */\nexport const Slider = _component(\n <V extends SliderValue = number>({\n _value: value = _bindable<V>(0 as V),\n min = 0,\n max = 100,\n step = 1,\n bigStep,\n orientation = 'horizontal',\n disabled,\n readonly,\n size,\n tone = 'accent',\n marks,\n valueText,\n name,\n onValueCommit,\n propsRoot,\n propsTrack,\n propsRange,\n propsMark,\n propsMarkLabel,\n id,\n ...rest\n }: SliderProps<V>) => {\n const lang = useLang();\n // 在 Field 里时:标签作为名称、关联说明与错误、沿用不可用与只读\n const control = useFieldControl(() => ({ id, disabled, readonly }));\n /** 不接受改值:不可用或只读 */\n const off = () => control().disabled || control().readonly;\n const labelId = useId();\n let track = _state.raw<HTMLElement | null>(null);\n const thumbs: (HTMLElement | null)[] = [null, null];\n\n const isRange = () => Array.isArray(value);\n /** 各滑块的值(单值时只有一个) */\n const values = (): number[] => (Array.isArray(value) ? [...value] : [value as number]);\n /** 夹在范围内并对齐到步长 */\n const snap = (raw: number) => snapToStep(raw, step, min, max);\n const rtl = () => orientation === 'horizontal' && !!track && isRtl(track);\n\n /** 第 index 个滑块能取的范围:范围选择时不能越过另一个 */\n function bounds(index: number): [number, number] {\n if (!isRange()) return [min, max];\n const [low, high] = values() as [number, number];\n return index === 0 ? [min, high] : [low, max];\n }\n\n /** 改第 index 个滑块的值 */\n function set(index: number, raw: number) {\n const [lower, upper] = bounds(index);\n const next = clamp(snap(raw), lower, upper);\n if (!isRange()) {\n value = next as V;\n return;\n }\n const pair = values() as [number, number];\n pair[index] = next;\n value = pair as unknown as V;\n }\n\n /** 指针位置对应的值 */\n function valueAt(clientX: number, clientY: number) {\n const rect = track!.getBoundingClientRect();\n let ratio =\n orientation === 'vertical'\n ? (rect.bottom - clientY) / rect.height\n : (clientX - rect.left) / rect.width;\n if (rtl()) ratio = 1 - ratio;\n return snap(min + clamp(ratio, 0, 1) * (max - min));\n }\n\n /** 离 target 最近的滑块;两个重合时按方向选(往高处去的拿高的那个) */\n function nearest(target: number) {\n if (!isRange()) return 0;\n const [low, high] = values() as [number, number];\n if (low === high) return target > high ? 1 : 0;\n return Math.abs(target - low) <= Math.abs(target - high) ? 0 : 1;\n }\n\n function grab(event: PointerEvent) {\n if (off() || event.button !== 0 || !track) return;\n // 不让浏览器把焦点放到别处、开始选中文字;焦点交给滑块,键盘接着可以微调\n event.preventDefault();\n const target = valueAt(event.clientX, event.clientY);\n const index = nearest(target);\n thumbs[index]?.focus();\n set(index, target);\n startMove(event, {\n onMove: ({ clientX, clientY }) => set(index, valueAt(clientX, clientY)),\n onEnd: () => onValueCommit?.(value),\n });\n }\n\n function onKeydown(index: number, event: KeyboardEvent) {\n if (off()) return;\n const current = values()[index]!;\n const big = bigStep ?? Math.max(step, (max - min) / 10);\n // 从右到左排版时,横向的左右键反过来(右边是起点)\n const { forward, backward } = inlineArrows(rtl());\n const [lower, upper] = bounds(index);\n const next: Record<string, number> = {\n [forward]: current + step,\n ArrowUp: current + step,\n [backward]: current - step,\n ArrowDown: current - step,\n PageUp: current + big,\n PageDown: current - big,\n Home: lower,\n End: upper,\n };\n if (!(event.key in next)) return;\n event.preventDefault();\n set(index, next[event.key]!);\n onValueCommit?.(value);\n }\n\n const percentOf = (number: number) =>\n max > min ? ((clamp(number, min, max) - min) / (max - min)) * 100 : 0;\n\n return () => {\n const vertical = orientation === 'vertical';\n const field = control();\n const range = isRange();\n // 父级传入超出范围的值时按范围内显示(不改父级的值),滑块不会跑出轨道\n const shown = values().map((number) => clamp(number, min, max));\n const [start, end] = range\n ? [percentOf(shown[0]!), percentOf(shown[1]!)]\n : [0, percentOf(shown[0]!)];\n const normalized = (marks ?? []).map((mark) =>\n typeof mark === 'number' ? { value: mark } : mark,\n );\n const labelled = normalized.some((mark) => mark.label != null);\n const position = (percent: number) =>\n vertical\n ? sliderPositionStyles.bottom(`${percent}%`)\n : sliderPositionStyles.inline(`${percent}%`);\n\n const renderThumb = (number: number, index: number) => {\n const [lower, upper] = bounds(index);\n const part = range ? (index === 0 ? lang.sliderMin : lang.sliderMax) : undefined;\n const ownLabel = rest['aria-label'];\n // 范围时每个滑块的名称后面加“最小值 / 最大值”:有 aria-label 时拼在一起,用 Field 的标签时连上隐藏的文字\n const labelledBy = defaultLabelledBy(rest, field.labelledBy);\n return (\n <div\n key={index}\n {...mergeAttrs<'div'>(\n {\n sx: [\n sliderStyles.thumb,\n focusRingStyles.visible,\n vertical ? sliderStyles.thumbVertical : sliderStyles.thumbHorizontal,\n position(percentOf(number)),\n ],\n },\n rest,\n {\n ref: (element: unknown) => (thumbs[index] = element as HTMLElement | null),\n role: 'slider',\n id: index === 0 ? field.id : undefined,\n tabindex: field.disabled ? undefined : 0,\n 'aria-valuemin': lower,\n 'aria-valuemax': upper,\n 'aria-valuenow': number,\n 'aria-valuetext': valueText?.(number),\n 'aria-orientation': orientation,\n 'aria-disabled': field.disabled || undefined,\n 'aria-readonly': field.readonly || undefined,\n 'aria-label': part && ownLabel != null ? `${ownLabel} ${part}` : ownLabel,\n 'aria-labelledby':\n part && labelledBy ? `${labelledBy} ${labelId}-${index}` : labelledBy,\n 'aria-describedby': field.describedBy,\n 'aria-invalid': field.invalid || undefined,\n onKeydown: (event: KeyboardEvent) => onKeydown(index, event),\n },\n )}\n data-index={range ? index : undefined}\n >\n {part && labelledBy && (\n <VisuallyHidden id={`${labelId}-${index}`}>{part}</VisuallyHidden>\n )}\n </div>\n );\n };\n\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n sliderStyles.root,\n vertical ? sliderStyles.vertical : sliderStyles.horizontal,\n labelled &&\n (vertical ? sliderStyles.labelledVertical : sliderStyles.labelledHorizontal),\n toneFillStyles[tone],\n size && fontSizeStyles[size],\n ],\n },\n propsRoot,\n {\n sx: [\n field.readonly && sliderStyles.readonly,\n field.disabled && sliderStyles.disabled,\n ],\n onPointerdown: grab,\n },\n )}\n data-disabled={field.disabled || undefined}\n data-readonly={field.readonly || undefined}\n data-orientation={orientation}\n data-range={range || undefined}\n >\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n sliderStyles.track,\n vertical ? sliderStyles.trackVertical : sliderStyles.trackHorizontal,\n ],\n },\n propsTrack,\n { ref: _toRef(track) },\n )}\n >\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n sliderStyles.range,\n vertical ? sliderStyles.rangeVertical : sliderStyles.rangeHorizontal,\n ],\n },\n propsRange,\n {\n sx: [\n position(start),\n vertical\n ? sliderPositionStyles.height(`${end - start}%`)\n : sliderPositionStyles.width(`${end - start}%`),\n ],\n },\n )}\n />\n {normalized.map((mark) => {\n const percent = percentOf(mark.value);\n const own = typeof propsMark === 'function' ? propsMark(mark) : propsMark;\n return (\n <span\n key={mark.value}\n {...mergeAttrs<'span'>(\n {\n sx: [\n sliderStyles.mark,\n vertical ? sliderStyles.markVertical : sliderStyles.markHorizontal,\n percent >= start && percent <= end && sliderStyles.markActive,\n ],\n },\n own,\n { sx: position(percent) },\n )}\n />\n );\n })}\n </div>\n {shown.map(renderThumb)}\n {normalized.map((mark) => {\n if (mark.label == null) return null;\n const own =\n typeof propsMarkLabel === 'function' ? propsMarkLabel(mark) : propsMarkLabel;\n return (\n <span\n key={mark.value}\n {...mergeAttrs<'span'>(\n {\n sx: [\n sliderStyles.markLabel,\n vertical ? sliderStyles.markLabelVertical : sliderStyles.markLabelHorizontal,\n ],\n },\n own,\n { sx: position(percentOf(mark.value)), 'aria-hidden': true },\n )}\n >\n {mark.label}\n </span>\n );\n })}\n <FormValue name={name} value={range ? shown : shown[0]} disabled={control().disabled} />\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -5,8 +5,8 @@ import { useDelayedLoading } from "../utils/motion/delayed-loading.js";
5
5
  import { Spinner } from "../base/Spinner.js";
6
6
  import { useFieldControl } from "../form/Field.js";
7
7
  import { choiceInputStyles, choiceParts, syncChecked, useChoiceAppearance } from "./choice-styles.js";
8
- import { createVNode, mergeProps } from "vue";
9
- import { _component, bindable, childrenProp, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
8
+ import { createVNode } from "vue";
9
+ import { _component, bindable, childrenProp, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
10
10
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
11
11
  //#region src/input/Switch.tsx
12
12
  /** 角色、勾选状态与可用性由组件管理;原生的 size 属性让给字号档位 */
@@ -120,7 +120,7 @@ var Switch = /*#__PURE__*/ _component((_props, _ctx) => {
120
120
  on ? switchStyles.contentOn : switchStyles.contentOff,
121
121
  on !== checked.value && switchStyles.contentHidden
122
122
  ] }, propsContent.value, { "aria-hidden": true }), [createVNode("span", mergeAttrs({ sx: switchStyles.contentText }, propsContentText.value), [child])]);
123
- return createVNode("label", mergeProps(mergeAttrs(s.root, propsRoot.value), {
123
+ return createVNode("label", mergeJsxProps(mergeAttrs(s.root, propsRoot.value), {
124
124
  "data-state": checked.value ? "checked" : "unchecked",
125
125
  "data-disabled": state.disabled || void 0,
126
126
  "data-readonly": state.readonly || void 0,
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../src/input/Switch.tsx"],"sourcesContent":["/**\n * 开关(原生 input type=\"checkbox\" + role=\"switch\"):立即生效的开 / 关设置,如“接收通知”。\n * 需要提交才生效的选项用 Checkbox。结构与样式见 choice-styles.ts:input 画成轨道,滑块叠在上面。\n *\n * <Switch _checked={notify}>接收通知</Switch>\n *\n * 读屏念“开关,开 / 关”;空格切换(原生)。在 Field 里时关联说明与错误、沿用其状态。\n * 切换要等接口时用 loading:滑块里转圈、点击无效。轨道里可以放文字或图标(checkedContent / uncheckedContent),对读屏隐藏。\n * 部件:Root(label)、Control(叠放层)、Thumb(滑块)、Content(轨道里的文字)、ContentText(文字的字号层)、Spinner、Label(文字);未声明的属性落到 input 上。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { useFieldControl } from '../form/Field';\nimport { Spinner, type SpinnerProps } from '../base/Spinner';\nimport { useDelayedLoading } from '../utils/motion/delayed-loading';\nimport { hasContent, mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport type { StatusTone } from '../utils/style/tone-styles';\nimport type { TextSize } from '../utils/style/typography';\nimport { choiceInputStyles, choiceParts, syncChecked, useChoiceAppearance } from './choice-styles';\nimport { t } from '../config/theme/tokens';\n\n/** 角色、勾选状态与可用性由组件管理;原生的 size 属性让给字号档位 */\nexport type SwitchManaged =\n | 'type'\n | 'role'\n | 'checked'\n | 'disabled'\n | 'required'\n | 'size'\n | 'aria-invalid'\n | 'aria-describedby'\n | 'aria-busy';\n\n/** 未声明的属性落到 input 上;外层 label 用 propsRoot */\nexport interface SwitchProps extends PartProps<'input', SwitchManaged> {\n /** 是否打开:父级写 _checked={x} */\n _checked?: boolean;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:能聚焦、读屏念“只读”,不能切换(查看详情、审批时);外观照常 */\n readonly?: boolean;\n /** 必填 */\n required?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 切换中(如等接口返回):滑块里显示加载指示,点击无效,带 aria-busy */\n loading?: boolean;\n /** 打开时轨道里的文字或图标(如“开”、对勾);给了它或 uncheckedContent 时轨道随内容加宽 */\n checkedContent?: VNodeChild;\n /** 关闭时轨道里的文字或图标 */\n uncheckedContent?: VNodeChild;\n /** 字号档位;不写时继承上下文字号 */\n size?: TextSize;\n /** 打开时轨道的色调(与 Button、Badge 等同一套),默认 accent;可以用 defaults.Choice 统一改 */\n tone?: StatusTone;\n /** 外层 label 的部件属性 */\n propsRoot?: PartProps<'label'>;\n /** 叠放层的部件属性 */\n propsControl?: PartProps<'span'>;\n /** 滑块的部件属性 */\n propsThumb?: PartProps<'span'>;\n /** 轨道里文字(开、关两份)的部件属性 */\n propsContent?: PartProps<'span'>;\n /** 轨道里文字的内层(定字号、字重)的部件属性;改字号写这里,外层的内边距才仍按开关的字号算 */\n propsContentText?: PartProps<'span'>;\n /** 加载指示的部件属性 */\n propsSpinner?: Partial<SpinnerProps>;\n /** 文字的部件属性 */\n propsLabel?: PartProps<'span'>;\n /** 文字 */\n children?: VNodeChild;\n}\n\n/** Switch 的样式:track、trackWide、trackOff、thumb、thumbOn、content、contentOn、contentOff、contentHidden、contentText、spinner */\nexport const switchStyles = css.create({\n track: { width: '2.25em', height: '1.25em', borderRadius: '_full', borderColor: 'transparent' },\n // 轨道里有文字:宽度随文字(两份文字叠在同一格里,取较宽的,切换时宽度不跳)\n trackWide: { width: '_full', minWidth: '2.25em' },\n trackOff: { backgroundColor: '_borderStrong' },\n // 滑块靠起始边,打开后移到结束边:用逻辑方向的外边距,从右到左排版自动反过来\n thumb: {\n display: 'grid',\n placeItems: 'center',\n justifySelf: 'start',\n width: '0.875em',\n height: '0.875em',\n marginInlineStart: '0.1875em',\n borderRadius: '_full',\n backgroundColor: '_background',\n boxShadow: '_sm',\n transition: `margin-inline-start ${t.durations.sm} ${t.easings.standard}`,\n },\n // 移到结束边:百分比相对整条轨道,轨道随文字加宽时同样贴边\n thumbOn: { marginInlineStart: 'calc(100% - 1.0625em)', backgroundColor: 'var(--tone-on-fill)' },\n // 用 flex 居中:按行内文字排时随外层的行高落在基线上,图标会比轨道中线偏下\n content: {\n gridArea: '1 / 1',\n justifySelf: 'stretch',\n alignSelf: 'center',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n whiteSpace: 'nowrap',\n pointerEvents: 'none',\n },\n // 文字在滑块的另一侧\n contentOn: {\n paddingInlineStart: '0.5em',\n paddingInlineEnd: '1.375em',\n color: 'var(--tone-on-fill)',\n },\n contentOff: { paddingInlineStart: '1.375em', paddingInlineEnd: '0.5em', color: '_text' },\n contentHidden: { visibility: 'hidden' },\n // 字号缩在里层:外层的内边距按开关的字号算,给滑块留的位置才够\n contentText: {\n display: 'flex',\n alignItems: 'center',\n fontSize: '_xs',\n fontWeight: '_semibold',\n lineHeight: 1,\n },\n spinner: { width: '0.75em', height: '0.75em', color: 'var(--tone-fill)' },\n});\n\n/** 开关:立即生效的开 / 关 */\nexport const Switch = _component(\n ({\n _checked: checked = _bindable(false),\n disabled,\n readonly,\n required,\n invalid,\n size,\n tone,\n loading = false,\n checkedContent,\n uncheckedContent,\n id,\n propsRoot,\n propsControl,\n propsThumb,\n propsContent,\n propsContentText,\n propsSpinner,\n propsLabel,\n children,\n ...rest\n }: SwitchProps) => {\n const control = useFieldControl(() => ({ id, invalid, required, disabled, readonly }));\n const appearance = useChoiceAppearance(() => ({ size, tone }));\n // 很快完成的切换不闪加载指示;点击拦截、aria-busy 按真实的 loading\n const spinner = useDelayedLoading(() => loading);\n return () => {\n const state = control();\n const s = choiceParts(appearance(), { disabled: state.disabled, readonly: state.readonly });\n const wide = checkedContent != null || uncheckedContent != null;\n const content = (on: boolean, child: VNodeChild) => (\n <span\n {...mergeAttrs<'span'>(\n {\n sx: [\n switchStyles.content,\n on ? switchStyles.contentOn : switchStyles.contentOff,\n on !== checked && switchStyles.contentHidden,\n ],\n },\n propsContent,\n { 'aria-hidden': true },\n )}\n >\n <span {...mergeAttrs<'span'>({ sx: switchStyles.contentText }, propsContentText)}>\n {child}\n </span>\n </span>\n );\n return (\n <label\n {...mergeAttrs<'label'>(s.root, propsRoot)}\n data-state={checked ? 'checked' : 'unchecked'}\n data-disabled={state.disabled || undefined}\n data-readonly={state.readonly || undefined}\n data-loading={loading || undefined}\n >\n <span {...mergeAttrs<'span'>(s.control, propsControl)}>\n <input\n {...mergeAttrs<'input'>(\n {\n ...s.input,\n sx: [\n s.input.sx,\n focusRingStyles.tight,\n switchStyles.track,\n wide && switchStyles.trackWide,\n checked ? choiceInputStyles.checked : switchStyles.trackOff,\n state.invalid && choiceInputStyles.invalid,\n ],\n },\n rest,\n {\n type: 'checkbox',\n role: 'switch',\n id: state.id,\n checked,\n disabled: state.disabled,\n required: state.required,\n 'aria-invalid': state.invalid || undefined,\n 'aria-readonly': state.readonly || undefined,\n 'aria-describedby': state.describedBy,\n 'aria-busy': loading || undefined,\n // 切换中、只读时不接受切换:拦下 click,勾选状态就不变\n onClick: (event: MouseEvent) => {\n if (loading || state.readonly) event.preventDefault();\n },\n onChange: (event: Event) => {\n const target = event.target as HTMLInputElement;\n checked = target.checked;\n syncChecked([target], () => checked);\n },\n },\n )}\n />\n {wide && content(true, checkedContent)}\n {wide && content(false, uncheckedContent)}\n <span\n {...mergeAttrs<'span'>(\n {\n ...s.indicator,\n sx: [s.indicator.sx, switchStyles.thumb, checked && switchStyles.thumbOn],\n },\n propsThumb,\n )}\n >\n {spinner.value && (\n <Spinner\n {...mergePartProps<SpinnerProps>(\n { propsIcon: { sx: switchStyles.spinner } },\n propsSpinner,\n )}\n />\n )}\n </span>\n </span>\n {hasContent(children) && (\n <span {...mergeAttrs<'span'>(s.label, propsLabel)}>{children}</span>\n )}\n </label>\n );\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"Switch.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../src/input/Switch.tsx"],"sourcesContent":["/**\n * 开关(原生 input type=\"checkbox\" + role=\"switch\"):立即生效的开 / 关设置,如“接收通知”。\n * 需要提交才生效的选项用 Checkbox。结构与样式见 choice-styles.ts:input 画成轨道,滑块叠在上面。\n *\n * <Switch _checked={notify}>接收通知</Switch>\n *\n * 读屏念“开关,开 / 关”;空格切换(原生)。在 Field 里时关联说明与错误、沿用其状态。\n * 切换要等接口时用 loading:滑块里转圈、点击无效。轨道里可以放文字或图标(checkedContent / uncheckedContent),对读屏隐藏。\n * 部件:Root(label)、Control(叠放层)、Thumb(滑块)、Content(轨道里的文字)、ContentText(文字的字号层)、Spinner、Label(文字);未声明的属性落到 input 上。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { useFieldControl } from '../form/Field';\nimport { Spinner, type SpinnerProps } from '../base/Spinner';\nimport { useDelayedLoading } from '../utils/motion/delayed-loading';\nimport { hasContent, mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport type { StatusTone } from '../utils/style/tone-styles';\nimport type { TextSize } from '../utils/style/typography';\nimport { choiceInputStyles, choiceParts, syncChecked, useChoiceAppearance } from './choice-styles';\nimport { t } from '../config/theme/tokens';\n\n/** 角色、勾选状态与可用性由组件管理;原生的 size 属性让给字号档位 */\nexport type SwitchManaged =\n | 'type'\n | 'role'\n | 'checked'\n | 'disabled'\n | 'required'\n | 'size'\n | 'aria-invalid'\n | 'aria-describedby'\n | 'aria-busy';\n\n/** 未声明的属性落到 input 上;外层 label 用 propsRoot */\nexport interface SwitchProps extends PartProps<'input', SwitchManaged> {\n /** 是否打开:父级写 _checked={x} */\n _checked?: boolean;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:能聚焦、读屏念“只读”,不能切换(查看详情、审批时);外观照常 */\n readonly?: boolean;\n /** 必填 */\n required?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 切换中(如等接口返回):滑块里显示加载指示,点击无效,带 aria-busy */\n loading?: boolean;\n /** 打开时轨道里的文字或图标(如“开”、对勾);给了它或 uncheckedContent 时轨道随内容加宽 */\n checkedContent?: VNodeChild;\n /** 关闭时轨道里的文字或图标 */\n uncheckedContent?: VNodeChild;\n /** 字号档位;不写时继承上下文字号 */\n size?: TextSize;\n /** 打开时轨道的色调(与 Button、Badge 等同一套),默认 accent;可以用 defaults.Choice 统一改 */\n tone?: StatusTone;\n /** 外层 label 的部件属性 */\n propsRoot?: PartProps<'label'>;\n /** 叠放层的部件属性 */\n propsControl?: PartProps<'span'>;\n /** 滑块的部件属性 */\n propsThumb?: PartProps<'span'>;\n /** 轨道里文字(开、关两份)的部件属性 */\n propsContent?: PartProps<'span'>;\n /** 轨道里文字的内层(定字号、字重)的部件属性;改字号写这里,外层的内边距才仍按开关的字号算 */\n propsContentText?: PartProps<'span'>;\n /** 加载指示的部件属性 */\n propsSpinner?: Partial<SpinnerProps>;\n /** 文字的部件属性 */\n propsLabel?: PartProps<'span'>;\n /** 文字 */\n children?: VNodeChild;\n}\n\n/** Switch 的样式:track、trackWide、trackOff、thumb、thumbOn、content、contentOn、contentOff、contentHidden、contentText、spinner */\nexport const switchStyles = css.create({\n track: { width: '2.25em', height: '1.25em', borderRadius: '_full', borderColor: 'transparent' },\n // 轨道里有文字:宽度随文字(两份文字叠在同一格里,取较宽的,切换时宽度不跳)\n trackWide: { width: '_full', minWidth: '2.25em' },\n trackOff: { backgroundColor: '_borderStrong' },\n // 滑块靠起始边,打开后移到结束边:用逻辑方向的外边距,从右到左排版自动反过来\n thumb: {\n display: 'grid',\n placeItems: 'center',\n justifySelf: 'start',\n width: '0.875em',\n height: '0.875em',\n marginInlineStart: '0.1875em',\n borderRadius: '_full',\n backgroundColor: '_background',\n boxShadow: '_sm',\n transition: `margin-inline-start ${t.durations.sm} ${t.easings.standard}`,\n },\n // 移到结束边:百分比相对整条轨道,轨道随文字加宽时同样贴边\n thumbOn: { marginInlineStart: 'calc(100% - 1.0625em)', backgroundColor: 'var(--tone-on-fill)' },\n // 用 flex 居中:按行内文字排时随外层的行高落在基线上,图标会比轨道中线偏下\n content: {\n gridArea: '1 / 1',\n justifySelf: 'stretch',\n alignSelf: 'center',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n whiteSpace: 'nowrap',\n pointerEvents: 'none',\n },\n // 文字在滑块的另一侧\n contentOn: {\n paddingInlineStart: '0.5em',\n paddingInlineEnd: '1.375em',\n color: 'var(--tone-on-fill)',\n },\n contentOff: { paddingInlineStart: '1.375em', paddingInlineEnd: '0.5em', color: '_text' },\n contentHidden: { visibility: 'hidden' },\n // 字号缩在里层:外层的内边距按开关的字号算,给滑块留的位置才够\n contentText: {\n display: 'flex',\n alignItems: 'center',\n fontSize: '_xs',\n fontWeight: '_semibold',\n lineHeight: 1,\n },\n spinner: { width: '0.75em', height: '0.75em', color: 'var(--tone-fill)' },\n});\n\n/** 开关:立即生效的开 / 关 */\nexport const Switch = _component(\n ({\n _checked: checked = _bindable(false),\n disabled,\n readonly,\n required,\n invalid,\n size,\n tone,\n loading = false,\n checkedContent,\n uncheckedContent,\n id,\n propsRoot,\n propsControl,\n propsThumb,\n propsContent,\n propsContentText,\n propsSpinner,\n propsLabel,\n children,\n ...rest\n }: SwitchProps) => {\n const control = useFieldControl(() => ({ id, invalid, required, disabled, readonly }));\n const appearance = useChoiceAppearance(() => ({ size, tone }));\n // 很快完成的切换不闪加载指示;点击拦截、aria-busy 按真实的 loading\n const spinner = useDelayedLoading(() => loading);\n return () => {\n const state = control();\n const s = choiceParts(appearance(), { disabled: state.disabled, readonly: state.readonly });\n const wide = checkedContent != null || uncheckedContent != null;\n const content = (on: boolean, child: VNodeChild) => (\n <span\n {...mergeAttrs<'span'>(\n {\n sx: [\n switchStyles.content,\n on ? switchStyles.contentOn : switchStyles.contentOff,\n on !== checked && switchStyles.contentHidden,\n ],\n },\n propsContent,\n { 'aria-hidden': true },\n )}\n >\n <span {...mergeAttrs<'span'>({ sx: switchStyles.contentText }, propsContentText)}>\n {child}\n </span>\n </span>\n );\n return (\n <label\n {...mergeAttrs<'label'>(s.root, propsRoot)}\n data-state={checked ? 'checked' : 'unchecked'}\n data-disabled={state.disabled || undefined}\n data-readonly={state.readonly || undefined}\n data-loading={loading || undefined}\n >\n <span {...mergeAttrs<'span'>(s.control, propsControl)}>\n <input\n {...mergeAttrs<'input'>(\n {\n ...s.input,\n sx: [\n s.input.sx,\n focusRingStyles.tight,\n switchStyles.track,\n wide && switchStyles.trackWide,\n checked ? choiceInputStyles.checked : switchStyles.trackOff,\n state.invalid && choiceInputStyles.invalid,\n ],\n },\n rest,\n {\n type: 'checkbox',\n role: 'switch',\n id: state.id,\n checked,\n disabled: state.disabled,\n required: state.required,\n 'aria-invalid': state.invalid || undefined,\n 'aria-readonly': state.readonly || undefined,\n 'aria-describedby': state.describedBy,\n 'aria-busy': loading || undefined,\n // 切换中、只读时不接受切换:拦下 click,勾选状态就不变\n onClick: (event: MouseEvent) => {\n if (loading || state.readonly) event.preventDefault();\n },\n onChange: (event: Event) => {\n const target = event.target as HTMLInputElement;\n checked = target.checked;\n syncChecked([target], () => checked);\n },\n },\n )}\n />\n {wide && content(true, checkedContent)}\n {wide && content(false, uncheckedContent)}\n <span\n {...mergeAttrs<'span'>(\n {\n ...s.indicator,\n sx: [s.indicator.sx, switchStyles.thumb, checked && switchStyles.thumbOn],\n },\n propsThumb,\n )}\n >\n {spinner.value && (\n <Spinner\n {...mergePartProps<SpinnerProps>(\n { propsIcon: { sx: switchStyles.spinner } },\n propsSpinner,\n )}\n />\n )}\n </span>\n </span>\n {hasContent(children) && (\n <span {...mergeAttrs<'span'>(s.label, propsLabel)}>{children}</span>\n )}\n </label>\n );\n };\n },\n);\n"],"mappings":";;;;;;;;;;;;;;AA4EA,IAAa,eAAe,IAAI,OAAO;CACrC,OAAO;EAAE,OAAO;EAAU,QAAQ;EAAU,cAAc;EAAS,aAAa;CAAc;CAE9F,WAAW;EAAE,OAAO;EAAS,UAAU;CAAS;CAChD,UAAU,EAAE,iBAAiB,gBAAgB;CAE7C,OAAO;EACL,SAAS;EACT,YAAY;EACZ,aAAa;EACb,OAAO;EACP,QAAQ;EACR,mBAAmB;EACnB,cAAc;EACd,iBAAiB;EACjB,WAAW;EACX,YAAY,uBAAuB,EAAE,UAAU,GAAE,GAAI,EAAE,QAAQ;CACjE;CAEA,SAAS;EAAE,mBAAmB;EAAyB,iBAAiB;CAAsB;CAE9F,SAAS;EACP,UAAU;EACV,aAAa;EACb,WAAW;EACX,SAAS;EACT,YAAY;EACZ,gBAAgB;EAChB,YAAY;EACZ,eAAe;CACjB;CAEA,WAAW;EACT,oBAAoB;EACpB,kBAAkB;EAClB,OAAO;CACT;CACA,YAAY;EAAE,oBAAoB;EAAW,kBAAkB;EAAS,OAAO;CAAQ;CACvF,eAAe,EAAE,YAAY,SAAS;CAEtC,aAAa;EACX,SAAS;EACT,YAAY;EACZ,UAAU;EACV,YAAY;EACZ,YAAY;CACd;CACA,SAAS;EAAE,OAAO;EAAU,QAAQ;EAAU,OAAO;CAAmB;AAC1E,CAAC;;AAGD,IAAa,SAAS,0BACpB,QAAA,SAqBmB;CAAA,MAAA,UAAAA,SAAA,QAAA,kBApBa,OAAK,KAAA,IAAA;CAAA,MAAA,WAAAC,aAAA,QAAA,UAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,UAAAA,aAAA,QAAA,SAAA;CAAA,MAAA,OAAAA,aAAA,QAAA,MAAA;CAAA,MAAA,OAAAA,aAAA,QAAA,MAAA;CAAA,MAAA,UAAAA,aAAA,QAAA,WAOzB,KAAK;CAAA,MAAA,iBAAAA,aAAA,QAAA,gBAAA;CAAA,MAAA,mBAAAA,aAAA,QAAA,kBAAA;CAAA,MAAA,KAAAA,aAAA,QAAA,IAAA;CAAA,MAAA,YAAAA,aAAA,QAAA,WAAA;CAAA,MAAA,eAAAA,aAAA,QAAA,cAAA;CAAA,MAAA,aAAAA,aAAA,QAAA,YAAA;CAAA,MAAA,eAAAA,aAAA,QAAA,cAAA;CAAA,MAAA,mBAAAA,aAAA,QAAA,kBAAA;CAAA,MAAA,eAAAA,aAAA,QAAA,cAAA;CAAA,MAAA,aAAAA,aAAA,QAAA,YAAA;CAAA,MAAA,WAAAC,aAAA,MAAA;CAAA,MAYZ,OAAIC,UAAA,QAAA,MAAA,KAAA;CAEP,MAAM,UAAU,uBAAuB;EAAE,IAAE,GAAA;EAAE,SAAO,QAAA;EAAE,UAAQ,SAAA;EAAE,UAAQ,SAAA;EAAE,UAAQ,SAAA;CAAC,EAAE;CACrF,MAAM,aAAa,2BAA2B;EAAE,MAAI,KAAA;EAAE,MAAI,KAAA;CAAC,EAAE;CAE7D,MAAM,UAAU,wBAAkB,QAAA,KAAa;CAC/C,aAAa;EACX,MAAM,QAAQ,QAAQ;EACtB,MAAM,IAAI,YAAY,WAAW,GAAG;GAAE,UAAU,MAAM;GAAU,UAAU,MAAM;EAAS,CAAC;EAC1F,MAAM,OAAO,eAAA,SAAkB,QAAQ,iBAAA,SAAoB;EAC3D,MAAM,WAAW,IAAa,UAAiBC,YAAA,QAEvC,WACF,EACE,IAAI;GACF,aAAa;GACb,KAAK,aAAa,YAAY,aAAa;GAC3C,OAAE,QAAA,SAAgB,aAAa;EAAa,EAEhD,GAAC,aAAA,OAED,EAAE,eAAe,KAAK,CACxB,GAAC,CAAAA,YAAA,QAES,WAAmB,EAAE,IAAI,aAAa,YAAY,GAAC,iBAAA,KAAkB,GAAC,CAC7E,KAAK,CAAA,CAAA,CAAA;EAIZ,OAAAA,YAAA,SAAAC,cAEQ,WAAoB,EAAE,MAAI,UAAA,KAAW,GAAC;GAAA,cAC9B,QAAA,QAAU,YAAY;GAAW,iBAC9B,MAAM,YAAY,KAAA;GAAS,iBAC3B,MAAM,YAAY,KAAA;GAAS,gBAC5B,QAAA,SAAW,KAAA;EAAS,CAAA,GAAA,CAAAD,YAAA,QAExB,WAAmB,EAAE,SAAO,aAAA,KAAc,GAAC;GAAAA,YAAA,SAE7C,WACF;IACE,GAAG,EAAE;IACL,IAAI;KACF,EAAE,MAAM;KACR,gBAAgB;KAChB,aAAa;KACb,QAAQ,aAAa;KACrB,QAAA,QAAU,kBAAkB,UAAU,aAAa;KACnD,MAAM,WAAW,kBAAkB;IAAO;GAE9C,GACA,MACA;IACE,MAAM;IACN,MAAM;IACN,IAAI,MAAM;IACV,SAAO,QAAA;IACP,UAAU,MAAM;IAChB,UAAU,MAAM;IAChB,gBAAgB,MAAM,WAAW,KAAA;IACjC,iBAAiB,MAAM,YAAY,KAAA;IACnC,oBAAoB,MAAM;IAC1B,aAAa,QAAA,SAAW,KAAA;IAExB,UAAU,UAAsB;KAC9B,IAAI,QAAA,SAAW,MAAM,UAAU,MAAM,eAAe;IACtD;IACA,WAAW,UAAiB;KAC1B,MAAM,SAAS,MAAM;KACrB,QAAA,QAAU,OAAO;KACjB,YAAY,CAAC,MAAM,SAAG,QAAA,KAAa;IACrC;GACF,CACF,GAAC,IAAA;GAEF,QAAQ,QAAQ,MAAI,eAAA,KAAgB;GACpC,QAAQ,QAAQ,OAAK,iBAAA,KAAkB;GAACA,YAAA,QAEnC,WACF;IACE,GAAG,EAAE;IACL,IAAI;KAAC,EAAE,UAAU;KAAI,aAAa;KAAO,QAAA,SAAW,aAAa;IAAO;GAC1E,GAAC,WAAA,KAEH,GAAC,CAEA,QAAQ,SAAKA,YAAA,SAEN,eACF,EAAE,WAAW,EAAE,IAAI,aAAa,QAAQ,EAAE,GAAC,aAAA,KAE7C,GAAC,IAAA,CAEJ,CAAA;EAAA,CAAA,GAGJ,WAAU,SAAA,KAAS,KAACA,YAAA,QACT,WAAmB,EAAE,OAAK,WAAA,KAAY,GAAC,CAAA,SAAA,KAAA,CAAA,CAClD,CAAA;CAGP;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;CAAA;AAAA,CACH"}
@@ -11,8 +11,8 @@ import { controlClear, controlIcon, controlParts, focusOnShell, useControlAppear
11
11
  import { activeOptionId } from "./Listbox.js";
12
12
  import { FormValue } from "../form/FormValue.js";
13
13
  import { ListPopover } from "./ListPopover.js";
14
- import { Fragment, createVNode, isVNode, mergeProps, shallowRef, useId, vModelText, watch, withDirectives } from "vue";
15
- import { _component, bindable, childrenProp, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
14
+ import { Fragment, createVNode, isVNode, shallowRef, useId, vModelText, watch, withDirectives } from "vue";
15
+ import { _component, bindable, childrenProp, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
16
16
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
17
17
  //#region src/input/TagsInput.tsx
18
18
  /** 角色、展开状态与可用性由组件管理 */
@@ -198,7 +198,7 @@ var TagsInput = /*#__PURE__*/ _component((_props, _ctx) => {
198
198
  const state = control();
199
199
  const s = controlParts(appearance(), state);
200
200
  const editable = !state.disabled && !state.readonly;
201
- return createVNode(Fragment, null, [createVNode("div", mergeProps(mergeAttrs({
201
+ return createVNode(Fragment, null, [createVNode("div", mergeJsxProps(mergeAttrs({
202
202
  ...s.root,
203
203
  sx: [s.root.sx, tagsInputStyles.root]
204
204
  }, propsRoot.value, {
@@ -214,9 +214,9 @@ var TagsInput = /*#__PURE__*/ _component((_props, _ctx) => {
214
214
  value.value.map((tag) => {
215
215
  let _slot;
216
216
  const own = typeof propsTag.value === "function" ? propsTag.value(tag) : propsTag.value;
217
- return createVNode(Tag, mergeProps({ "key": tag }, mergePartProps({ variant: "surface" }, own, { onRemove: editable ? () => remove(tag) : void 0 }), { "data-tag": "" }), _isSlot(_slot = labelOf(tag)) ? _slot : { default: () => [_slot] });
217
+ return createVNode(Tag, mergeJsxProps({ "key": tag }, mergePartProps({ variant: "surface" }, own, { onRemove: editable ? () => remove(tag) : void 0 }), { "data-tag": "" }), _isSlot(_slot = labelOf(tag)) ? _slot : { default: () => [_slot] });
218
218
  }),
219
- withDirectives(createVNode("input", mergeProps(mergeAttrs({
219
+ withDirectives(createVNode("input", mergeJsxProps(mergeAttrs({
220
220
  ...s.input,
221
221
  sx: [s.input.sx, tagsInputStyles.input]
222
222
  }, rest, {
@@ -1 +1 @@
1
- {"version":3,"file":"TagsInput.js","names":["_isVNode","_vtp_bindable","_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_vue_shallowRef","_createVNode","_Fragment","_mergeProps","_withDirectives","_vModelText"],"sources":["../../src/input/TagsInput.tsx"],"sourcesContent":["/**\n * 标签输入(多选的组合框):输入框里排着已选的 Tag,输入文字后回车(或输入逗号)加一个,可以从建议列表里选。\n * 关键词、收件人、标签、多个城市。参考 Mantine TagsInput、React Aria TagGroup + ComboBox。\n *\n * <TagsInput _value={keywords} aria-label=\"关键词\" /> 自由输入\n * <TagsInput _value={cities} items={cityOptions} allowCustomValue={false} /> 只能从建议里选\n *\n * - 回车、输入分隔符(默认 , , ; ;)把文字加成标签;粘贴时按分隔符与换行拆成多个;重复的不加;\n * - 输入框为空时按退格删掉最后一个标签;每个标签有移除按钮(离场后其余的平移补位);\n * - 有 items 时边输入边过滤建议(同 Combobox),↑↓ 移动、回车加入或移除高亮项(已选的打勾);\n * 异步取建议时绑定 inputValue 去请求、写 filter={false} 与 loading,结果没回来时列表显示加载中;\n * - 写了 name 时每个值一个隐藏的 input 随表单提交。\n *\n * 未声明的属性落到 input(主元素)上。部件:Root(外壳)、Tag、Input、Clear、Popover、Listbox。\n */\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 { Tag, type TagProps } from '../base/Tag';\nimport { useTextMatcher } from '../config/context';\nimport { isComposingKey } from '../utils/dom/hotkeys';\nimport { useAnchoredPopover, type FloatingPlacement } from '../utils/dom/floating';\nimport { openSetter, type OpenChangeProps } from '../utils/dom/open-change';\nimport { ListPopover } from './ListPopover';\nimport { useLayoutAnimation } from '../utils/motion/layout';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport {\n controlClear,\n controlParts,\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 { activeOptionId, type ListboxViewProps, type OptionRenderState } from './Listbox';\nimport {\n handleListKeydown,\n useListState,\n useSelectedOptions,\n type ListboxOption,\n type OptionMapping,\n toListboxOption,\n} from './list-state';\n\n/** 角色、展开状态与可用性由组件管理 */\nexport type TagsInputManaged =\n | 'value'\n | 'role'\n | 'size'\n | 'disabled'\n | 'readonly'\n | 'autocomplete'\n | 'aria-autocomplete'\n | 'aria-expanded'\n | 'aria-controls'\n | 'aria-activedescendant'\n | 'aria-invalid'\n | 'aria-required'\n | 'aria-describedby';\n\n/** TagsInput 除 toOption 外的属性;未声明的属性落到 input(主元素)上,外壳用 propsRoot */\nexport interface TagsInputBaseProps<T>\n extends\n PartProps<'input', TagsInputManaged>,\n ControlOptions,\n ControlIconOptions,\n OpenChangeProps {\n /** 已选的值:父级写 _value={list} */\n _value?: string[];\n /** 建议:ListboxOption、字符串,或任意数据加 toOption;不给时是纯自由输入 */\n items?: readonly T[];\n /** 允许加入不在建议里的文字,默认 true */\n allowCustomValue?: boolean;\n /** 失焦时把输入框里还没确认的文字加成标签,默认 true(同 Mantine);false 时文字留在框里 */\n acceptOnBlur?: boolean;\n /** 把输入拆成标签的分隔符,默认 [',', ',', ';', ';'];回车与粘贴里的换行总是分隔 */\n delimiters?: readonly string[];\n /** 最多几个标签;到了上限不再加入 */\n max?: number;\n /** 输入框里的文字:父级可以写 _inputValue={x}(异步取建议时据此搜索) */\n _inputValue?: string;\n /** 建议列表是否打开 */\n _open?: boolean;\n /** 过滤建议:默认按显示文字包含输入;false 不过滤(异步搜索) */\n filter?: false | ((item: T, query: string) => boolean);\n /** 正在取建议 */\n loading?: boolean;\n /** 弹出位置,默认 bottom-start */\n placement?: FloatingPlacement;\n /** 有标签时显示清空按钮 */\n clearable?: boolean;\n /** 表单提交时的 name(每个值一个隐藏的 input) */\n name?: string;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:标签不能移除,不能输入 */\n readonly?: boolean;\n /** 必填:至少要有一个标签(读屏念“必填”;校验交给表单) */\n required?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 自定义建议的内容 */\n children?: (item: T, state: OptionRenderState) => VNodeChild;\n /** 外壳的部件属性 */\n propsRoot?: PartProps<'div'>;\n /** 每个标签的部件属性,可以按值计算 */\n propsTag?: Partial<TagProps> | ((value: string) => Partial<TagProps>);\n /** 清空按钮的部件属性 */\n propsClear?: Partial<PresetIconButtonProps>;\n /** 弹出层的部件属性 */\n propsPopover?: PartProps<'div', 'id' | 'popover'>;\n /** 建议列表的部件属性 */\n propsListbox?: Partial<ListboxViewProps<T>>;\n}\n\n/** 标签输入的属性;items 不是 ListboxOption 或字符串时要给 toOption */\nexport type TagsInputProps<T = ListboxOption> = TagsInputBaseProps<T> & OptionMapping<T>;\n\n/** TagsInput 的样式:root、input、popover */\nexport const tagsInputStyles = css.create({\n // 标签多了换行;行与行之间留出间距\n root: { flexWrap: 'wrap', rowGap: '_xs', paddingBlock: '_xs' },\n // 输入框至少留出几个字的位置,放不下时换到下一行\n input: { flexBasis: '6em' },\n});\n\n/** 默认的分隔符:英文、中文的逗号与分号 */\nconst DELIMITERS = [',', ',', ';', ';'];\n\n/** 标签输入:输入框里排着 Tag,回车或分隔符加入,退格删最后一个 */\nexport const TagsInput = _component(\n <T = ListboxOption,>({\n _value: value = _bindable<string[]>([]),\n items = [],\n toOption,\n allowCustomValue = true,\n acceptOnBlur = true,\n delimiters = DELIMITERS,\n max,\n _inputValue: inputValue = _bindable(''),\n _open: open = _bindable(false),\n onOpenChange,\n filter,\n loading = false,\n placement = 'bottom-start',\n clearable = false,\n name,\n variant,\n size,\n radius,\n disabled,\n readonly,\n required,\n invalid,\n id,\n children,\n propsRoot,\n icon,\n propsIcon,\n propsTag,\n propsClear,\n propsPopover,\n propsListbox,\n ...rest\n }: TagsInputProps<T>) => {\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 let shell = _state.raw<HTMLElement | null>(null);\n let input = _state.raw<HTMLInputElement | null>(null);\n let panel = _state.raw<HTMLElement | null>(null);\n // 标签增删时其余的平移补位\n const layout = useLayoutAnimation(() => shell, { children: '[data-tag]' });\n\n const setOpen = openSetter(\n () => open,\n (next) => (open = next),\n () => onOpenChange,\n );\n const optionOf = (item: T) => toListboxOption(item, toOption);\n // 异步搜索(filter={false})时结果可能还没回来:建议列表与 combobox 角色一直在,等待时显示加载中\n const suggestions = () => items.length > 0 || filter === false;\n // 标签的文字:异步建议换了 items 之后,已选的仍按之前见过的文字显示;自定义的值就是文字\n const selectedOf = useSelectedOptions({ items: () => items, toOption: optionOf });\n const labelOf = (tag: string) => selectedOf([tag])[0]!.label;\n\n const list = useListState({\n items: () => {\n const query = inputValue.trim();\n if (filter === false || !query) return items;\n const matcher = textMatcher();\n return items.filter((item) =>\n filter ? filter(item, query) : matcher(optionOf(item).label, query),\n );\n },\n toOption: optionOf,\n selected: () => value,\n mode: () => 'multiple',\n onChange: (next) => void layout.change(() => (value = [...next])),\n });\n\n /** 把一段文字变成值:是建议的文字或值时取建议的值,否则(允许时)原样 */\n function resolve(text: string): string | undefined {\n const trimmed = text.trim();\n if (!trimmed) return undefined;\n const item = items.find((candidate) => {\n const option = optionOf(candidate);\n return option.value === trimmed || option.label === trimmed;\n });\n if (item !== undefined) return optionOf(item).value;\n return allowCustomValue ? trimmed : undefined;\n }\n\n /** 加入几段文字;重复的、超出上限的不加;返回是否加入了 */\n function add(texts: readonly string[]) {\n const next = [...value];\n for (const text of texts) {\n const tag = resolve(text);\n if (tag === undefined || next.includes(tag) || (max != null && next.length >= max))\n continue;\n next.push(tag);\n }\n if (next.length === value.length) return false;\n void layout.change(() => (value = next));\n return true;\n }\n\n const remove = (tag: string) =>\n void layout.change(() => (value = value.filter((item) => item !== tag)));\n\n const splitter = () =>\n new RegExp(\n `[${[...delimiters, '\\n', '\\r', '\\t'].map((d) => d.replace(/[\\\\\\]^-]/g, '\\\\$&')).join('')}]`,\n );\n\n // 输入了分隔符:分隔符前的部分加成标签,剩下的留在输入框里\n watch(\n () => inputValue,\n (text) => {\n const parts = text.split(splitter());\n if (parts.length > 1) {\n add(parts.slice(0, -1));\n inputValue = parts.at(-1)!;\n return;\n }\n if (suggestions() && text && !control().readonly) {\n setOpen(true, 'trigger');\n list.move('first');\n }\n },\n );\n\n function onKeydown(event: KeyboardEvent) {\n const state = control();\n if (state.disabled || state.readonly || isComposingKey(event)) return;\n if (event.key === 'Backspace' && !inputValue && value.length) {\n event.preventDefault();\n remove(value.at(-1)!);\n return;\n }\n if (open && suggestions()) {\n if (handleListKeydown(list, event, { homeEnd: false })) {\n event.preventDefault();\n if (event.key === 'Enter') inputValue = '';\n return;\n }\n } else if (event.key === 'ArrowDown' && suggestions()) {\n event.preventDefault();\n list.activateDefault();\n setOpen(true, 'trigger', event);\n return;\n }\n if (event.key === 'Enter' && inputValue.trim()) {\n event.preventDefault();\n if (add([inputValue])) inputValue = '';\n }\n }\n\n // 粘贴多段(有分隔符、换行)时拆开加入;只有一段时照常粘贴\n function onPaste(event: ClipboardEvent) {\n const text = event.clipboardData?.getData('text') ?? '';\n const parts = text.split(splitter());\n if (parts.length < 2) return;\n event.preventDefault();\n add(parts);\n }\n\n const { onToggle } = useAnchoredPopover(\n () => ({\n open: open && suggestions(),\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 return () => {\n const state = control();\n const s = controlParts(appearance(), state);\n const editable = !state.disabled && !state.readonly;\n return (\n <>\n <div\n {...mergeAttrs<'div'>({ ...s.root, sx: [s.root.sx, tagsInputStyles.root] }, propsRoot, {\n ref: _toRef(shell),\n // 外壳里的标签不是原生控件的一部分:不可用要写在外壳上,辅助技术才把它们一起当作不可用\n 'aria-disabled': state.disabled || undefined,\n onPointerdown: focusOnShell(() => input),\n })}\n data-state={open ? 'open' : 'closed'}\n data-invalid={state.invalid || undefined}\n data-disabled={state.disabled || undefined}\n >\n {controlIcon(s, icon, propsIcon)}\n {value.map((tag) => {\n const own = typeof propsTag === 'function' ? propsTag(tag) : propsTag;\n return (\n <Tag\n key={tag}\n {...mergePartProps<TagProps>({ variant: 'surface' }, own, {\n onRemove: editable ? () => remove(tag) : undefined,\n })}\n data-tag=\"\"\n >\n {labelOf(tag)}\n </Tag>\n );\n })}\n <input\n {...mergeAttrs<'input'>(\n { ...s.input, sx: [s.input.sx, tagsInputStyles.input] },\n rest,\n {\n ref: _toRef(input),\n id: state.id,\n role: suggestions() ? 'combobox' : undefined,\n autocomplete: 'off',\n disabled: state.disabled,\n readonly: state.readonly,\n 'aria-autocomplete': suggestions() ? 'list' : undefined,\n 'aria-expanded': suggestions() ? open : undefined,\n 'aria-controls': suggestions() ? listId : undefined,\n 'aria-activedescendant':\n open && suggestions() ? activeOptionId(list, listId) : undefined,\n 'aria-invalid': state.invalid || undefined,\n 'aria-required': state.required || undefined,\n 'aria-describedby': state.describedBy,\n onKeydown,\n onPaste,\n onBlur: (event: FocusEvent) => {\n setOpen(false, 'focus', event);\n if (\n acceptOnBlur &&\n inputValue.trim() &&\n !control().readonly &&\n add([inputValue])\n )\n inputValue = '';\n },\n },\n )}\n _value={inputValue}\n />\n {clearable &&\n value.length > 0 &&\n editable &&\n controlClear(s, propsClear, () => {\n void layout.change(() => (value = []));\n input?.focus();\n })}\n <FormValue name={name} value={value} disabled={state.disabled} />\n </div>\n {suggestions() && (\n <ListPopover\n panelRef={_toRef(panel)}\n onToggle={onToggle}\n size={appearance().size}\n labelledBy={state.labelledBy}\n label={rest['aria-label']}\n loading={loading}\n onPick={() => {\n inputValue = '';\n input?.focus();\n }}\n listbox={{ list, id: listId, multiple: true, renderOption: children }}\n propsListbox={propsListbox}\n propsPopover={propsPopover}\n />\n )}\n </>\n );\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"TagsInput.js","names":["_isVNode","_vtp_bindable","_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_vue_shallowRef","_createVNode","_Fragment","_mergeProps","_withDirectives","_vModelText"],"sources":["../../src/input/TagsInput.tsx"],"sourcesContent":["/**\n * 标签输入(多选的组合框):输入框里排着已选的 Tag,输入文字后回车(或输入逗号)加一个,可以从建议列表里选。\n * 关键词、收件人、标签、多个城市。参考 Mantine TagsInput、React Aria TagGroup + ComboBox。\n *\n * <TagsInput _value={keywords} aria-label=\"关键词\" /> 自由输入\n * <TagsInput _value={cities} items={cityOptions} allowCustomValue={false} /> 只能从建议里选\n *\n * - 回车、输入分隔符(默认 , , ; ;)把文字加成标签;粘贴时按分隔符与换行拆成多个;重复的不加;\n * - 输入框为空时按退格删掉最后一个标签;每个标签有移除按钮(离场后其余的平移补位);\n * - 有 items 时边输入边过滤建议(同 Combobox),↑↓ 移动、回车加入或移除高亮项(已选的打勾);\n * 异步取建议时绑定 inputValue 去请求、写 filter={false} 与 loading,结果没回来时列表显示加载中;\n * - 写了 name 时每个值一个隐藏的 input 随表单提交。\n *\n * 未声明的属性落到 input(主元素)上。部件:Root(外壳)、Tag、Input、Clear、Popover、Listbox。\n */\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 { Tag, type TagProps } from '../base/Tag';\nimport { useTextMatcher } from '../config/context';\nimport { isComposingKey } from '../utils/dom/hotkeys';\nimport { useAnchoredPopover, type FloatingPlacement } from '../utils/dom/floating';\nimport { openSetter, type OpenChangeProps } from '../utils/dom/open-change';\nimport { ListPopover } from './ListPopover';\nimport { useLayoutAnimation } from '../utils/motion/layout';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport {\n controlClear,\n controlParts,\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 { activeOptionId, type ListboxViewProps, type OptionRenderState } from './Listbox';\nimport {\n handleListKeydown,\n useListState,\n useSelectedOptions,\n type ListboxOption,\n type OptionMapping,\n toListboxOption,\n} from './list-state';\n\n/** 角色、展开状态与可用性由组件管理 */\nexport type TagsInputManaged =\n | 'value'\n | 'role'\n | 'size'\n | 'disabled'\n | 'readonly'\n | 'autocomplete'\n | 'aria-autocomplete'\n | 'aria-expanded'\n | 'aria-controls'\n | 'aria-activedescendant'\n | 'aria-invalid'\n | 'aria-required'\n | 'aria-describedby';\n\n/** TagsInput 除 toOption 外的属性;未声明的属性落到 input(主元素)上,外壳用 propsRoot */\nexport interface TagsInputBaseProps<T>\n extends\n PartProps<'input', TagsInputManaged>,\n ControlOptions,\n ControlIconOptions,\n OpenChangeProps {\n /** 已选的值:父级写 _value={list} */\n _value?: string[];\n /** 建议:ListboxOption、字符串,或任意数据加 toOption;不给时是纯自由输入 */\n items?: readonly T[];\n /** 允许加入不在建议里的文字,默认 true */\n allowCustomValue?: boolean;\n /** 失焦时把输入框里还没确认的文字加成标签,默认 true(同 Mantine);false 时文字留在框里 */\n acceptOnBlur?: boolean;\n /** 把输入拆成标签的分隔符,默认 [',', ',', ';', ';'];回车与粘贴里的换行总是分隔 */\n delimiters?: readonly string[];\n /** 最多几个标签;到了上限不再加入 */\n max?: number;\n /** 输入框里的文字:父级可以写 _inputValue={x}(异步取建议时据此搜索) */\n _inputValue?: string;\n /** 建议列表是否打开 */\n _open?: boolean;\n /** 过滤建议:默认按显示文字包含输入;false 不过滤(异步搜索) */\n filter?: false | ((item: T, query: string) => boolean);\n /** 正在取建议 */\n loading?: boolean;\n /** 弹出位置,默认 bottom-start */\n placement?: FloatingPlacement;\n /** 有标签时显示清空按钮 */\n clearable?: boolean;\n /** 表单提交时的 name(每个值一个隐藏的 input) */\n name?: string;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:标签不能移除,不能输入 */\n readonly?: boolean;\n /** 必填:至少要有一个标签(读屏念“必填”;校验交给表单) */\n required?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 自定义建议的内容 */\n children?: (item: T, state: OptionRenderState) => VNodeChild;\n /** 外壳的部件属性 */\n propsRoot?: PartProps<'div'>;\n /** 每个标签的部件属性,可以按值计算 */\n propsTag?: Partial<TagProps> | ((value: string) => Partial<TagProps>);\n /** 清空按钮的部件属性 */\n propsClear?: Partial<PresetIconButtonProps>;\n /** 弹出层的部件属性 */\n propsPopover?: PartProps<'div', 'id' | 'popover'>;\n /** 建议列表的部件属性 */\n propsListbox?: Partial<ListboxViewProps<T>>;\n}\n\n/** 标签输入的属性;items 不是 ListboxOption 或字符串时要给 toOption */\nexport type TagsInputProps<T = ListboxOption> = TagsInputBaseProps<T> & OptionMapping<T>;\n\n/** TagsInput 的样式:root、input、popover */\nexport const tagsInputStyles = css.create({\n // 标签多了换行;行与行之间留出间距\n root: { flexWrap: 'wrap', rowGap: '_xs', paddingBlock: '_xs' },\n // 输入框至少留出几个字的位置,放不下时换到下一行\n input: { flexBasis: '6em' },\n});\n\n/** 默认的分隔符:英文、中文的逗号与分号 */\nconst DELIMITERS = [',', ',', ';', ';'];\n\n/** 标签输入:输入框里排着 Tag,回车或分隔符加入,退格删最后一个 */\nexport const TagsInput = _component(\n <T = ListboxOption,>({\n _value: value = _bindable<string[]>([]),\n items = [],\n toOption,\n allowCustomValue = true,\n acceptOnBlur = true,\n delimiters = DELIMITERS,\n max,\n _inputValue: inputValue = _bindable(''),\n _open: open = _bindable(false),\n onOpenChange,\n filter,\n loading = false,\n placement = 'bottom-start',\n clearable = false,\n name,\n variant,\n size,\n radius,\n disabled,\n readonly,\n required,\n invalid,\n id,\n children,\n propsRoot,\n icon,\n propsIcon,\n propsTag,\n propsClear,\n propsPopover,\n propsListbox,\n ...rest\n }: TagsInputProps<T>) => {\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 let shell = _state.raw<HTMLElement | null>(null);\n let input = _state.raw<HTMLInputElement | null>(null);\n let panel = _state.raw<HTMLElement | null>(null);\n // 标签增删时其余的平移补位\n const layout = useLayoutAnimation(() => shell, { children: '[data-tag]' });\n\n const setOpen = openSetter(\n () => open,\n (next) => (open = next),\n () => onOpenChange,\n );\n const optionOf = (item: T) => toListboxOption(item, toOption);\n // 异步搜索(filter={false})时结果可能还没回来:建议列表与 combobox 角色一直在,等待时显示加载中\n const suggestions = () => items.length > 0 || filter === false;\n // 标签的文字:异步建议换了 items 之后,已选的仍按之前见过的文字显示;自定义的值就是文字\n const selectedOf = useSelectedOptions({ items: () => items, toOption: optionOf });\n const labelOf = (tag: string) => selectedOf([tag])[0]!.label;\n\n const list = useListState({\n items: () => {\n const query = inputValue.trim();\n if (filter === false || !query) return items;\n const matcher = textMatcher();\n return items.filter((item) =>\n filter ? filter(item, query) : matcher(optionOf(item).label, query),\n );\n },\n toOption: optionOf,\n selected: () => value,\n mode: () => 'multiple',\n onChange: (next) => void layout.change(() => (value = [...next])),\n });\n\n /** 把一段文字变成值:是建议的文字或值时取建议的值,否则(允许时)原样 */\n function resolve(text: string): string | undefined {\n const trimmed = text.trim();\n if (!trimmed) return undefined;\n const item = items.find((candidate) => {\n const option = optionOf(candidate);\n return option.value === trimmed || option.label === trimmed;\n });\n if (item !== undefined) return optionOf(item).value;\n return allowCustomValue ? trimmed : undefined;\n }\n\n /** 加入几段文字;重复的、超出上限的不加;返回是否加入了 */\n function add(texts: readonly string[]) {\n const next = [...value];\n for (const text of texts) {\n const tag = resolve(text);\n if (tag === undefined || next.includes(tag) || (max != null && next.length >= max))\n continue;\n next.push(tag);\n }\n if (next.length === value.length) return false;\n void layout.change(() => (value = next));\n return true;\n }\n\n const remove = (tag: string) =>\n void layout.change(() => (value = value.filter((item) => item !== tag)));\n\n const splitter = () =>\n new RegExp(\n `[${[...delimiters, '\\n', '\\r', '\\t'].map((d) => d.replace(/[\\\\\\]^-]/g, '\\\\$&')).join('')}]`,\n );\n\n // 输入了分隔符:分隔符前的部分加成标签,剩下的留在输入框里\n watch(\n () => inputValue,\n (text) => {\n const parts = text.split(splitter());\n if (parts.length > 1) {\n add(parts.slice(0, -1));\n inputValue = parts.at(-1)!;\n return;\n }\n if (suggestions() && text && !control().readonly) {\n setOpen(true, 'trigger');\n list.move('first');\n }\n },\n );\n\n function onKeydown(event: KeyboardEvent) {\n const state = control();\n if (state.disabled || state.readonly || isComposingKey(event)) return;\n if (event.key === 'Backspace' && !inputValue && value.length) {\n event.preventDefault();\n remove(value.at(-1)!);\n return;\n }\n if (open && suggestions()) {\n if (handleListKeydown(list, event, { homeEnd: false })) {\n event.preventDefault();\n if (event.key === 'Enter') inputValue = '';\n return;\n }\n } else if (event.key === 'ArrowDown' && suggestions()) {\n event.preventDefault();\n list.activateDefault();\n setOpen(true, 'trigger', event);\n return;\n }\n if (event.key === 'Enter' && inputValue.trim()) {\n event.preventDefault();\n if (add([inputValue])) inputValue = '';\n }\n }\n\n // 粘贴多段(有分隔符、换行)时拆开加入;只有一段时照常粘贴\n function onPaste(event: ClipboardEvent) {\n const text = event.clipboardData?.getData('text') ?? '';\n const parts = text.split(splitter());\n if (parts.length < 2) return;\n event.preventDefault();\n add(parts);\n }\n\n const { onToggle } = useAnchoredPopover(\n () => ({\n open: open && suggestions(),\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 return () => {\n const state = control();\n const s = controlParts(appearance(), state);\n const editable = !state.disabled && !state.readonly;\n return (\n <>\n <div\n {...mergeAttrs<'div'>({ ...s.root, sx: [s.root.sx, tagsInputStyles.root] }, propsRoot, {\n ref: _toRef(shell),\n // 外壳里的标签不是原生控件的一部分:不可用要写在外壳上,辅助技术才把它们一起当作不可用\n 'aria-disabled': state.disabled || undefined,\n onPointerdown: focusOnShell(() => input),\n })}\n data-state={open ? 'open' : 'closed'}\n data-invalid={state.invalid || undefined}\n data-disabled={state.disabled || undefined}\n >\n {controlIcon(s, icon, propsIcon)}\n {value.map((tag) => {\n const own = typeof propsTag === 'function' ? propsTag(tag) : propsTag;\n return (\n <Tag\n key={tag}\n {...mergePartProps<TagProps>({ variant: 'surface' }, own, {\n onRemove: editable ? () => remove(tag) : undefined,\n })}\n data-tag=\"\"\n >\n {labelOf(tag)}\n </Tag>\n );\n })}\n <input\n {...mergeAttrs<'input'>(\n { ...s.input, sx: [s.input.sx, tagsInputStyles.input] },\n rest,\n {\n ref: _toRef(input),\n id: state.id,\n role: suggestions() ? 'combobox' : undefined,\n autocomplete: 'off',\n disabled: state.disabled,\n readonly: state.readonly,\n 'aria-autocomplete': suggestions() ? 'list' : undefined,\n 'aria-expanded': suggestions() ? open : undefined,\n 'aria-controls': suggestions() ? listId : undefined,\n 'aria-activedescendant':\n open && suggestions() ? activeOptionId(list, listId) : undefined,\n 'aria-invalid': state.invalid || undefined,\n 'aria-required': state.required || undefined,\n 'aria-describedby': state.describedBy,\n onKeydown,\n onPaste,\n onBlur: (event: FocusEvent) => {\n setOpen(false, 'focus', event);\n if (\n acceptOnBlur &&\n inputValue.trim() &&\n !control().readonly &&\n add([inputValue])\n )\n inputValue = '';\n },\n },\n )}\n _value={inputValue}\n />\n {clearable &&\n value.length > 0 &&\n editable &&\n controlClear(s, propsClear, () => {\n void layout.change(() => (value = []));\n input?.focus();\n })}\n <FormValue name={name} value={value} disabled={state.disabled} />\n </div>\n {suggestions() && (\n <ListPopover\n panelRef={_toRef(panel)}\n onToggle={onToggle}\n size={appearance().size}\n labelledBy={state.labelledBy}\n label={rest['aria-label']}\n loading={loading}\n onPick={() => {\n inputValue = '';\n input?.focus();\n }}\n listbox={{ list, id: listId, multiple: true, renderOption: children }}\n propsListbox={propsListbox}\n propsPopover={propsPopover}\n />\n )}\n </>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -5,8 +5,8 @@ import { useFieldControl } from "../form/Field.js";
5
5
  import { CharacterCount } from "./CharacterCount.js";
6
6
  import { controlAffix, controlClear, controlIcon, controlParts, focusOnShell, useControlAppearance } from "./control.js";
7
7
  import { displayPosition } from "./text-format.js";
8
- import { createVNode, mergeProps, ref, shallowRef, useId, vModelText, withDirectives } from "vue";
9
- import { _component, bindable, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
8
+ import { createVNode, ref, shallowRef, useId, vModelText, withDirectives } from "vue";
9
+ import { _component, bindable, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
10
10
  import { Eye, EyeOff } from "@lucide/icons";
11
11
  //#region src/input/TextField.tsx
12
12
  /**
@@ -119,16 +119,16 @@ var TextField = /*#__PURE__*/ _component((_props, _ctx) => {
119
119
  "aria-invalid": state.invalid || void 0,
120
120
  "aria-describedby": describedBy || void 0
121
121
  });
122
- return createVNode("div", mergeProps(mergeAttrs(s.root, propsRoot.value, { onPointerdown: focusOnShell(() => input.value) }), {
122
+ return createVNode("div", mergeJsxProps(mergeAttrs(s.root, propsRoot.value, { onPointerdown: focusOnShell(() => input.value) }), {
123
123
  "data-invalid": state.invalid || void 0,
124
124
  "data-disabled": state.disabled || void 0
125
125
  }), [
126
126
  controlIcon(s, icon.value, propsIcon.value),
127
127
  controlAffix(s, prefix.value, inputId, propsPrefix.value),
128
- format.value ? createVNode("input", mergeProps(inputAttrs, {
128
+ format.value ? createVNode("input", mergeJsxProps(inputAttrs, {
129
129
  "value": format.value.format(value.value),
130
130
  "onInput": onFormattedInput
131
- }), null) : withDirectives(createVNode("input", mergeProps(inputAttrs, { "onUpdate:modelValue": ($event) => value.value = $event }), null), [[vModelText, value.value]]),
131
+ }), null) : withDirectives(createVNode("input", mergeJsxProps(inputAttrs, { "onUpdate:modelValue": ($event) => value.value = $event }), null), [[vModelText, value.value]]),
132
132
  controlAffix(s, suffix.value, inputId, propsSuffix.value),
133
133
  clearable.value && value.value && editable && controlClear(s, propsClear.value, clear),
134
134
  password && createVNode(IconButton, mergePartProps({
@@ -1 +1 @@
1
- {"version":3,"file":"TextField.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_vue_ref","_createVNode","_mergeProps","_withDirectives","_vModelText"],"sources":["../../src/input/TextField.tsx"],"sourcesContent":["/**\n * 单行文本框:外壳(div)里放原生 input,前后可以带图标,可以一键清空;type=\"password\" 时带显示 / 隐藏密码的按钮。\n *\n * <TextField _value={keyword} type=\"search\" icon={Search} clearable aria-label=\"搜索\" />\n * <Field label=\"密码\" error={errors.password}><TextField _value={password} type=\"password\" /></Field>\n *\n * 未声明的属性落到 input(主元素)上,外壳用 propsRoot(COMPONENTS.md §2)。\n * 双向绑定经 v-model:中文输入法组合输入期间不写回,组合结束才写回。\n * format 让输入时自动分组显示(手机号 138 0000 1111、身份证号、银行卡号,见 text-format.ts):值是去掉分隔的原文,\n * 重新分组后光标留在刚输入的字符后面。\n * 在 Field 里时自动关联标签、说明、错误信息,并沿用 Field 的 invalid / required / disabled / readonly。\n *\n * 部件:Root(外壳)、Input、Icon、IconEnd、Prefix、Suffix(固定文字)、Clear(ClearButton)、Reveal(显示密码的 IconButton)、\n * Count(字数计数 CharacterCount)。\n */\nimport { Eye, EyeOff } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { useId, type VNodeChild } from 'vue';\nimport type { PresetIconButtonProps } from '../base/CloseButton';\nimport type { IconData, IconProps } from '../base/Icon';\nimport { IconButton, type IconButtonProps } from '../base/IconButton';\nimport { useLang } from '../config/context';\nimport { CharacterCount, type CharacterCountProps } from './CharacterCount';\nimport { displayPosition, type TextFormat } from './text-format';\nimport { useFieldControl } from '../form/Field';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport {\n controlClear,\n controlParts,\n focusOnShell,\n controlAffix,\n controlIcon,\n useControlAppearance,\n type ControlIconOptions,\n type ControlOptions,\n} from './control';\n\n/** 值与状态由组件管理;原生的 size 属性(字符宽度)让给字号档位,prefix 属性(RDFa)让给前缀 */\nexport type TextFieldManaged =\n | 'value'\n | 'disabled'\n | 'readonly'\n | 'required'\n | 'size'\n | 'prefix'\n | 'aria-invalid'\n | 'aria-describedby';\n\n/** schema 的格式(JSON Schema format)→ 输入框的 type:手机上弹出对应的键盘 */\nconst FORMAT_TYPES: Readonly<Record<string, 'email' | 'url'>> = { email: 'email', uri: 'url' };\n\n/** 未声明的属性落到 input(主元素)上;外壳用 propsRoot */\nexport interface TextFieldProps\n extends PartProps<'input', TextFieldManaged>, ControlOptions, ControlIconOptions {\n /** 输入值:父级写 _value={x} 双向绑定 */\n _value?: string;\n /** 显示格式:输入时自动分组(phoneFormat、idCardFormat、bankCardFormat 或 createGroupedFormat),值是去掉分隔的原文 */\n format?: TextFormat;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:可以选中、复制,不能修改 */\n readonly?: boolean;\n /** 必填 */\n required?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 有内容时显示清空按钮 */\n clearable?: boolean;\n /** 后置图标 */\n iconEnd?: IconData;\n /** 输入框前的固定文字(如 `https://`、`¥`),不算在值里 */\n prefix?: VNodeChild;\n /** 输入框后的固定文字(如 `.com`、`元`),不算在值里 */\n suffix?: VNodeChild;\n /** 显示字数计数;上限取 maxlength(含 zod 推出的约束),超出时用危险色 */\n showCount?: boolean;\n /** 外壳(边框、焦点环)的部件属性 */\n propsRoot?: PartProps<'div'>;\n /** 后置图标的部件属性 */\n propsIconEnd?: Partial<IconProps>;\n /** 前缀文字的部件属性(指向输入框的 label) */\n propsPrefix?: PartProps<'label'>;\n /** 后缀文字的部件属性(指向输入框的 label) */\n propsSuffix?: PartProps<'label'>;\n /** 字数计数的部件属性 */\n propsCount?: Partial<CharacterCountProps>;\n /** 清空按钮的部件属性 */\n propsClear?: Partial<PresetIconButtonProps>;\n /** 显示 / 隐藏密码按钮的部件属性 */\n propsReveal?: Partial<IconButtonProps>;\n}\n\n/** 单行文本框:未声明的属性落到 input 上 */\nexport const TextField = _component(\n ({\n _value: value = _bindable(''),\n format,\n type,\n variant,\n size,\n radius,\n disabled,\n readonly,\n required,\n invalid,\n clearable = false,\n icon,\n iconEnd,\n prefix,\n suffix,\n showCount = false,\n id,\n propsRoot,\n propsIcon,\n propsIconEnd,\n propsPrefix,\n propsSuffix,\n propsCount,\n propsClear,\n propsReveal,\n ...rest\n }: TextFieldProps) => {\n const lang = useLang();\n const appearance = useControlAppearance(() => ({ variant, size, radius }));\n const control = useFieldControl(() => ({ id, invalid, required, disabled, readonly }));\n let input = _state.raw<HTMLInputElement | null>(null);\n let revealed = _state(false);\n const countId = useId();\n // 前后缀的 label 要指向输入框:不在 Field 里、也没写 id 时用自己生成的\n const ownId = useId();\n\n function clear() {\n value = '';\n input?.focus();\n }\n\n /** 有 format 时的输入:取出原文写回,再按格式显示,光标放回刚才那个字符的后面 */\n function onFormattedInput(event: Event) {\n const element = event.target as HTMLInputElement;\n const caret = element.selectionStart ?? element.value.length;\n const before = format!.parse(element.value.slice(0, caret)).length;\n const raw = format!.parse(element.value);\n value = raw;\n const shown = format!.format(raw);\n if (element.value !== shown) {\n element.value = shown;\n const position = displayPosition(format!, raw, before);\n element.setSelectionRange(position, position);\n }\n }\n\n return () => {\n const state = control();\n const s = controlParts(appearance(), state);\n const editable = !state.disabled && !state.readonly;\n const constraints = state.constraints;\n // 不写 type 时按 schema 的格式选:z.email() → email、z.url() → url\n const inputType = type ?? FORMAT_TYPES[constraints.format ?? ''] ?? 'text';\n const password = inputType === 'password';\n const limit = rest.maxlength ?? constraints.maxLength;\n const describedBy = [state.describedBy, showCount && countId].filter(Boolean).join(' ');\n const inputId = state.id ?? ownId;\n const inputAttrs = mergeAttrs<'input'>(\n {\n ...s.input,\n // 有 format 时输入框里多了分隔,按原文的长度限制交给 format.parse 截断\n minlength: format ? undefined : constraints.minLength,\n maxlength: format ? undefined : constraints.maxLength,\n inputmode: format?.inputmode,\n },\n rest,\n {\n ref: _toRef(input),\n id: inputId,\n type: password && revealed ? 'text' : inputType,\n disabled: state.disabled,\n readonly: state.readonly,\n required: state.required,\n 'aria-invalid': state.invalid || undefined,\n 'aria-describedby': describedBy || undefined,\n },\n );\n return (\n <div\n {...mergeAttrs<'div'>(s.root, propsRoot, {\n onPointerdown: focusOnShell(() => input),\n })}\n data-invalid={state.invalid || undefined}\n data-disabled={state.disabled || undefined}\n >\n {controlIcon(s, icon, propsIcon)}\n {controlAffix(s, prefix, inputId, propsPrefix)}\n {format ? (\n <input {...inputAttrs} value={format.format(value)} onInput={onFormattedInput} />\n ) : (\n // _bind 编译为 v-model:复用 Vue 对输入法组合输入的处理,组合结束才写回\n <input {...inputAttrs} _value={value} />\n )}\n {controlAffix(s, suffix, inputId, propsSuffix)}\n {clearable && value && editable && controlClear(s, propsClear, clear)}\n {password && (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n ...s.button,\n radius: 'full',\n icon: revealed ? EyeOff : Eye,\n // 名称不变、用 aria-pressed 表示状态:读屏念“显示密码,已按下”(名称跟着变会和按下状态打架)\n 'aria-label': lang.passwordShow,\n },\n propsReveal,\n {\n disabled: state.disabled,\n 'aria-pressed': revealed,\n onClick: () => (revealed = !revealed),\n },\n )}\n />\n )}\n {showCount && (\n <CharacterCount\n {...mergePartProps<CharacterCountProps>(\n { count: value.length, max: limit == null ? undefined : Number(limit) },\n propsCount,\n { id: countId },\n )}\n />\n )}\n {controlIcon(s, iconEnd, propsIconEnd)}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"TextField.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_vue_ref","_createVNode","_mergeProps","_withDirectives","_vModelText"],"sources":["../../src/input/TextField.tsx"],"sourcesContent":["/**\n * 单行文本框:外壳(div)里放原生 input,前后可以带图标,可以一键清空;type=\"password\" 时带显示 / 隐藏密码的按钮。\n *\n * <TextField _value={keyword} type=\"search\" icon={Search} clearable aria-label=\"搜索\" />\n * <Field label=\"密码\" error={errors.password}><TextField _value={password} type=\"password\" /></Field>\n *\n * 未声明的属性落到 input(主元素)上,外壳用 propsRoot(COMPONENTS.md §2)。\n * 双向绑定经 v-model:中文输入法组合输入期间不写回,组合结束才写回。\n * format 让输入时自动分组显示(手机号 138 0000 1111、身份证号、银行卡号,见 text-format.ts):值是去掉分隔的原文,\n * 重新分组后光标留在刚输入的字符后面。\n * 在 Field 里时自动关联标签、说明、错误信息,并沿用 Field 的 invalid / required / disabled / readonly。\n *\n * 部件:Root(外壳)、Input、Icon、IconEnd、Prefix、Suffix(固定文字)、Clear(ClearButton)、Reveal(显示密码的 IconButton)、\n * Count(字数计数 CharacterCount)。\n */\nimport { Eye, EyeOff } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { useId, type VNodeChild } from 'vue';\nimport type { PresetIconButtonProps } from '../base/CloseButton';\nimport type { IconData, IconProps } from '../base/Icon';\nimport { IconButton, type IconButtonProps } from '../base/IconButton';\nimport { useLang } from '../config/context';\nimport { CharacterCount, type CharacterCountProps } from './CharacterCount';\nimport { displayPosition, type TextFormat } from './text-format';\nimport { useFieldControl } from '../form/Field';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport {\n controlClear,\n controlParts,\n focusOnShell,\n controlAffix,\n controlIcon,\n useControlAppearance,\n type ControlIconOptions,\n type ControlOptions,\n} from './control';\n\n/** 值与状态由组件管理;原生的 size 属性(字符宽度)让给字号档位,prefix 属性(RDFa)让给前缀 */\nexport type TextFieldManaged =\n | 'value'\n | 'disabled'\n | 'readonly'\n | 'required'\n | 'size'\n | 'prefix'\n | 'aria-invalid'\n | 'aria-describedby';\n\n/** schema 的格式(JSON Schema format)→ 输入框的 type:手机上弹出对应的键盘 */\nconst FORMAT_TYPES: Readonly<Record<string, 'email' | 'url'>> = { email: 'email', uri: 'url' };\n\n/** 未声明的属性落到 input(主元素)上;外壳用 propsRoot */\nexport interface TextFieldProps\n extends PartProps<'input', TextFieldManaged>, ControlOptions, ControlIconOptions {\n /** 输入值:父级写 _value={x} 双向绑定 */\n _value?: string;\n /** 显示格式:输入时自动分组(phoneFormat、idCardFormat、bankCardFormat 或 createGroupedFormat),值是去掉分隔的原文 */\n format?: TextFormat;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:可以选中、复制,不能修改 */\n readonly?: boolean;\n /** 必填 */\n required?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 有内容时显示清空按钮 */\n clearable?: boolean;\n /** 后置图标 */\n iconEnd?: IconData;\n /** 输入框前的固定文字(如 `https://`、`¥`),不算在值里 */\n prefix?: VNodeChild;\n /** 输入框后的固定文字(如 `.com`、`元`),不算在值里 */\n suffix?: VNodeChild;\n /** 显示字数计数;上限取 maxlength(含 zod 推出的约束),超出时用危险色 */\n showCount?: boolean;\n /** 外壳(边框、焦点环)的部件属性 */\n propsRoot?: PartProps<'div'>;\n /** 后置图标的部件属性 */\n propsIconEnd?: Partial<IconProps>;\n /** 前缀文字的部件属性(指向输入框的 label) */\n propsPrefix?: PartProps<'label'>;\n /** 后缀文字的部件属性(指向输入框的 label) */\n propsSuffix?: PartProps<'label'>;\n /** 字数计数的部件属性 */\n propsCount?: Partial<CharacterCountProps>;\n /** 清空按钮的部件属性 */\n propsClear?: Partial<PresetIconButtonProps>;\n /** 显示 / 隐藏密码按钮的部件属性 */\n propsReveal?: Partial<IconButtonProps>;\n}\n\n/** 单行文本框:未声明的属性落到 input 上 */\nexport const TextField = _component(\n ({\n _value: value = _bindable(''),\n format,\n type,\n variant,\n size,\n radius,\n disabled,\n readonly,\n required,\n invalid,\n clearable = false,\n icon,\n iconEnd,\n prefix,\n suffix,\n showCount = false,\n id,\n propsRoot,\n propsIcon,\n propsIconEnd,\n propsPrefix,\n propsSuffix,\n propsCount,\n propsClear,\n propsReveal,\n ...rest\n }: TextFieldProps) => {\n const lang = useLang();\n const appearance = useControlAppearance(() => ({ variant, size, radius }));\n const control = useFieldControl(() => ({ id, invalid, required, disabled, readonly }));\n let input = _state.raw<HTMLInputElement | null>(null);\n let revealed = _state(false);\n const countId = useId();\n // 前后缀的 label 要指向输入框:不在 Field 里、也没写 id 时用自己生成的\n const ownId = useId();\n\n function clear() {\n value = '';\n input?.focus();\n }\n\n /** 有 format 时的输入:取出原文写回,再按格式显示,光标放回刚才那个字符的后面 */\n function onFormattedInput(event: Event) {\n const element = event.target as HTMLInputElement;\n const caret = element.selectionStart ?? element.value.length;\n const before = format!.parse(element.value.slice(0, caret)).length;\n const raw = format!.parse(element.value);\n value = raw;\n const shown = format!.format(raw);\n if (element.value !== shown) {\n element.value = shown;\n const position = displayPosition(format!, raw, before);\n element.setSelectionRange(position, position);\n }\n }\n\n return () => {\n const state = control();\n const s = controlParts(appearance(), state);\n const editable = !state.disabled && !state.readonly;\n const constraints = state.constraints;\n // 不写 type 时按 schema 的格式选:z.email() → email、z.url() → url\n const inputType = type ?? FORMAT_TYPES[constraints.format ?? ''] ?? 'text';\n const password = inputType === 'password';\n const limit = rest.maxlength ?? constraints.maxLength;\n const describedBy = [state.describedBy, showCount && countId].filter(Boolean).join(' ');\n const inputId = state.id ?? ownId;\n const inputAttrs = mergeAttrs<'input'>(\n {\n ...s.input,\n // 有 format 时输入框里多了分隔,按原文的长度限制交给 format.parse 截断\n minlength: format ? undefined : constraints.minLength,\n maxlength: format ? undefined : constraints.maxLength,\n inputmode: format?.inputmode,\n },\n rest,\n {\n ref: _toRef(input),\n id: inputId,\n type: password && revealed ? 'text' : inputType,\n disabled: state.disabled,\n readonly: state.readonly,\n required: state.required,\n 'aria-invalid': state.invalid || undefined,\n 'aria-describedby': describedBy || undefined,\n },\n );\n return (\n <div\n {...mergeAttrs<'div'>(s.root, propsRoot, {\n onPointerdown: focusOnShell(() => input),\n })}\n data-invalid={state.invalid || undefined}\n data-disabled={state.disabled || undefined}\n >\n {controlIcon(s, icon, propsIcon)}\n {controlAffix(s, prefix, inputId, propsPrefix)}\n {format ? (\n <input {...inputAttrs} value={format.format(value)} onInput={onFormattedInput} />\n ) : (\n // _bind 编译为 v-model:复用 Vue 对输入法组合输入的处理,组合结束才写回\n <input {...inputAttrs} _value={value} />\n )}\n {controlAffix(s, suffix, inputId, propsSuffix)}\n {clearable && value && editable && controlClear(s, propsClear, clear)}\n {password && (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n ...s.button,\n radius: 'full',\n icon: revealed ? EyeOff : Eye,\n // 名称不变、用 aria-pressed 表示状态:读屏念“显示密码,已按下”(名称跟着变会和按下状态打架)\n 'aria-label': lang.passwordShow,\n },\n propsReveal,\n {\n disabled: state.disabled,\n 'aria-pressed': revealed,\n onClick: () => (revealed = !revealed),\n },\n )}\n />\n )}\n {showCount && (\n <CharacterCount\n {...mergePartProps<CharacterCountProps>(\n { count: value.length, max: limit == null ? undefined : Number(limit) },\n propsCount,\n { id: countId },\n )}\n />\n )}\n {controlIcon(s, iconEnd, propsIconEnd)}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -2,8 +2,8 @@ import { mergeAttrs, mergePartProps } from "../utils/props.js";
2
2
  import { useFieldControl } from "../form/Field.js";
3
3
  import { CharacterCount } from "./CharacterCount.js";
4
4
  import { controlClear, controlParts, useControlAppearance } from "./control.js";
5
- import { createVNode, mergeProps, nextTick, shallowRef, useId, vModelText, withDirectives } from "vue";
6
- import { _component, bindable, effect, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
5
+ import { createVNode, nextTick, shallowRef, useId, vModelText, withDirectives } from "vue";
6
+ import { _component, bindable, effect, 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/Textarea.tsx
9
9
  /** 值与状态由组件管理 */
@@ -78,11 +78,11 @@ var Textarea = /*#__PURE__*/ _component((_props, _ctx) => {
78
78
  const s = controlParts(appearance(), state, true);
79
79
  const limit = rest.maxlength ?? state.constraints.maxLength;
80
80
  const describedBy = [state.describedBy, showCount.value && countId].filter(Boolean).join(" ");
81
- return createVNode("div", mergeProps(mergeAttrs(s.root, propsRoot.value), {
81
+ return createVNode("div", mergeJsxProps(mergeAttrs(s.root, propsRoot.value), {
82
82
  "data-invalid": state.invalid || void 0,
83
83
  "data-disabled": state.disabled || void 0
84
84
  }), [
85
- withDirectives(createVNode("textarea", mergeProps(mergeAttrs({
85
+ withDirectives(createVNode("textarea", mergeJsxProps(mergeAttrs({
86
86
  ...s.input,
87
87
  sx: [
88
88
  s.input.sx,
@@ -1 +1 @@
1
- {"version":3,"file":"Textarea.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","_mergeProps","_withDirectives","_vModelText"],"sources":["../../src/input/Textarea.tsx"],"sourcesContent":["/**\n * 多行文本框:外壳与 TextField 相同(control),高度随内容增长,在 rows 与 maxRows 之间。\n *\n * <Field label=\"备注\"><Textarea _value={note} rows={3} maxRows={8} /></Field>\n *\n * 自动增高:内容变化后(含父级改值)把高度设为 scrollHeight,上下限用 lh 单位(行高的倍数)由 CSS 夹住。\n * 没用 field-sizing: content:Firefox 还不支持,样式的类型表里也没有。中文输入法照常(v-model)。\n *\n * 未声明的属性落到 textarea(主元素)上,外壳用 propsRoot。部件:Root(外壳)、Textarea。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { nextTick, useId } from 'vue';\nimport { CharacterCount, type CharacterCountProps } from './CharacterCount';\nimport { useFieldControl } from '../form/Field';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport type { PresetIconButtonProps } from '../base/CloseButton';\nimport { controlClear, controlParts, useControlAppearance, type ControlOptions } from './control';\n\n/** 值与状态由组件管理 */\nexport type TextareaManaged =\n 'value' | 'rows' | 'disabled' | 'readonly' | 'required' | 'aria-invalid' | 'aria-describedby';\n\n/** 未声明的属性落到 textarea(主元素)上;外壳用 propsRoot */\nexport interface TextareaProps extends PartProps<'textarea', TextareaManaged>, ControlOptions {\n /** 输入值:父级写 _value={x} 双向绑定 */\n _value?: string;\n /** 最少显示几行,默认 3 */\n rows?: number;\n /** 最多增高到几行,之后出现滚动条;默认不限 */\n maxRows?: number;\n /** 不随内容增高,固定为 rows 行(可以拖动右下角改变高度) */\n fixed?: boolean;\n /** 不可用 */\n disabled?: boolean;\n /** 只读 */\n readonly?: boolean;\n /** 必填 */\n required?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 显示字数计数(右下角);上限取 maxlength(含 zod 推出的约束),超出时用危险色 */\n showCount?: boolean;\n /** 有内容时在右上角显示清空按钮 */\n clearable?: boolean;\n /** 清空按钮的部件属性 */\n propsClear?: Partial<PresetIconButtonProps>;\n /** 外壳的部件属性 */\n propsRoot?: PartProps<'div'>;\n /** 字数计数的部件属性 */\n propsCount?: Partial<CharacterCountProps>;\n}\n\n/** Textarea 的样式:textarea、fixed、count、clear */\nexport const textareaStyles = css.create({\n // 随外壳拉伸:外壳给了高度(propsRoot 的 height)时文字区占满,不停在基线上\n textarea: { alignSelf: 'stretch', resize: 'none', overflowY: 'auto' },\n fixed: { resize: 'vertical' },\n // 计数贴在右下角\n count: { alignSelf: 'flex-end', paddingBlockEnd: '_xs' },\n // 清空按钮贴在第一行(多行时不随内容居中)\n clear: { alignSelf: 'flex-start', marginBlockStart: '_xs' },\n});\n\n// 行数是任意值,用动态样式;单独一个 create,见 COMPONENTS.md §4\n/** Textarea 的样式:min、max */\nexport const textareaRowStyles = css.create({\n min: (rows: number) => ({ minHeight: `${rows}lh` }),\n max: (rows: number) => ({ maxHeight: `${rows}lh` }),\n});\n\n/** 多行文本框:高度随内容增长 */\nexport const Textarea = _component(\n ({\n _value: value = _bindable(''),\n rows = 3,\n maxRows,\n fixed = false,\n variant,\n size,\n radius,\n disabled,\n readonly,\n required,\n invalid,\n showCount = false,\n clearable = false,\n id,\n propsRoot,\n propsCount,\n propsClear,\n ...rest\n }: TextareaProps) => {\n const countId = useId();\n const appearance = useControlAppearance(() => ({ variant, size, radius }));\n const control = useFieldControl(() => ({ id, invalid, required, disabled, readonly }));\n let textarea = _state.raw<HTMLTextAreaElement | null>(null);\n\n // 内容变化(含父级改值)后按内容高度重设\n _effect(() => {\n if (fixed || !textarea) return;\n void value;\n const element = textarea;\n void nextTick(() => {\n element.style.height = 'auto';\n element.style.height = `${element.scrollHeight}px`;\n });\n });\n\n return () => {\n const state = control();\n const s = controlParts(appearance(), state, true);\n const limit = rest.maxlength ?? state.constraints.maxLength;\n const describedBy = [state.describedBy, showCount && countId].filter(Boolean).join(' ');\n return (\n <div\n {...mergeAttrs<'div'>(s.root, propsRoot)}\n data-invalid={state.invalid || undefined}\n data-disabled={state.disabled || undefined}\n >\n <textarea\n {...mergeAttrs<'textarea'>(\n {\n ...s.input,\n sx: [\n s.input.sx,\n textareaStyles.textarea,\n fixed && textareaStyles.fixed,\n textareaRowStyles.min(rows),\n maxRows != null && !fixed && textareaRowStyles.max(maxRows),\n ],\n minlength: state.constraints.minLength,\n maxlength: state.constraints.maxLength,\n },\n rest,\n {\n ref: _toRef(textarea),\n id: state.id,\n rows,\n disabled: state.disabled,\n readonly: state.readonly,\n required: state.required,\n 'aria-invalid': state.invalid || undefined,\n 'aria-describedby': describedBy || undefined,\n },\n )}\n _value={value}\n />\n {clearable &&\n value &&\n !state.disabled &&\n !state.readonly &&\n // 使用方的 sx 接在贴顶的样式之后,不把它整个换掉\n controlClear(s, { ...propsClear, sx: [textareaStyles.clear, propsClear?.sx] }, () => {\n value = '';\n textarea?.focus();\n })}\n {showCount && (\n <CharacterCount\n {...mergePartProps<CharacterCountProps>(\n {\n sx: textareaStyles.count,\n count: value.length,\n max: limit == null ? undefined : Number(limit),\n },\n propsCount,\n { id: countId },\n )}\n />\n )}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"Textarea.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","_mergeProps","_withDirectives","_vModelText"],"sources":["../../src/input/Textarea.tsx"],"sourcesContent":["/**\n * 多行文本框:外壳与 TextField 相同(control),高度随内容增长,在 rows 与 maxRows 之间。\n *\n * <Field label=\"备注\"><Textarea _value={note} rows={3} maxRows={8} /></Field>\n *\n * 自动增高:内容变化后(含父级改值)把高度设为 scrollHeight,上下限用 lh 单位(行高的倍数)由 CSS 夹住。\n * 没用 field-sizing: content:Firefox 还不支持,样式的类型表里也没有。中文输入法照常(v-model)。\n *\n * 未声明的属性落到 textarea(主元素)上,外壳用 propsRoot。部件:Root(外壳)、Textarea。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { nextTick, useId } from 'vue';\nimport { CharacterCount, type CharacterCountProps } from './CharacterCount';\nimport { useFieldControl } from '../form/Field';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport type { PresetIconButtonProps } from '../base/CloseButton';\nimport { controlClear, controlParts, useControlAppearance, type ControlOptions } from './control';\n\n/** 值与状态由组件管理 */\nexport type TextareaManaged =\n 'value' | 'rows' | 'disabled' | 'readonly' | 'required' | 'aria-invalid' | 'aria-describedby';\n\n/** 未声明的属性落到 textarea(主元素)上;外壳用 propsRoot */\nexport interface TextareaProps extends PartProps<'textarea', TextareaManaged>, ControlOptions {\n /** 输入值:父级写 _value={x} 双向绑定 */\n _value?: string;\n /** 最少显示几行,默认 3 */\n rows?: number;\n /** 最多增高到几行,之后出现滚动条;默认不限 */\n maxRows?: number;\n /** 不随内容增高,固定为 rows 行(可以拖动右下角改变高度) */\n fixed?: boolean;\n /** 不可用 */\n disabled?: boolean;\n /** 只读 */\n readonly?: boolean;\n /** 必填 */\n required?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 显示字数计数(右下角);上限取 maxlength(含 zod 推出的约束),超出时用危险色 */\n showCount?: boolean;\n /** 有内容时在右上角显示清空按钮 */\n clearable?: boolean;\n /** 清空按钮的部件属性 */\n propsClear?: Partial<PresetIconButtonProps>;\n /** 外壳的部件属性 */\n propsRoot?: PartProps<'div'>;\n /** 字数计数的部件属性 */\n propsCount?: Partial<CharacterCountProps>;\n}\n\n/** Textarea 的样式:textarea、fixed、count、clear */\nexport const textareaStyles = css.create({\n // 随外壳拉伸:外壳给了高度(propsRoot 的 height)时文字区占满,不停在基线上\n textarea: { alignSelf: 'stretch', resize: 'none', overflowY: 'auto' },\n fixed: { resize: 'vertical' },\n // 计数贴在右下角\n count: { alignSelf: 'flex-end', paddingBlockEnd: '_xs' },\n // 清空按钮贴在第一行(多行时不随内容居中)\n clear: { alignSelf: 'flex-start', marginBlockStart: '_xs' },\n});\n\n// 行数是任意值,用动态样式;单独一个 create,见 COMPONENTS.md §4\n/** Textarea 的样式:min、max */\nexport const textareaRowStyles = css.create({\n min: (rows: number) => ({ minHeight: `${rows}lh` }),\n max: (rows: number) => ({ maxHeight: `${rows}lh` }),\n});\n\n/** 多行文本框:高度随内容增长 */\nexport const Textarea = _component(\n ({\n _value: value = _bindable(''),\n rows = 3,\n maxRows,\n fixed = false,\n variant,\n size,\n radius,\n disabled,\n readonly,\n required,\n invalid,\n showCount = false,\n clearable = false,\n id,\n propsRoot,\n propsCount,\n propsClear,\n ...rest\n }: TextareaProps) => {\n const countId = useId();\n const appearance = useControlAppearance(() => ({ variant, size, radius }));\n const control = useFieldControl(() => ({ id, invalid, required, disabled, readonly }));\n let textarea = _state.raw<HTMLTextAreaElement | null>(null);\n\n // 内容变化(含父级改值)后按内容高度重设\n _effect(() => {\n if (fixed || !textarea) return;\n void value;\n const element = textarea;\n void nextTick(() => {\n element.style.height = 'auto';\n element.style.height = `${element.scrollHeight}px`;\n });\n });\n\n return () => {\n const state = control();\n const s = controlParts(appearance(), state, true);\n const limit = rest.maxlength ?? state.constraints.maxLength;\n const describedBy = [state.describedBy, showCount && countId].filter(Boolean).join(' ');\n return (\n <div\n {...mergeAttrs<'div'>(s.root, propsRoot)}\n data-invalid={state.invalid || undefined}\n data-disabled={state.disabled || undefined}\n >\n <textarea\n {...mergeAttrs<'textarea'>(\n {\n ...s.input,\n sx: [\n s.input.sx,\n textareaStyles.textarea,\n fixed && textareaStyles.fixed,\n textareaRowStyles.min(rows),\n maxRows != null && !fixed && textareaRowStyles.max(maxRows),\n ],\n minlength: state.constraints.minLength,\n maxlength: state.constraints.maxLength,\n },\n rest,\n {\n ref: _toRef(textarea),\n id: state.id,\n rows,\n disabled: state.disabled,\n readonly: state.readonly,\n required: state.required,\n 'aria-invalid': state.invalid || undefined,\n 'aria-describedby': describedBy || undefined,\n },\n )}\n _value={value}\n />\n {clearable &&\n value &&\n !state.disabled &&\n !state.readonly &&\n // 使用方的 sx 接在贴顶的样式之后,不把它整个换掉\n controlClear(s, { ...propsClear, sx: [textareaStyles.clear, propsClear?.sx] }, () => {\n value = '';\n textarea?.focus();\n })}\n {showCount && (\n <CharacterCount\n {...mergePartProps<CharacterCountProps>(\n {\n sx: textareaStyles.count,\n count: value.length,\n max: limit == null ? undefined : Number(limit),\n },\n propsCount,\n { id: countId },\n )}\n />\n )}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -5,8 +5,8 @@ import { useFieldControl } from "../form/Field.js";
5
5
  import { rovingFocus } from "../utils/dom/roving-focus.js";
6
6
  import { useActiveIndicator } from "../utils/motion/active-indicator.js";
7
7
  import { ToolbarContext } from "../navigation/Toolbar.js";
8
- import { computed, createVNode, mergeProps, shallowRef } from "vue";
9
- import { _component, bindable, childrenProp, createContext, effect, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
8
+ import { computed, createVNode, shallowRef } from "vue";
9
+ import { _component, bindable, childrenProp, createContext, effect, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
10
10
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
11
11
  //#region src/input/ToggleGroup.tsx
12
12
  /** ToggleGroup 交给组内 ToggleGroupItem 的状态 */
@@ -114,7 +114,7 @@ var ToggleGroup = /*#__PURE__*/ _component((_props, _ctx) => {
114
114
  });
115
115
  return () => {
116
116
  const field = control();
117
- return createVNode("div", mergeProps(mergeAttrs({ sx: [toggleGroupStyles.root, orientation.value === "vertical" && toggleGroupStyles.vertical] }, rest, {
117
+ return createVNode("div", mergeJsxProps(mergeAttrs({ sx: [toggleGroupStyles.root, orientation.value === "vertical" && toggleGroupStyles.vertical] }, rest, {
118
118
  ref: root,
119
119
  id: field.id,
120
120
  role: "group",
@@ -173,7 +173,7 @@ var ToggleItem = /*#__PURE__*/ _component((_props2, _ctx2) => {
173
173
  const pressed = group.selected.includes(value.value);
174
174
  const off = disabled.value || group.disabled;
175
175
  const base = appearance();
176
- return createVNode("button", mergeProps(mergeAttrs({
176
+ return createVNode("button", mergeJsxProps(mergeAttrs({
177
177
  ...buttonPart,
178
178
  sx: [buttonSx({
179
179
  ...base,