@zerodep-dev/vue-tsx-pro-ui 0.2.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 (416) 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/config/Provider.d.ts +3 -1
  62. package/dist/config/Provider.js +9 -4
  63. package/dist/config/Provider.js.map +1 -1
  64. package/dist/config/context.d.ts +18 -0
  65. package/dist/config/context.js +16 -1
  66. package/dist/config/context.js.map +1 -1
  67. package/dist/config/createUi.d.ts +20 -3
  68. package/dist/config/createUi.js +80 -49
  69. package/dist/config/createUi.js.map +1 -1
  70. package/dist/config/layout/preference.d.ts +43 -0
  71. package/dist/config/layout/preference.js +108 -0
  72. package/dist/config/layout/preference.js.map +1 -0
  73. package/dist/date/Calendar.js +3 -3
  74. package/dist/date/Calendar.js.map +1 -1
  75. package/dist/date/CalendarBoard.js +9 -9
  76. package/dist/date/CalendarBoard.js.map +1 -1
  77. package/dist/date/CalendarView.js +7 -7
  78. package/dist/date/CalendarView.js.map +1 -1
  79. package/dist/date/DateField.js +3 -3
  80. package/dist/date/DateField.js.map +1 -1
  81. package/dist/date/DatePicker.js +5 -5
  82. package/dist/date/DatePicker.js.map +1 -1
  83. package/dist/date/DateRangePicker.js +5 -5
  84. package/dist/date/DateRangePicker.js.map +1 -1
  85. package/dist/date/DateSegmentGroup.js +5 -5
  86. package/dist/date/DateSegmentGroup.js.map +1 -1
  87. package/dist/date/QuarterCalendar.js +6 -6
  88. package/dist/date/QuarterCalendar.js.map +1 -1
  89. package/dist/date/RangeCalendar.js +3 -3
  90. package/dist/date/RangeCalendar.js.map +1 -1
  91. package/dist/date/SegmentedField.js +3 -3
  92. package/dist/date/SegmentedField.js.map +1 -1
  93. package/dist/date/TimeField.js +3 -3
  94. package/dist/date/TimeField.js.map +1 -1
  95. package/dist/date/TimePicker.js +4 -4
  96. package/dist/date/TimePicker.js.map +1 -1
  97. package/dist/date/date-segments.js +1 -1
  98. package/dist/date/date-segments.js.map +1 -1
  99. package/dist/date/picker-popover.js +3 -2
  100. package/dist/date/picker-popover.js.map +1 -1
  101. package/dist/diagram/Diagram.js +12 -12
  102. package/dist/diagram/Diagram.js.map +1 -1
  103. package/dist/diagram/DiagramLanes.js +3 -3
  104. package/dist/diagram/DiagramLanes.js.map +1 -1
  105. package/dist/diagram/DiagramMinimap.js +4 -4
  106. package/dist/diagram/DiagramMinimap.js.map +1 -1
  107. package/dist/display/Accordion.js +6 -6
  108. package/dist/display/Accordion.js.map +1 -1
  109. package/dist/display/AnimatedNumber.js +4 -4
  110. package/dist/display/AnimatedNumber.js.map +1 -1
  111. package/dist/display/Avatar.js +4 -4
  112. package/dist/display/Avatar.js.map +1 -1
  113. package/dist/display/Checklist.js +7 -7
  114. package/dist/display/Checklist.js.map +1 -1
  115. package/dist/display/Collapse.js +8 -5
  116. package/dist/display/Collapse.js.map +1 -1
  117. package/dist/display/Collapsible.js +3 -3
  118. package/dist/display/Collapsible.js.map +1 -1
  119. package/dist/display/Descriptions.js +5 -5
  120. package/dist/display/Descriptions.js.map +1 -1
  121. package/dist/display/Ellipsis.js +3 -3
  122. package/dist/display/Ellipsis.js.map +1 -1
  123. package/dist/display/FieldCompare.js +4 -4
  124. package/dist/display/FieldCompare.js.map +1 -1
  125. package/dist/display/Gauge.js +11 -11
  126. package/dist/display/Gauge.js.map +1 -1
  127. package/dist/display/Image.js +4 -4
  128. package/dist/display/Image.js.map +1 -1
  129. package/dist/display/Marquee.js +3 -3
  130. package/dist/display/Marquee.js.map +1 -1
  131. package/dist/display/ProportionBar.js +4 -4
  132. package/dist/display/ProportionBar.js.map +1 -1
  133. package/dist/display/Sortable.js +4 -4
  134. package/dist/display/Sortable.js.map +1 -1
  135. package/dist/display/Sparkline.js +6 -6
  136. package/dist/display/Sparkline.js.map +1 -1
  137. package/dist/display/Stat.js +3 -3
  138. package/dist/display/Stat.js.map +1 -1
  139. package/dist/display/Timeline.js +7 -7
  140. package/dist/display/Timeline.js.map +1 -1
  141. package/dist/display/Tree.js +10 -10
  142. package/dist/display/Tree.js.map +1 -1
  143. package/dist/display/VirtualList.js +7 -7
  144. package/dist/display/VirtualList.js.map +1 -1
  145. package/dist/display/Watermark.js +3 -3
  146. package/dist/display/Watermark.js.map +1 -1
  147. package/dist/docs-kit/CodeGroup.js +5 -5
  148. package/dist/docs-kit/CodeGroup.js.map +1 -1
  149. package/dist/docs-kit/CodePreview.js +6 -6
  150. package/dist/docs-kit/CodePreview.js.map +1 -1
  151. package/dist/docs-kit/PropsTable.js +4 -4
  152. package/dist/docs-kit/PropsTable.js.map +1 -1
  153. package/dist/feedback/Alert.js +5 -5
  154. package/dist/feedback/Alert.js.map +1 -1
  155. package/dist/feedback/Banner.js +5 -5
  156. package/dist/feedback/Banner.js.map +1 -1
  157. package/dist/feedback/Empty.js +4 -4
  158. package/dist/feedback/Empty.js.map +1 -1
  159. package/dist/feedback/LoadingBar.js +20 -13
  160. package/dist/feedback/LoadingBar.js.map +1 -1
  161. package/dist/feedback/LoadingOverlay.js +3 -3
  162. package/dist/feedback/LoadingOverlay.js.map +1 -1
  163. package/dist/feedback/Progress.js +14 -14
  164. package/dist/feedback/Progress.js.map +1 -1
  165. package/dist/feedback/Result.js +4 -4
  166. package/dist/feedback/Result.js.map +1 -1
  167. package/dist/feedback/SkeletonText.js +3 -3
  168. package/dist/feedback/SkeletonText.js.map +1 -1
  169. package/dist/feedback/Toast.js +6 -6
  170. package/dist/feedback/Toast.js.map +1 -1
  171. package/dist/form/Field.js +7 -7
  172. package/dist/form/Field.js.map +1 -1
  173. package/dist/form/Form.js +3 -3
  174. package/dist/form/Form.js.map +1 -1
  175. package/dist/form/FormErrorSummary.js +3 -3
  176. package/dist/form/FormErrorSummary.js.map +1 -1
  177. package/dist/form/FormSection.js +6 -6
  178. package/dist/form/FormSection.js.map +1 -1
  179. package/dist/index.d.ts +11 -6
  180. package/dist/index.js +10 -5
  181. package/dist/input/Autocomplete.js +3 -3
  182. package/dist/input/Autocomplete.js.map +1 -1
  183. package/dist/input/Cascader.js +7 -7
  184. package/dist/input/Cascader.js.map +1 -1
  185. package/dist/input/CharacterCount.js +3 -3
  186. package/dist/input/CharacterCount.js.map +1 -1
  187. package/dist/input/Checkbox.js +5 -5
  188. package/dist/input/Checkbox.js.map +1 -1
  189. package/dist/input/ColorField.js +4 -4
  190. package/dist/input/ColorField.js.map +1 -1
  191. package/dist/input/Combobox.js +4 -4
  192. package/dist/input/Combobox.js.map +1 -1
  193. package/dist/input/ConditionBuilder.js +15 -14
  194. package/dist/input/ConditionBuilder.js.map +1 -1
  195. package/dist/input/FileDrop.js +3 -3
  196. package/dist/input/FileDrop.js.map +1 -1
  197. package/dist/input/Listbox.js +9 -9
  198. package/dist/input/Listbox.js.map +1 -1
  199. package/dist/input/Mentions.js +3 -3
  200. package/dist/input/Mentions.js.map +1 -1
  201. package/dist/input/NumberField.js +3 -3
  202. package/dist/input/NumberField.js.map +1 -1
  203. package/dist/input/NumberRangeField.js +5 -5
  204. package/dist/input/NumberRangeField.js.map +1 -1
  205. package/dist/input/OtpField.js +5 -5
  206. package/dist/input/OtpField.js.map +1 -1
  207. package/dist/input/PeoplePicker.js +6 -6
  208. package/dist/input/PeoplePicker.js.map +1 -1
  209. package/dist/input/PeoplePickerPanel.js +4 -4
  210. package/dist/input/PeoplePickerPanel.js.map +1 -1
  211. package/dist/input/Radio.js +4 -4
  212. package/dist/input/Radio.js.map +1 -1
  213. package/dist/input/Rating.js +5 -5
  214. package/dist/input/Rating.js.map +1 -1
  215. package/dist/input/Select.js +4 -4
  216. package/dist/input/Select.js.map +1 -1
  217. package/dist/input/SelectedTags.js +4 -4
  218. package/dist/input/SelectedTags.js.map +1 -1
  219. package/dist/input/Slider.js +6 -6
  220. package/dist/input/Slider.js.map +1 -1
  221. package/dist/input/Switch.js +3 -3
  222. package/dist/input/Switch.js.map +1 -1
  223. package/dist/input/TagsInput.js +5 -5
  224. package/dist/input/TagsInput.js.map +1 -1
  225. package/dist/input/TextField.js +5 -5
  226. package/dist/input/TextField.js.map +1 -1
  227. package/dist/input/Textarea.js +4 -4
  228. package/dist/input/Textarea.js.map +1 -1
  229. package/dist/input/ToggleGroup.js +4 -4
  230. package/dist/input/ToggleGroup.js.map +1 -1
  231. package/dist/input/Transfer.js +8 -8
  232. package/dist/input/Transfer.js.map +1 -1
  233. package/dist/input/TreeSelect.js +6 -6
  234. package/dist/input/TreeSelect.js.map +1 -1
  235. package/dist/input/Upload.js +8 -8
  236. package/dist/input/Upload.js.map +1 -1
  237. package/dist/layout/Affix.js +4 -4
  238. package/dist/layout/Affix.js.map +1 -1
  239. package/dist/layout/ResizeHandle.d.ts +6 -2
  240. package/dist/layout/ResizeHandle.js +32 -9
  241. package/dist/layout/ResizeHandle.js.map +1 -1
  242. package/dist/layout/ScrollArea.js +3 -3
  243. package/dist/layout/ScrollArea.js.map +1 -1
  244. package/dist/layout/Separator.js +3 -3
  245. package/dist/layout/Separator.js.map +1 -1
  246. package/dist/layout/Splitter.js +3 -3
  247. package/dist/layout/Splitter.js.map +1 -1
  248. package/dist/layout/ViewportFill.d.ts +2 -2
  249. package/dist/layout/ViewportFill.js +4 -4
  250. package/dist/layout/ViewportFill.js.map +1 -1
  251. package/dist/navigation/Breadcrumbs.js +4 -4
  252. package/dist/navigation/Breadcrumbs.js.map +1 -1
  253. package/dist/navigation/NavBar.js +6 -6
  254. package/dist/navigation/NavBar.js.map +1 -1
  255. package/dist/navigation/NavList.d.ts +1 -0
  256. package/dist/navigation/NavList.js +20 -12
  257. package/dist/navigation/NavList.js.map +1 -1
  258. package/dist/navigation/NavMenu.d.ts +27 -0
  259. package/dist/navigation/NavMenu.js +54 -0
  260. package/dist/navigation/NavMenu.js.map +1 -0
  261. package/dist/navigation/PageJump.js +3 -3
  262. package/dist/navigation/PageJump.js.map +1 -1
  263. package/dist/navigation/PageSizeSelect.js +4 -4
  264. package/dist/navigation/PageSizeSelect.js.map +1 -1
  265. package/dist/navigation/Pagination.js +6 -6
  266. package/dist/navigation/Pagination.js.map +1 -1
  267. package/dist/navigation/PaginationBar.js +5 -5
  268. package/dist/navigation/PaginationBar.js.map +1 -1
  269. package/dist/navigation/Steps.js +4 -4
  270. package/dist/navigation/Steps.js.map +1 -1
  271. package/dist/navigation/TableOfContents.js +5 -5
  272. package/dist/navigation/TableOfContents.js.map +1 -1
  273. package/dist/navigation/Tabs.js +7 -7
  274. package/dist/navigation/Tabs.js.map +1 -1
  275. package/dist/navigation/Toolbar.js +3 -3
  276. package/dist/navigation/Toolbar.js.map +1 -1
  277. package/dist/overlay/AlertDialog.js +4 -4
  278. package/dist/overlay/AlertDialog.js.map +1 -1
  279. package/dist/overlay/CommandPalette.js +4 -4
  280. package/dist/overlay/CommandPalette.js.map +1 -1
  281. package/dist/overlay/ContextMenu.js +3 -3
  282. package/dist/overlay/ContextMenu.js.map +1 -1
  283. package/dist/overlay/Dialog.js +4 -4
  284. package/dist/overlay/Dialog.js.map +1 -1
  285. package/dist/overlay/Drawer.js +5 -5
  286. package/dist/overlay/Drawer.js.map +1 -1
  287. package/dist/overlay/HoverCard.js +5 -3
  288. package/dist/overlay/HoverCard.js.map +1 -1
  289. package/dist/overlay/Lightbox.js +5 -5
  290. package/dist/overlay/Lightbox.js.map +1 -1
  291. package/dist/overlay/Menu.js +7 -7
  292. package/dist/overlay/Menu.js.map +1 -1
  293. package/dist/overlay/ModalCore.js +9 -9
  294. package/dist/overlay/ModalCore.js.map +1 -1
  295. package/dist/overlay/Popconfirm.js +6 -6
  296. package/dist/overlay/Popconfirm.js.map +1 -1
  297. package/dist/overlay/Popover.js +5 -3
  298. package/dist/overlay/Popover.js.map +1 -1
  299. package/dist/overlay/Tooltip.js +5 -3
  300. package/dist/overlay/Tooltip.js.map +1 -1
  301. package/dist/overlay/Tour.js +8 -8
  302. package/dist/overlay/Tour.js.map +1 -1
  303. package/dist/overlay/detached.d.ts +2 -0
  304. package/dist/overlay/detached.js +73 -42
  305. package/dist/overlay/detached.js.map +1 -1
  306. package/dist/patterns/ActionBar.js +3 -3
  307. package/dist/patterns/ActionBar.js.map +1 -1
  308. package/dist/patterns/AppShell.d.ts +28 -1
  309. package/dist/patterns/AppShell.js +158 -52
  310. package/dist/patterns/AppShell.js.map +1 -1
  311. package/dist/patterns/AuthLayout.d.ts +28 -0
  312. package/dist/patterns/AuthLayout.js +77 -0
  313. package/dist/patterns/AuthLayout.js.map +1 -0
  314. package/dist/patterns/CommentThread.js +9 -9
  315. package/dist/patterns/CommentThread.js.map +1 -1
  316. package/dist/patterns/DataImport.js +4 -4
  317. package/dist/patterns/DataImport.js.map +1 -1
  318. package/dist/patterns/DeadlineBadge.js +3 -3
  319. package/dist/patterns/DeadlineBadge.js.map +1 -1
  320. package/dist/patterns/FilterBar.d.ts +11 -1
  321. package/dist/patterns/FilterBar.js +39 -10
  322. package/dist/patterns/FilterBar.js.map +1 -1
  323. package/dist/patterns/FormDialog.d.ts +18 -0
  324. package/dist/patterns/FormDialog.js +46 -0
  325. package/dist/patterns/FormDialog.js.map +1 -0
  326. package/dist/patterns/KanbanBoard.js +8 -8
  327. package/dist/patterns/KanbanBoard.js.map +1 -1
  328. package/dist/patterns/LayoutSwitcher.d.ts +12 -0
  329. package/dist/patterns/LayoutSwitcher.js +79 -0
  330. package/dist/patterns/LayoutSwitcher.js.map +1 -0
  331. package/dist/patterns/NotificationCenter.js +8 -8
  332. package/dist/patterns/NotificationCenter.js.map +1 -1
  333. package/dist/patterns/PageTabs.d.ts +12 -7
  334. package/dist/patterns/PageTabs.js +41 -29
  335. package/dist/patterns/PageTabs.js.map +1 -1
  336. package/dist/patterns/QueryTable.d.ts +7 -1
  337. package/dist/patterns/QueryTable.js +116 -81
  338. package/dist/patterns/QueryTable.js.map +1 -1
  339. package/dist/patterns/SlideCaptcha.d.ts +80 -0
  340. package/dist/patterns/SlideCaptcha.js +354 -0
  341. package/dist/patterns/SlideCaptcha.js.map +1 -0
  342. package/dist/patterns/StepsForm.js +7 -7
  343. package/dist/patterns/StepsForm.js.map +1 -1
  344. package/dist/patterns/ThemeSwitcher.js +3 -3
  345. package/dist/patterns/ThemeSwitcher.js.map +1 -1
  346. package/dist/patterns/index.d.ts +7 -3
  347. package/dist/patterns/index.js +5 -1
  348. package/dist/patterns/messages.d.ts +37 -1
  349. package/dist/patterns/messages.js +38 -2
  350. package/dist/patterns/messages.js.map +1 -1
  351. package/dist/table/ColumnHeaderActions.js +3 -3
  352. package/dist/table/ColumnHeaderActions.js.map +1 -1
  353. package/dist/table/ColumnResizer.js +3 -3
  354. package/dist/table/ColumnResizer.js.map +1 -1
  355. package/dist/table/ColumnSettings.js +5 -5
  356. package/dist/table/ColumnSettings.js.map +1 -1
  357. package/dist/table/ColumnTable.js +8 -8
  358. package/dist/table/ColumnTable.js.map +1 -1
  359. package/dist/table/DataTable.js +8 -8
  360. package/dist/table/DataTable.js.map +1 -1
  361. package/dist/table/DataTableView.js +21 -21
  362. package/dist/table/DataTableView.js.map +1 -1
  363. package/dist/table/PivotTable.js +3 -3
  364. package/dist/table/PivotTable.js.map +1 -1
  365. package/dist/table/SelectionBar.js +4 -4
  366. package/dist/table/SelectionBar.js.map +1 -1
  367. package/dist/table/TreeDataTable.js +5 -5
  368. package/dist/table/TreeDataTable.js.map +1 -1
  369. package/dist/theme-customize/ThemeCustomizer.js +7 -6
  370. package/dist/theme-customize/ThemeCustomizer.js.map +1 -1
  371. package/dist/theme-customize/ThemeThumbnail.js +3 -3
  372. package/dist/theme-customize/ThemeThumbnail.js.map +1 -1
  373. package/dist/three/background/AuroraBackground.js +3 -3
  374. package/dist/three/background/AuroraBackground.js.map +1 -1
  375. package/dist/three/background/MeshGradient.js +3 -3
  376. package/dist/three/background/MeshGradient.js.map +1 -1
  377. package/dist/three/background/ShaderBackground.js +3 -3
  378. package/dist/three/background/ShaderBackground.js.map +1 -1
  379. package/dist/three/core/EffectSurface.js +3 -3
  380. package/dist/three/core/EffectSurface.js.map +1 -1
  381. package/dist/three/core/ThreeCanvas.js +4 -4
  382. package/dist/three/core/ThreeCanvas.js.map +1 -1
  383. package/dist/three/effects/Confetti.js +3 -3
  384. package/dist/three/effects/Confetti.js.map +1 -1
  385. package/dist/three/effects/ParticleField.js +3 -3
  386. package/dist/three/effects/ParticleField.js.map +1 -1
  387. package/dist/three/effects/WaveGrid.js +3 -3
  388. package/dist/three/effects/WaveGrid.js.map +1 -1
  389. package/dist/three/globe/Globe.js +3 -3
  390. package/dist/three/globe/Globe.js.map +1 -1
  391. package/dist/three/model/ModelViewer.js +3 -3
  392. package/dist/three/model/ModelViewer.js.map +1 -1
  393. package/dist/utils/data/number.d.ts +5 -0
  394. package/dist/utils/data/number.js +8 -1
  395. package/dist/utils/data/number.js.map +1 -1
  396. package/dist/utils/dom/element.d.ts +3 -1
  397. package/dist/utils/dom/element.js +8 -4
  398. package/dist/utils/dom/element.js.map +1 -1
  399. package/dist/utils/dom/fullscreen.d.ts +1 -1
  400. package/dist/utils/dom/fullscreen.js +12 -8
  401. package/dist/utils/dom/fullscreen.js.map +1 -1
  402. package/dist/utils/dom/mounted.d.ts +7 -0
  403. package/dist/utils/dom/mounted.js +16 -0
  404. package/dist/utils/dom/mounted.js.map +1 -0
  405. package/dist/utils/dom/overflow.js +2 -1
  406. package/dist/utils/dom/overflow.js.map +1 -1
  407. package/dist/utils/dom/pan-zoom.js +2 -1
  408. package/dist/utils/dom/pan-zoom.js.map +1 -1
  409. package/dist/utils/props.js +3 -13
  410. package/dist/utils/props.js.map +1 -1
  411. package/dist/utils/request/http.d.ts +12 -0
  412. package/dist/utils/request/http.js +6 -2
  413. package/dist/utils/request/http.js.map +1 -1
  414. package/dist/utils/request/use-request.js +4 -2
  415. package/dist/utils/request/use-request.js.map +1 -1
  416. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"Upload.js","names":["_isVNode","Upload","_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","_mergeProps","FileIcon","_Fragment"],"sources":["../../src/input/Upload.tsx"],"sourcesContent":["/**\n * 上传(div):FileDrop 选文件,下面列出文件、上传进度、失败重试与移除。只负责界面与状态,怎样上传由 upload 决定:\n *\n * <Upload\n * _value={files}\n * multiple\n * accept=\"image/*\"\n * maxSize={5_000_000}\n * upload={(file, { onProgress, signal }) => api.upload(file, { onProgress, signal })}\n * />\n * <Upload _value={files} action=\"/files\" /> 用应用配置的请求客户端(http)上传\n *\n * - value 是 UploadFile 的数组(文件、状态、进度、错误、upload 的结果),父级写 _value={list};\n * - 给了 upload 或 action 时选到文件就开始上传,否则停在 selected(等提交时一起上传);移除正在上传的文件会中止(signal);\n * - action:经 createUi / Provider 的 http 把文件 POST 过去(multipart,字段名 fieldName),与其他请求共用 baseURL、令牌与拆包;\n * fetch 拿不到上传的字节进度,进度条是不确定的,要进度时写 upload(XMLHttpRequest 的 upload.onprogress);\n * - 超过 maxSize、不在 accept 里的文件也列出来,带错误、不上传;单选(不写 multiple)时新文件替换旧的;\n * - 已有文件(之前上传过、从后端读回来的)用 existingUploadFile 放进 value:状态是 done,没有 File,\n * 给了 url 时文件名链到它(预览、下载),可以移除;\n *\n * let files = _state([existingUploadFile({ name: '验证报告.pdf', url: '/files/123' })]);\n * - 在 Field 里时关联标签与错误;写了 name 时有一个隐藏的 file input 带着全部文件,原生提交(FormData)也拿得到。\n *\n * - 图片墙(listType=\"picture\"):方形缩略图(选的文件用本地地址显示,不等上传),点开看大图(整面墙是一个 ImageGroup,\n * 大图里左右切换);上传中盖一层进度,失败标红;选文件的区域是墙上最后一格。sortable 时拖动把手(或聚焦后用键盘)调整顺序,\n * pasteable 时焦点在组件里按 Ctrl + V 把剪贴板里的图片加进来(截图、从别处复制的图)。\n *\n * 部件:Root(div)、Drop(FileDrop)、List(ul)、Item(li)、Icon(文件图标)、Body(文件名与下一行)、Name、Meta(大小或错误)、\n * Progress、Retry(重试按钮)、Remove(移除按钮)。\n */\nimport {\n CircleAlert,\n CircleCheck,\n File as FileIcon,\n GripVertical,\n ImagePlus,\n RotateCw,\n X,\n} from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { onBeforeUnmount, watch } from 'vue';\nimport { ButtonBase } from '../base/ButtonBase';\nimport { Image, ImageGroup } from '../display/Image';\nimport { useSortable } from '../utils/dom/sortable';\nimport { Icon, type IconProps } from '../base/Icon';\nimport { Link } from '../base/Link';\nimport { IconButton, type IconButtonProps } from '../base/IconButton';\nimport { VisuallyHidden } from '../base/VisuallyHidden';\nimport { useLang } from '../config/context';\nimport { useFormat } from '../config/lang/format';\nimport { useFieldControl } from '../form/Field';\nimport { useHttp } from '../utils/request/http';\nimport { errorCodeText } from '../utils/request/error-message';\nimport { Progress, type ProgressProps } from '../feedback/Progress';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { itemStyles } from '../utils/style/item-styles';\nimport { FileDrop, matchesAccept, type FileDropProps } from './FileDrop';\nimport { GridList, type GridProps } from '../layout/Grid';\n\n/** 列表里的一个文件 */\nexport interface UploadFile {\n /** 组件给的 id,同一个列表里唯一 */\n readonly id: string;\n /** 文件名 */\n readonly name: string;\n /** 大小(字节);已有文件不知道时为 undefined */\n readonly size?: number;\n /** 选的文件;已有文件没有 */\n readonly file?: File;\n /** 已有文件的地址:文件名链到它 */\n readonly url?: string;\n /** selected:选了、还没上传;uploading:上传中;done:完成;error:失败或没通过检查 */\n readonly status: 'selected' | 'uploading' | 'done' | 'error';\n /** 上传进度 0–1;upload 没报告进度时为 undefined(不确定进度) */\n readonly progress?: number;\n /** 错误信息 */\n readonly error?: string;\n /** 没通过大小或类型检查:不会上传,也不能重试 */\n readonly rejected?: boolean;\n /** upload 的返回值(如文件地址) */\n readonly response?: unknown;\n}\n\n/** 上传一个文件:报告进度、响应中止;成功时 resolve(值记在 response 上),失败时 reject */\nexport type UploadHandler = (\n file: File,\n context: { onProgress: (fraction: number) => void; signal: AbortSignal },\n) => Promise<unknown>;\n\n/** 列表的样子 */\nexport interface UploadListTypes {\n /** 一行一个文件:图标、文件名、大小或进度(默认) */\n text: unknown;\n /** 图片墙:方形缩略图,点开看大图 */\n picture: unknown;\n}\n\n/** 未声明的属性落到外层 div 上 */\nexport interface UploadProps extends PartProps<'div'> {\n /** 文件列表:父级写 _value={list} */\n _value?: UploadFile[];\n /** 怎样上传一个文件;不写时用 action,都没有时只选文件、不上传 */\n upload?: UploadHandler;\n /** 上传地址:没写 upload 时用应用配置的请求客户端(useHttp)POST 过去,响应体记在 response 上 */\n action?: string;\n /** action 上传时文件在表单里的字段名,默认 file */\n fieldName?: string;\n /** 接受的文件类型(同原生 accept) */\n accept?: string;\n /** 可以选多个;不写时新文件替换旧的 */\n multiple?: boolean;\n /** 单个文件的大小上限(字节) */\n maxSize?: number;\n /** 最多几个文件,超出的不加进来 */\n maxFiles?: number;\n /** 原生表单提交时的字段名:写了才有隐藏的 file input */\n name?: string;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:只列出文件,不能再选、不能移除或重试 */\n readonly?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 必填 */\n required?: boolean;\n /** 选择区域里提示文字下面的说明(大小、类型限制) */\n description?: FileDropProps['description'];\n /** 列表的样子:text 一行一个文件(默认),picture 是图片墙 */\n listType?: keyof UploadListTypes;\n /** 图片墙里缩略图的边长(px),默认 104 */\n thumbnailSize?: number;\n /** 拖动把手(或聚焦后用键盘)调整文件的顺序(图片墙) */\n sortable?: boolean;\n /** 焦点在组件里时 Ctrl + V 把剪贴板里的图片、文件加进来 */\n pasteable?: boolean;\n /** 选择区域(FileDrop)的部件属性 */\n propsDrop?: Partial<FileDropProps>;\n /** 列表的部件属性 */\n propsList?: Partial<GridProps<'ul'>>;\n /** 每一项的部件属性,可以按文件计算 */\n propsItem?: PartProps<'li'> | ((file: UploadFile) => PartProps<'li'>);\n /** 每一项的文件图标(按状态是文件、对勾或警告)的部件属性 */\n propsIcon?: Partial<IconProps>;\n /** 每一项里文件名与下一行(大小、错误或进度)的外层的部件属性 */\n propsBody?: PartProps<'div'>;\n /** 每一项里文件名的部件属性 */\n propsName?: PartProps<'span'>;\n /** 每一项里文件大小或错误信息的部件属性 */\n propsMeta?: PartProps<'span'>;\n /** 每一项上传中的进度条的部件属性;进度与名称(文件名)由组件管理 */\n propsProgress?: Omit<Partial<ProgressProps>, 'value' | 'aria-label'>;\n /**\n * 每一项失败后的重试按钮的部件属性。名称(重新上传 文件名)每项不同,由组件按语言包生成,\n * 改文案请改语言包的 uploadRetry;点击由组件管理\n */\n propsRetry?: Omit<Partial<IconButtonProps>, 'aria-label' | 'onClick'>;\n /** 每一项的移除按钮的部件属性;名称(语言包的 uploadRemove)、点击与不可用由组件管理 */\n propsRemove?: Omit<Partial<IconButtonProps>, 'aria-label' | 'onClick' | 'disabled'>;\n}\n\n/** Upload 的样式:root、list、item、icon、body、name、meta、error、progress */\nexport const uploadStyles = css.create({\n root: { display: 'grid', gap: '_sm' },\n item: {\n cursor: 'default',\n gap: '_sm',\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_borderMuted',\n borderRadius: '_md',\n },\n icon: { flexShrink: 0, color: '_textMuted' },\n body: { display: 'grid', gap: '_xs', flexGrow: 1, minWidth: 0 },\n name: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' },\n meta: { fontSize: '_sm', color: '_textMuted' },\n error: { color: '_dangerText' },\n done: { color: '_successText' },\n progress: { width: '_full' },\n // 图片墙:缩略图与“添加图片”一样大,排成一行、放不下换行\n wall: { display: 'flex', flexWrap: 'wrap', gap: '_sm' },\n wallList: { display: 'contents' },\n card: {\n position: 'relative',\n boxSizing: 'border-box',\n flexShrink: 0,\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_borderMuted',\n borderRadius: '_md',\n overflow: 'hidden',\n backgroundColor: '_fill',\n },\n cardError: { borderColor: '_danger' },\n // 选文件的那一格:同样大小,图标与文字居中\n addCard: { padding: '_xs', gap: '_xs', textAlign: 'center', fontSize: '_sm' },\n // 上传中、失败:盖在缩略图上\n overlay: {\n position: 'absolute',\n insetInline: 0,\n bottom: 0,\n display: 'flex',\n flexDirection: 'column',\n gap: '_xs',\n padding: '_xs',\n backgroundColor: 'rgb(0 0 0 / 0.55)',\n color: 'white',\n fontSize: '_xs',\n },\n placeholder: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '_xs',\n width: '_full',\n height: '_full',\n padding: '_xs',\n boxSizing: 'border-box',\n color: '_textMuted',\n fontSize: '_xs',\n textAlign: 'center',\n overflowWrap: 'anywhere',\n },\n // 右上角的把手、重试、移除:浅色底上的小按钮\n actions: {\n position: 'absolute',\n top: '_xs',\n insetInlineEnd: '_xs',\n display: 'flex',\n gap: '2px',\n },\n action: { backgroundColor: { default: 'rgb(255 255 255 / 0.85)', ':hover': 'white' } },\n handle: {\n display: 'grid',\n placeItems: 'center',\n width: '1.75em',\n height: '1.75em',\n borderRadius: '_sm',\n color: '_text',\n backgroundColor: 'rgb(255 255 255 / 0.85)',\n cursor: { default: 'grab', ':active': 'grabbing' },\n touchAction: 'none',\n },\n});\n\n/** Upload 的动态样式:缩略图的边长 */\nexport const uploadDynamicStyles = css.create({\n square: (size: number) => ({ width: `${size}px`, height: `${size}px` }),\n});\n\nlet nextId = 0;\n\n/** 已有文件(之前上传过、从后端读回来的):放进 Upload 的 value,状态是 done */\nexport function existingUploadFile(file: {\n /** 标识;不写时生成一个 */\n id?: string;\n /** 文件名 */\n name: string;\n /** 大小(字节) */\n size?: number;\n /** 地址:文件名链到它 */\n url?: string;\n}): UploadFile {\n return { ...file, id: file.id ?? `upload-${++nextId}`, status: 'done', response: file.url };\n}\n\n/** 上传:选文件、列出文件与进度、失败重试、移除 */\nexport const Upload = _component(\n ({\n _value: value = _bindable<UploadFile[]>([]),\n upload,\n action,\n fieldName = 'file',\n accept,\n multiple = false,\n maxSize,\n maxFiles,\n name,\n disabled,\n readonly,\n invalid,\n required,\n description,\n listType = 'text',\n thumbnailSize = 104,\n sortable = false,\n pasteable = false,\n propsDrop,\n propsList,\n propsItem,\n propsIcon,\n propsBody,\n propsName,\n propsMeta,\n propsProgress,\n propsRetry,\n propsRemove,\n ...rest\n }: UploadProps) => {\n const lang = useLang();\n const format = useFormat();\n // delegate:里面的 FileDrop 照常从 Field 拿 id、说明与标签\n const control = useFieldControl(() => ({ invalid, required, disabled, readonly }), {\n delegate: true,\n });\n const http = useHttp();\n /** 实际用的上传函数:upload 优先,其次按 action 用请求客户端发 */\n const uploader = (): UploadHandler | undefined =>\n upload ??\n (action\n ? (file, { signal }) => {\n const body = new FormData();\n body.append(fieldName, file);\n return http.request({ method: 'POST', url: action, body, signal });\n }\n : undefined);\n let hidden = _state.raw<HTMLInputElement | null>(null);\n // 每个正在上传的文件一个:移除、重试、卸载时中止\n const controllers = new Map<string, AbortController>();\n onBeforeUnmount(() => controllers.forEach((controller) => controller.abort()));\n\n const patch = (id: string, changes: Partial<UploadFile>) =>\n (value = value.map((item) => (item.id === id ? { ...item, ...changes } : item)));\n\n async function start(item: UploadFile) {\n const send = uploader();\n if (!send || !item.file) return;\n controllers.get(item.id)?.abort();\n const controller = new AbortController();\n controllers.set(item.id, controller);\n patch(item.id, { status: 'uploading', progress: undefined, error: undefined });\n try {\n const response = await send(item.file!, {\n onProgress: (fraction) => {\n if (!controller.signal.aborted) patch(item.id, { progress: fraction });\n },\n signal: controller.signal,\n });\n if (!controller.signal.aborted) patch(item.id, { status: 'done', progress: 1, response });\n } catch (error) {\n if (controller.signal.aborted) return;\n // 码有文案时按码(网络断了、后端拒绝),否则是上传函数自己的说明,再没有是笼统的“上传失败”\n const message =\n errorCodeText(error, lang) ??\n (error instanceof Error && error.message ? error.message : lang.uploadFailed);\n patch(item.id, { status: 'error', error: message });\n } finally {\n if (controllers.get(item.id) === controller) controllers.delete(item.id);\n }\n }\n\n function remove(id: string) {\n controllers.get(id)?.abort();\n controllers.delete(id);\n value = value.filter((item) => item.id !== id);\n }\n\n function add(files: File[], rejectedType = false) {\n const entries = files.map((file): UploadFile => {\n const base = { id: `upload-${++nextId}`, name: file.name, size: file.size, file };\n if (rejectedType) {\n return { ...base, status: 'error', error: lang.fileTypeRejected, rejected: true };\n }\n if (maxSize != null && file.size > maxSize) {\n const error = lang.fileTooLarge(format.fileSize(maxSize));\n return { ...base, status: 'error', error, rejected: true };\n }\n return { ...base, status: 'selected' };\n });\n if (!multiple) value.forEach((item) => controllers.get(item.id)?.abort());\n const kept = multiple ? value : [];\n const room = maxFiles == null ? entries.length : Math.max(0, maxFiles - kept.length);\n const added = (multiple ? entries : entries.slice(-1)).slice(0, room);\n value = [...kept, ...added];\n added.filter((item) => item.status === 'selected').forEach((item) => void start(item));\n }\n\n // 图片墙里选的文件的本地地址:用完(移除、卸载)回收\n const previews = new Map<string, string>();\n const previewOf = (item: UploadFile) => {\n if (item.url) return item.url;\n if (!item.file || !item.file.type.startsWith('image/')) return undefined;\n let url = previews.get(item.id);\n if (!url) previews.set(item.id, (url = URL.createObjectURL(item.file)));\n return url;\n };\n watch(\n () => value,\n (list) => {\n const kept = new Set(list.map((item) => item.id));\n for (const [id, url] of previews)\n if (!kept.has(id)) {\n URL.revokeObjectURL(url);\n previews.delete(id);\n }\n },\n );\n onBeforeUnmount(() => previews.forEach((url) => URL.revokeObjectURL(url)));\n\n let wall = _state.raw<HTMLElement | null>(null);\n const sortableWall = useSortable<UploadFile>({\n items: () => value,\n getKey: (item) => item.id,\n getLabel: (item) => item.name,\n onChange: (next) => (value = next),\n container: () => wall,\n orientation: () => 'horizontal',\n disabled: () => !sortable || control().readonly || control().disabled,\n });\n\n /** 粘贴:剪贴板里的文件(截图是 image/png)按 accept 分开,不符合的照常列出、带错误 */\n function onPaste(event: ClipboardEvent) {\n const state = control();\n if (!pasteable || state.disabled || state.readonly) return;\n const files = [...(event.clipboardData?.files ?? [])];\n if (files.length === 0) return;\n event.preventDefault();\n const accepted = files.filter((file) => matchesAccept(file, accept));\n const rejected = files.filter((file) => !matchesAccept(file, accept));\n if (accepted.length) add(accepted);\n if (rejected.length) add(rejected, true);\n }\n\n // 隐藏的 file input 带着全部可提交的文件:原生提交、FormData 拿得到\n _effect(() => {\n if (!hidden || typeof DataTransfer === 'undefined') return;\n const transfer = new DataTransfer();\n for (const item of value) if (item.file && !item.rejected) transfer.items.add(item.file);\n hidden.files = transfer.files;\n });\n\n function renderItem(item: UploadFile) {\n const state = control();\n const own = typeof propsItem === 'function' ? propsItem(item) : propsItem;\n const fileName = item.name;\n const failed = item.status === 'error';\n return (\n <li\n key={item.id}\n {...mergeAttrs<'li'>({ sx: [itemStyles.row, uploadStyles.item] }, own)}\n data-state={item.status}\n >\n <Icon\n {...mergePartProps<IconProps>(\n {\n icon: failed ? CircleAlert : item.status === 'done' ? CircleCheck : FileIcon,\n sx: [\n uploadStyles.icon,\n failed && uploadStyles.error,\n item.status === 'done' && uploadStyles.done,\n ],\n },\n propsIcon,\n )}\n />\n <div {...mergeAttrs<'div'>({ sx: uploadStyles.body }, propsBody)}>\n <span {...mergeAttrs<'span'>({ sx: uploadStyles.name }, propsName)}>\n {item.url ? (\n <Link href={item.url} target=\"_blank\">\n {fileName}\n </Link>\n ) : (\n fileName\n )}\n </span>\n {item.status === 'uploading' ? (\n <Progress\n {...mergePartProps<ProgressProps>(\n { size: 'xs', sx: uploadStyles.progress },\n propsProgress,\n {\n value: item.progress == null ? null : Math.round(item.progress * 100),\n 'aria-label': fileName,\n },\n )}\n />\n ) : (\n <span\n {...mergeAttrs<'span'>(\n { sx: [uploadStyles.meta, failed && uploadStyles.error] },\n propsMeta,\n )}\n >\n {failed ? item.error : item.size != null && format.fileSize(item.size)}\n {item.status === 'done' && <VisuallyHidden> {lang.uploadDone}</VisuallyHidden>}\n </span>\n )}\n </div>\n {failed && uploader() && !item.rejected && !state.readonly && (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: RotateCw,\n variant: 'ghost',\n size: 'sm',\n // 名称带文件名、每项不同:类型里不让使用方覆盖(同一个值会让各项的按钮同名)\n 'aria-label': lang.uploadRetry(fileName),\n },\n propsRetry,\n { onClick: () => void start(item) },\n )}\n />\n )}\n {!state.readonly && (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: X,\n variant: 'ghost',\n size: 'sm',\n 'aria-label': lang.uploadRemove(fileName),\n },\n propsRemove,\n { disabled: state.disabled, onClick: () => remove(item.id) },\n )}\n />\n )}\n </li>\n );\n }\n\n /** 图片墙的一格:缩略图(点开看大图)、上传进度或错误、把手、重试与移除 */\n function renderCard(item: UploadFile) {\n const state = control();\n const failed = item.status === 'error';\n const src = previewOf(item);\n return (\n <div\n key={item.id}\n {...mergeAttrs<'div'>(\n {\n sx: [\n uploadStyles.card,\n uploadDynamicStyles.square(thumbnailSize),\n failed && uploadStyles.cardError,\n ],\n },\n sortableWall.itemProps(item.id),\n { role: 'listitem' },\n )}\n data-state={item.status}\n >\n {src && !item.rejected ? (\n <Image\n src={src}\n alt={item.name}\n width={thumbnailSize - 2}\n height={thumbnailSize - 2}\n radius=\"none\"\n preview={{ caption: item.name, download: item.name }}\n />\n ) : (\n <div {...css.attrs(uploadStyles.placeholder)}>\n <Icon icon={failed ? CircleAlert : FileIcon} sx={failed && uploadStyles.error} />\n {item.name}\n </div>\n )}\n {item.status === 'uploading' && (\n <div {...css.attrs(uploadStyles.overlay)}>\n <Progress\n {...mergePartProps<ProgressProps>({ size: 'xs' }, propsProgress, {\n value: item.progress == null ? null : Math.round(item.progress * 100),\n 'aria-label': item.name,\n })}\n />\n </div>\n )}\n {failed && src && !item.rejected && (\n <div {...css.attrs(uploadStyles.overlay)} title={item.error}>\n {item.error}\n </div>\n )}\n {item.status === 'done' && <VisuallyHidden>{lang.uploadDone}</VisuallyHidden>}\n {!state.readonly && (\n <div {...css.attrs(uploadStyles.actions)}>\n {sortable && (\n <ButtonBase\n sx={uploadStyles.handle}\n ripple={false}\n disabled={state.disabled}\n aria-label={lang.sortableHandle(item.name)}\n {...sortableWall.handleProps(item.id)}\n >\n <Icon icon={GripVertical} />\n </ButtonBase>\n )}\n {failed && uploader() && !item.rejected && (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: RotateCw,\n variant: 'ghost',\n size: 'xs',\n sx: uploadStyles.action,\n 'aria-label': lang.uploadRetry(item.name),\n },\n propsRetry,\n { onClick: () => void start(item) },\n )}\n />\n )}\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: X,\n variant: 'ghost',\n size: 'xs',\n sx: uploadStyles.action,\n 'aria-label': lang.uploadRemove(item.name),\n },\n propsRemove,\n { disabled: state.disabled, onClick: () => remove(item.id) },\n )}\n />\n </div>\n )}\n </div>\n );\n }\n\n /** 选文件的区域:列表模式在上方,图片墙模式是最后一格 */\n function renderDrop(picture: boolean) {\n const state = control();\n const full = maxFiles != null && multiple && value.length >= maxFiles;\n if (state.readonly || (picture && full)) return null;\n const hint = pasteable ? lang.uploadPasteHint : undefined;\n const props = mergePartProps<FileDropProps>(\n {\n accept,\n multiple,\n disabled: state.disabled,\n invalid: state.invalid,\n // 选好的文件不在这个输入框里(它选完就清空):已有文件时不再原生必填,免得表单交不了\n required: state.required && value.length === 0,\n description: picture\n ? undefined\n : hint\n ? [description, description != null && ' · ', hint]\n : description,\n propsRoot: picture\n ? { sx: [uploadStyles.addCard, uploadDynamicStyles.square(thumbnailSize)] }\n : undefined,\n },\n propsDrop,\n {\n onFiles: (files: File[]) => add(files),\n onReject: (files: File[]) => add(files, true),\n },\n );\n // 列表模式不传子元素:FileDrop 用默认的图标、提示与说明(写了 undefined 也算传了,会把默认内容换掉)\n if (!picture) return <FileDrop {...props} />;\n return (\n <FileDrop {...props}>\n <Icon icon={ImagePlus} />\n {lang.uploadAddImage}\n </FileDrop>\n );\n }\n\n return () => {\n const state = control();\n if (listType === 'picture')\n return (\n <div {...mergeAttrs<'div'>({ sx: uploadStyles.root }, rest, { onPaste })}>\n <ImageGroup sx={uploadStyles.wall}>\n {/* 列表里只有缩略图(“添加图片”与预览不是列表项);display: contents,缩略图仍和“添加图片”排在一行 */}\n <div\n ref={_toRef(wall)}\n role=\"list\"\n // 状态变化(失败、完成)由读屏播报\n aria-live=\"polite\"\n {...css.attrs(uploadStyles.wallList)}\n >\n {value.map(renderCard)}\n </div>\n {renderDrop(true)}\n </ImageGroup>\n {pasteable && !state.readonly && (\n <span {...css.attrs(uploadStyles.meta)}>\n {[description, description != null && ' · ', lang.uploadPasteHint]}\n </span>\n )}\n {sortable && (\n <>\n <VisuallyHidden id={sortableWall.instructionsId}>\n {lang.sortableInstructions}\n </VisuallyHidden>\n <VisuallyHidden aria-live=\"assertive\">{sortableWall.announcement}</VisuallyHidden>\n </>\n )}\n {name != null && (\n <input\n ref={_toRef(hidden)}\n type=\"file\"\n name={name}\n multiple\n hidden\n tabindex={-1}\n aria-hidden=\"true\"\n />\n )}\n </div>\n );\n return (\n <div {...mergeAttrs<'div'>({ sx: uploadStyles.root }, rest, { onPaste })}>\n {renderDrop(false)}\n {name != null && (\n <input\n ref={_toRef(hidden)}\n type=\"file\"\n name={name}\n multiple\n hidden\n tabindex={-1}\n aria-hidden=\"true\"\n />\n )}\n {value.length > 0 && (\n // 状态变化(失败、完成)由读屏播报\n <GridList\n {...mergePartProps<GridProps<'ul'>>({ gap: 'xs' }, propsList)}\n aria-live=\"polite\"\n >\n {value.map(renderItem)}\n </GridList>\n )}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"Upload.js","names":["_isVNode","Upload","_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","_mergeProps","FileIcon","_Fragment"],"sources":["../../src/input/Upload.tsx"],"sourcesContent":["/**\n * 上传(div):FileDrop 选文件,下面列出文件、上传进度、失败重试与移除。只负责界面与状态,怎样上传由 upload 决定:\n *\n * <Upload\n * _value={files}\n * multiple\n * accept=\"image/*\"\n * maxSize={5_000_000}\n * upload={(file, { onProgress, signal }) => api.upload(file, { onProgress, signal })}\n * />\n * <Upload _value={files} action=\"/files\" /> 用应用配置的请求客户端(http)上传\n *\n * - value 是 UploadFile 的数组(文件、状态、进度、错误、upload 的结果),父级写 _value={list};\n * - 给了 upload 或 action 时选到文件就开始上传,否则停在 selected(等提交时一起上传);移除正在上传的文件会中止(signal);\n * - action:经 createUi / Provider 的 http 把文件 POST 过去(multipart,字段名 fieldName),与其他请求共用 baseURL、令牌与拆包;\n * fetch 拿不到上传的字节进度,进度条是不确定的,要进度时写 upload(XMLHttpRequest 的 upload.onprogress);\n * - 超过 maxSize、不在 accept 里的文件也列出来,带错误、不上传;单选(不写 multiple)时新文件替换旧的;\n * - 已有文件(之前上传过、从后端读回来的)用 existingUploadFile 放进 value:状态是 done,没有 File,\n * 给了 url 时文件名链到它(预览、下载),可以移除;\n *\n * let files = _state([existingUploadFile({ name: '验证报告.pdf', url: '/files/123' })]);\n * - 在 Field 里时关联标签与错误;写了 name 时有一个隐藏的 file input 带着全部文件,原生提交(FormData)也拿得到。\n *\n * - 图片墙(listType=\"picture\"):方形缩略图(选的文件用本地地址显示,不等上传),点开看大图(整面墙是一个 ImageGroup,\n * 大图里左右切换);上传中盖一层进度,失败标红;选文件的区域是墙上最后一格。sortable 时拖动把手(或聚焦后用键盘)调整顺序,\n * pasteable 时焦点在组件里按 Ctrl + V 把剪贴板里的图片加进来(截图、从别处复制的图)。\n *\n * 部件:Root(div)、Drop(FileDrop)、List(ul)、Item(li)、Icon(文件图标)、Body(文件名与下一行)、Name、Meta(大小或错误)、\n * Progress、Retry(重试按钮)、Remove(移除按钮)。\n */\nimport {\n CircleAlert,\n CircleCheck,\n File as FileIcon,\n GripVertical,\n ImagePlus,\n RotateCw,\n X,\n} from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { onBeforeUnmount, watch } from 'vue';\nimport { ButtonBase } from '../base/ButtonBase';\nimport { Image, ImageGroup } from '../display/Image';\nimport { useSortable } from '../utils/dom/sortable';\nimport { Icon, type IconProps } from '../base/Icon';\nimport { Link } from '../base/Link';\nimport { IconButton, type IconButtonProps } from '../base/IconButton';\nimport { VisuallyHidden } from '../base/VisuallyHidden';\nimport { useLang } from '../config/context';\nimport { useFormat } from '../config/lang/format';\nimport { useFieldControl } from '../form/Field';\nimport { useHttp } from '../utils/request/http';\nimport { errorCodeText } from '../utils/request/error-message';\nimport { Progress, type ProgressProps } from '../feedback/Progress';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { itemStyles } from '../utils/style/item-styles';\nimport { FileDrop, matchesAccept, type FileDropProps } from './FileDrop';\nimport { GridList, type GridProps } from '../layout/Grid';\n\n/** 列表里的一个文件 */\nexport interface UploadFile {\n /** 组件给的 id,同一个列表里唯一 */\n readonly id: string;\n /** 文件名 */\n readonly name: string;\n /** 大小(字节);已有文件不知道时为 undefined */\n readonly size?: number;\n /** 选的文件;已有文件没有 */\n readonly file?: File;\n /** 已有文件的地址:文件名链到它 */\n readonly url?: string;\n /** selected:选了、还没上传;uploading:上传中;done:完成;error:失败或没通过检查 */\n readonly status: 'selected' | 'uploading' | 'done' | 'error';\n /** 上传进度 0–1;upload 没报告进度时为 undefined(不确定进度) */\n readonly progress?: number;\n /** 错误信息 */\n readonly error?: string;\n /** 没通过大小或类型检查:不会上传,也不能重试 */\n readonly rejected?: boolean;\n /** upload 的返回值(如文件地址) */\n readonly response?: unknown;\n}\n\n/** 上传一个文件:报告进度、响应中止;成功时 resolve(值记在 response 上),失败时 reject */\nexport type UploadHandler = (\n file: File,\n context: { onProgress: (fraction: number) => void; signal: AbortSignal },\n) => Promise<unknown>;\n\n/** 列表的样子 */\nexport interface UploadListTypes {\n /** 一行一个文件:图标、文件名、大小或进度(默认) */\n text: unknown;\n /** 图片墙:方形缩略图,点开看大图 */\n picture: unknown;\n}\n\n/** 未声明的属性落到外层 div 上 */\nexport interface UploadProps extends PartProps<'div'> {\n /** 文件列表:父级写 _value={list} */\n _value?: UploadFile[];\n /** 怎样上传一个文件;不写时用 action,都没有时只选文件、不上传 */\n upload?: UploadHandler;\n /** 上传地址:没写 upload 时用应用配置的请求客户端(useHttp)POST 过去,响应体记在 response 上 */\n action?: string;\n /** action 上传时文件在表单里的字段名,默认 file */\n fieldName?: string;\n /** 接受的文件类型(同原生 accept) */\n accept?: string;\n /** 可以选多个;不写时新文件替换旧的 */\n multiple?: boolean;\n /** 单个文件的大小上限(字节) */\n maxSize?: number;\n /** 最多几个文件,超出的不加进来 */\n maxFiles?: number;\n /** 原生表单提交时的字段名:写了才有隐藏的 file input */\n name?: string;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:只列出文件,不能再选、不能移除或重试 */\n readonly?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 必填 */\n required?: boolean;\n /** 选择区域里提示文字下面的说明(大小、类型限制) */\n description?: FileDropProps['description'];\n /** 列表的样子:text 一行一个文件(默认),picture 是图片墙 */\n listType?: keyof UploadListTypes;\n /** 图片墙里缩略图的边长(px),默认 104 */\n thumbnailSize?: number;\n /** 拖动把手(或聚焦后用键盘)调整文件的顺序(图片墙) */\n sortable?: boolean;\n /** 焦点在组件里时 Ctrl + V 把剪贴板里的图片、文件加进来 */\n pasteable?: boolean;\n /** 选择区域(FileDrop)的部件属性 */\n propsDrop?: Partial<FileDropProps>;\n /** 列表的部件属性 */\n propsList?: Partial<GridProps<'ul'>>;\n /** 每一项的部件属性,可以按文件计算 */\n propsItem?: PartProps<'li'> | ((file: UploadFile) => PartProps<'li'>);\n /** 每一项的文件图标(按状态是文件、对勾或警告)的部件属性 */\n propsIcon?: Partial<IconProps>;\n /** 每一项里文件名与下一行(大小、错误或进度)的外层的部件属性 */\n propsBody?: PartProps<'div'>;\n /** 每一项里文件名的部件属性 */\n propsName?: PartProps<'span'>;\n /** 每一项里文件大小或错误信息的部件属性 */\n propsMeta?: PartProps<'span'>;\n /** 每一项上传中的进度条的部件属性;进度与名称(文件名)由组件管理 */\n propsProgress?: Omit<Partial<ProgressProps>, 'value' | 'aria-label'>;\n /**\n * 每一项失败后的重试按钮的部件属性。名称(重新上传 文件名)每项不同,由组件按语言包生成,\n * 改文案请改语言包的 uploadRetry;点击由组件管理\n */\n propsRetry?: Omit<Partial<IconButtonProps>, 'aria-label' | 'onClick'>;\n /** 每一项的移除按钮的部件属性;名称(语言包的 uploadRemove)、点击与不可用由组件管理 */\n propsRemove?: Omit<Partial<IconButtonProps>, 'aria-label' | 'onClick' | 'disabled'>;\n}\n\n/** Upload 的样式:root、list、item、icon、body、name、meta、error、progress */\nexport const uploadStyles = css.create({\n root: { display: 'grid', gap: '_sm' },\n item: {\n cursor: 'default',\n gap: '_sm',\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_borderMuted',\n borderRadius: '_md',\n },\n icon: { flexShrink: 0, color: '_textMuted' },\n body: { display: 'grid', gap: '_xs', flexGrow: 1, minWidth: 0 },\n name: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' },\n meta: { fontSize: '_sm', color: '_textMuted' },\n error: { color: '_dangerText' },\n done: { color: '_successText' },\n progress: { width: '_full' },\n // 图片墙:缩略图与“添加图片”一样大,排成一行、放不下换行\n wall: { display: 'flex', flexWrap: 'wrap', gap: '_sm' },\n wallList: { display: 'contents' },\n card: {\n position: 'relative',\n boxSizing: 'border-box',\n flexShrink: 0,\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_borderMuted',\n borderRadius: '_md',\n overflow: 'hidden',\n backgroundColor: '_fill',\n },\n cardError: { borderColor: '_danger' },\n // 选文件的那一格:同样大小,图标与文字居中\n addCard: { padding: '_xs', gap: '_xs', textAlign: 'center', fontSize: '_sm' },\n // 上传中、失败:盖在缩略图上\n overlay: {\n position: 'absolute',\n insetInline: 0,\n bottom: 0,\n display: 'flex',\n flexDirection: 'column',\n gap: '_xs',\n padding: '_xs',\n backgroundColor: 'rgb(0 0 0 / 0.55)',\n color: 'white',\n fontSize: '_xs',\n },\n placeholder: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '_xs',\n width: '_full',\n height: '_full',\n padding: '_xs',\n boxSizing: 'border-box',\n color: '_textMuted',\n fontSize: '_xs',\n textAlign: 'center',\n overflowWrap: 'anywhere',\n },\n // 右上角的把手、重试、移除:浅色底上的小按钮\n actions: {\n position: 'absolute',\n top: '_xs',\n insetInlineEnd: '_xs',\n display: 'flex',\n gap: '2px',\n },\n action: { backgroundColor: { default: 'rgb(255 255 255 / 0.85)', ':hover': 'white' } },\n handle: {\n display: 'grid',\n placeItems: 'center',\n width: '1.75em',\n height: '1.75em',\n borderRadius: '_sm',\n color: '_text',\n backgroundColor: 'rgb(255 255 255 / 0.85)',\n cursor: { default: 'grab', ':active': 'grabbing' },\n touchAction: 'none',\n },\n});\n\n/** Upload 的动态样式:缩略图的边长 */\nexport const uploadDynamicStyles = css.create({\n square: (size: number) => ({ width: `${size}px`, height: `${size}px` }),\n});\n\nlet nextId = 0;\n\n/** 已有文件(之前上传过、从后端读回来的):放进 Upload 的 value,状态是 done */\nexport function existingUploadFile(file: {\n /** 标识;不写时生成一个 */\n id?: string;\n /** 文件名 */\n name: string;\n /** 大小(字节) */\n size?: number;\n /** 地址:文件名链到它 */\n url?: string;\n}): UploadFile {\n return { ...file, id: file.id ?? `upload-${++nextId}`, status: 'done', response: file.url };\n}\n\n/** 上传:选文件、列出文件与进度、失败重试、移除 */\nexport const Upload = _component(\n ({\n _value: value = _bindable<UploadFile[]>([]),\n upload,\n action,\n fieldName = 'file',\n accept,\n multiple = false,\n maxSize,\n maxFiles,\n name,\n disabled,\n readonly,\n invalid,\n required,\n description,\n listType = 'text',\n thumbnailSize = 104,\n sortable = false,\n pasteable = false,\n propsDrop,\n propsList,\n propsItem,\n propsIcon,\n propsBody,\n propsName,\n propsMeta,\n propsProgress,\n propsRetry,\n propsRemove,\n ...rest\n }: UploadProps) => {\n const lang = useLang();\n const format = useFormat();\n // delegate:里面的 FileDrop 照常从 Field 拿 id、说明与标签\n const control = useFieldControl(() => ({ invalid, required, disabled, readonly }), {\n delegate: true,\n });\n const http = useHttp();\n /** 实际用的上传函数:upload 优先,其次按 action 用请求客户端发 */\n const uploader = (): UploadHandler | undefined =>\n upload ??\n (action\n ? (file, { signal }) => {\n const body = new FormData();\n body.append(fieldName, file);\n return http.request({ method: 'POST', url: action, body, signal });\n }\n : undefined);\n let hidden = _state.raw<HTMLInputElement | null>(null);\n // 每个正在上传的文件一个:移除、重试、卸载时中止\n const controllers = new Map<string, AbortController>();\n onBeforeUnmount(() => controllers.forEach((controller) => controller.abort()));\n\n const patch = (id: string, changes: Partial<UploadFile>) =>\n (value = value.map((item) => (item.id === id ? { ...item, ...changes } : item)));\n\n async function start(item: UploadFile) {\n const send = uploader();\n if (!send || !item.file) return;\n controllers.get(item.id)?.abort();\n const controller = new AbortController();\n controllers.set(item.id, controller);\n patch(item.id, { status: 'uploading', progress: undefined, error: undefined });\n try {\n const response = await send(item.file!, {\n onProgress: (fraction) => {\n if (!controller.signal.aborted) patch(item.id, { progress: fraction });\n },\n signal: controller.signal,\n });\n if (!controller.signal.aborted) patch(item.id, { status: 'done', progress: 1, response });\n } catch (error) {\n if (controller.signal.aborted) return;\n // 码有文案时按码(网络断了、后端拒绝),否则是上传函数自己的说明,再没有是笼统的“上传失败”\n const message =\n errorCodeText(error, lang) ??\n (error instanceof Error && error.message ? error.message : lang.uploadFailed);\n patch(item.id, { status: 'error', error: message });\n } finally {\n if (controllers.get(item.id) === controller) controllers.delete(item.id);\n }\n }\n\n function remove(id: string) {\n controllers.get(id)?.abort();\n controllers.delete(id);\n value = value.filter((item) => item.id !== id);\n }\n\n function add(files: File[], rejectedType = false) {\n const entries = files.map((file): UploadFile => {\n const base = { id: `upload-${++nextId}`, name: file.name, size: file.size, file };\n if (rejectedType) {\n return { ...base, status: 'error', error: lang.fileTypeRejected, rejected: true };\n }\n if (maxSize != null && file.size > maxSize) {\n const error = lang.fileTooLarge(format.fileSize(maxSize));\n return { ...base, status: 'error', error, rejected: true };\n }\n return { ...base, status: 'selected' };\n });\n if (!multiple) value.forEach((item) => controllers.get(item.id)?.abort());\n const kept = multiple ? value : [];\n const room = maxFiles == null ? entries.length : Math.max(0, maxFiles - kept.length);\n const added = (multiple ? entries : entries.slice(-1)).slice(0, room);\n value = [...kept, ...added];\n added.filter((item) => item.status === 'selected').forEach((item) => void start(item));\n }\n\n // 图片墙里选的文件的本地地址:用完(移除、卸载)回收\n const previews = new Map<string, string>();\n const previewOf = (item: UploadFile) => {\n if (item.url) return item.url;\n if (!item.file || !item.file.type.startsWith('image/')) return undefined;\n let url = previews.get(item.id);\n if (!url) previews.set(item.id, (url = URL.createObjectURL(item.file)));\n return url;\n };\n watch(\n () => value,\n (list) => {\n const kept = new Set(list.map((item) => item.id));\n for (const [id, url] of previews)\n if (!kept.has(id)) {\n URL.revokeObjectURL(url);\n previews.delete(id);\n }\n },\n );\n onBeforeUnmount(() => previews.forEach((url) => URL.revokeObjectURL(url)));\n\n let wall = _state.raw<HTMLElement | null>(null);\n const sortableWall = useSortable<UploadFile>({\n items: () => value,\n getKey: (item) => item.id,\n getLabel: (item) => item.name,\n onChange: (next) => (value = next),\n container: () => wall,\n orientation: () => 'horizontal',\n disabled: () => !sortable || control().readonly || control().disabled,\n });\n\n /** 粘贴:剪贴板里的文件(截图是 image/png)按 accept 分开,不符合的照常列出、带错误 */\n function onPaste(event: ClipboardEvent) {\n const state = control();\n if (!pasteable || state.disabled || state.readonly) return;\n const files = [...(event.clipboardData?.files ?? [])];\n if (files.length === 0) return;\n event.preventDefault();\n const accepted = files.filter((file) => matchesAccept(file, accept));\n const rejected = files.filter((file) => !matchesAccept(file, accept));\n if (accepted.length) add(accepted);\n if (rejected.length) add(rejected, true);\n }\n\n // 隐藏的 file input 带着全部可提交的文件:原生提交、FormData 拿得到\n _effect(() => {\n if (!hidden || typeof DataTransfer === 'undefined') return;\n const transfer = new DataTransfer();\n for (const item of value) if (item.file && !item.rejected) transfer.items.add(item.file);\n hidden.files = transfer.files;\n });\n\n function renderItem(item: UploadFile) {\n const state = control();\n const own = typeof propsItem === 'function' ? propsItem(item) : propsItem;\n const fileName = item.name;\n const failed = item.status === 'error';\n return (\n <li\n key={item.id}\n {...mergeAttrs<'li'>({ sx: [itemStyles.row, uploadStyles.item] }, own)}\n data-state={item.status}\n >\n <Icon\n {...mergePartProps<IconProps>(\n {\n icon: failed ? CircleAlert : item.status === 'done' ? CircleCheck : FileIcon,\n sx: [\n uploadStyles.icon,\n failed && uploadStyles.error,\n item.status === 'done' && uploadStyles.done,\n ],\n },\n propsIcon,\n )}\n />\n <div {...mergeAttrs<'div'>({ sx: uploadStyles.body }, propsBody)}>\n <span {...mergeAttrs<'span'>({ sx: uploadStyles.name }, propsName)}>\n {item.url ? (\n <Link href={item.url} target=\"_blank\">\n {fileName}\n </Link>\n ) : (\n fileName\n )}\n </span>\n {item.status === 'uploading' ? (\n <Progress\n {...mergePartProps<ProgressProps>(\n { size: 'xs', sx: uploadStyles.progress },\n propsProgress,\n {\n value: item.progress == null ? null : Math.round(item.progress * 100),\n 'aria-label': fileName,\n },\n )}\n />\n ) : (\n <span\n {...mergeAttrs<'span'>(\n { sx: [uploadStyles.meta, failed && uploadStyles.error] },\n propsMeta,\n )}\n >\n {failed ? item.error : item.size != null && format.fileSize(item.size)}\n {item.status === 'done' && <VisuallyHidden> {lang.uploadDone}</VisuallyHidden>}\n </span>\n )}\n </div>\n {failed && uploader() && !item.rejected && !state.readonly && (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: RotateCw,\n variant: 'ghost',\n size: 'sm',\n // 名称带文件名、每项不同:类型里不让使用方覆盖(同一个值会让各项的按钮同名)\n 'aria-label': lang.uploadRetry(fileName),\n },\n propsRetry,\n { onClick: () => void start(item) },\n )}\n />\n )}\n {!state.readonly && (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: X,\n variant: 'ghost',\n size: 'sm',\n 'aria-label': lang.uploadRemove(fileName),\n },\n propsRemove,\n { disabled: state.disabled, onClick: () => remove(item.id) },\n )}\n />\n )}\n </li>\n );\n }\n\n /** 图片墙的一格:缩略图(点开看大图)、上传进度或错误、把手、重试与移除 */\n function renderCard(item: UploadFile) {\n const state = control();\n const failed = item.status === 'error';\n const src = previewOf(item);\n return (\n <div\n key={item.id}\n {...mergeAttrs<'div'>(\n {\n sx: [\n uploadStyles.card,\n uploadDynamicStyles.square(thumbnailSize),\n failed && uploadStyles.cardError,\n ],\n },\n sortableWall.itemProps(item.id),\n { role: 'listitem' },\n )}\n data-state={item.status}\n >\n {src && !item.rejected ? (\n <Image\n src={src}\n alt={item.name}\n width={thumbnailSize - 2}\n height={thumbnailSize - 2}\n radius=\"none\"\n preview={{ caption: item.name, download: item.name }}\n />\n ) : (\n <div {...css.attrs(uploadStyles.placeholder)}>\n <Icon icon={failed ? CircleAlert : FileIcon} sx={failed && uploadStyles.error} />\n {item.name}\n </div>\n )}\n {item.status === 'uploading' && (\n <div {...css.attrs(uploadStyles.overlay)}>\n <Progress\n {...mergePartProps<ProgressProps>({ size: 'xs' }, propsProgress, {\n value: item.progress == null ? null : Math.round(item.progress * 100),\n 'aria-label': item.name,\n })}\n />\n </div>\n )}\n {failed && src && !item.rejected && (\n <div {...css.attrs(uploadStyles.overlay)} title={item.error}>\n {item.error}\n </div>\n )}\n {item.status === 'done' && <VisuallyHidden>{lang.uploadDone}</VisuallyHidden>}\n {!state.readonly && (\n <div {...css.attrs(uploadStyles.actions)}>\n {sortable && (\n <ButtonBase\n sx={uploadStyles.handle}\n ripple={false}\n disabled={state.disabled}\n aria-label={lang.sortableHandle(item.name)}\n {...sortableWall.handleProps(item.id)}\n >\n <Icon icon={GripVertical} />\n </ButtonBase>\n )}\n {failed && uploader() && !item.rejected && (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: RotateCw,\n variant: 'ghost',\n size: 'xs',\n sx: uploadStyles.action,\n 'aria-label': lang.uploadRetry(item.name),\n },\n propsRetry,\n { onClick: () => void start(item) },\n )}\n />\n )}\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: X,\n variant: 'ghost',\n size: 'xs',\n sx: uploadStyles.action,\n 'aria-label': lang.uploadRemove(item.name),\n },\n propsRemove,\n { disabled: state.disabled, onClick: () => remove(item.id) },\n )}\n />\n </div>\n )}\n </div>\n );\n }\n\n /** 选文件的区域:列表模式在上方,图片墙模式是最后一格 */\n function renderDrop(picture: boolean) {\n const state = control();\n const full = maxFiles != null && multiple && value.length >= maxFiles;\n if (state.readonly || (picture && full)) return null;\n const hint = pasteable ? lang.uploadPasteHint : undefined;\n const props = mergePartProps<FileDropProps>(\n {\n accept,\n multiple,\n disabled: state.disabled,\n invalid: state.invalid,\n // 选好的文件不在这个输入框里(它选完就清空):已有文件时不再原生必填,免得表单交不了\n required: state.required && value.length === 0,\n description: picture\n ? undefined\n : hint\n ? [description, description != null && ' · ', hint]\n : description,\n propsRoot: picture\n ? { sx: [uploadStyles.addCard, uploadDynamicStyles.square(thumbnailSize)] }\n : undefined,\n },\n propsDrop,\n {\n onFiles: (files: File[]) => add(files),\n onReject: (files: File[]) => add(files, true),\n },\n );\n // 列表模式不传子元素:FileDrop 用默认的图标、提示与说明(写了 undefined 也算传了,会把默认内容换掉)\n if (!picture) return <FileDrop {...props} />;\n return (\n <FileDrop {...props}>\n <Icon icon={ImagePlus} />\n {lang.uploadAddImage}\n </FileDrop>\n );\n }\n\n return () => {\n const state = control();\n if (listType === 'picture')\n return (\n <div {...mergeAttrs<'div'>({ sx: uploadStyles.root }, rest, { onPaste })}>\n <ImageGroup sx={uploadStyles.wall}>\n {/* 列表里只有缩略图(“添加图片”与预览不是列表项);display: contents,缩略图仍和“添加图片”排在一行 */}\n <div\n ref={_toRef(wall)}\n role=\"list\"\n // 状态变化(失败、完成)由读屏播报\n aria-live=\"polite\"\n {...css.attrs(uploadStyles.wallList)}\n >\n {value.map(renderCard)}\n </div>\n {renderDrop(true)}\n </ImageGroup>\n {pasteable && !state.readonly && (\n <span {...css.attrs(uploadStyles.meta)}>\n {[description, description != null && ' · ', lang.uploadPasteHint]}\n </span>\n )}\n {sortable && (\n <>\n <VisuallyHidden id={sortableWall.instructionsId}>\n {lang.sortableInstructions}\n </VisuallyHidden>\n <VisuallyHidden aria-live=\"assertive\">{sortableWall.announcement}</VisuallyHidden>\n </>\n )}\n {name != null && (\n <input\n ref={_toRef(hidden)}\n type=\"file\"\n name={name}\n multiple\n hidden\n tabindex={-1}\n aria-hidden=\"true\"\n />\n )}\n </div>\n );\n return (\n <div {...mergeAttrs<'div'>({ sx: uploadStyles.root }, rest, { onPaste })}>\n {renderDrop(false)}\n {name != null && (\n <input\n ref={_toRef(hidden)}\n type=\"file\"\n name={name}\n multiple\n hidden\n tabindex={-1}\n aria-hidden=\"true\"\n />\n )}\n {value.length > 0 && (\n // 状态变化(失败、完成)由读屏播报\n <GridList\n {...mergePartProps<GridProps<'ul'>>({ gap: 'xs' }, propsList)}\n aria-live=\"polite\"\n >\n {value.map(renderItem)}\n </GridList>\n )}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { t } from "../config/theme/tokens.js";
2
2
  import { mergeAttrs } from "../utils/props.js";
3
3
  import { useIntersectionObserver } from "../utils/dom/intersection.js";
4
- import { Fragment, createVNode, mergeProps, ref, shallowRef } from "vue";
5
- import { _component, childrenProp, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
4
+ import { Fragment, createVNode, ref, shallowRef } from "vue";
5
+ import { _component, childrenProp, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
6
6
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
7
7
  //#region src/layout/Affix.tsx
8
8
  /** onChange 换成报告是否贴住 */
@@ -51,13 +51,13 @@ var Affix = /*#__PURE__*/ _component((_props, _ctx) => {
51
51
  }));
52
52
  return () => {
53
53
  const bottom = atBottom();
54
- const marker = createVNode("div", mergeProps({
54
+ const marker = createVNode("div", mergeJsxProps({
55
55
  "aria-hidden": "true",
56
56
  "ref": _cache[0] || (_cache[0] = (element) => sentinel.value = element instanceof HTMLElement ? element : null)
57
57
  }, css.attrs(affixStyles.sentinel)), null);
58
58
  return createVNode(Fragment, null, [
59
59
  !bottom && marker,
60
- createVNode("div", mergeProps(mergeAttrs({ sx: [
60
+ createVNode("div", mergeJsxProps(mergeAttrs({ sx: [
61
61
  affixStyles.root,
62
62
  bottom ? css.bind(affixPositionStyles.bottom, () => [offsetBottom.value ?? 0], true) : css.bind(affixPositionStyles.top, () => [offsetTop.value ?? 0], true),
63
63
  shadow.value && stuck.value && affixStyles.stuck
@@ -1 +1 @@
1
- {"version":3,"file":"Affix.js","names":["_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_vue_shallowRef","_vue_ref","_createVNode","_mergeProps","_Fragment"],"sources":["../../src/layout/Affix.tsx"],"sourcesContent":["/**\n * 固钉:滚动到某个位置后贴住视口(或滚动容器)的顶部、底部不走,如表单的提交栏、长表格上方的筛选条、文章的目录。\n *\n * <Affix offsetTop={64}>\n * <FilterBar … />\n * </Affix>\n * <Affix offsetBottom={0} onChange={(stuck) => …}><ActionBar … /></Affix>\n *\n * 用 CSS position: sticky:在所在的滚动容器里贴住,不脱离文档流(不用占位、不用量宽度),容器滚出去时跟着走。\n * 是否已经贴住由 IntersectionObserver 看一个零高度的哨兵(useIntersectionObserver):贴住时加阴影(浮在内容上)、\n * 写 data-stuck,并报告 onChange。sticky 只在父元素的范围里生效:Affix 要放在跟着滚动的那一层里;\n * 祖先里有 overflow 不是 visible 的元素时,sticky 相对的是它(不是视口):这时把它作为 target 传进来。\n * 部件:Root(div,sticky 的那层)。\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 { useIntersectionObserver } from '../utils/dom/intersection';\nimport { mergeAttrs, type PartProps } from '../utils/props';\nimport { t } from '../config/theme/tokens';\n\n/** onChange 换成报告是否贴住 */\nexport type AffixManaged = 'onChange';\n\n/** 未声明的属性落到 sticky 的 div 上 */\nexport interface AffixProps extends PartProps<'div', AffixManaged> {\n /** 贴住时离顶部多远(px),默认 0;与 offsetBottom 二选一 */\n offsetTop?: number;\n /** 贴住时离底部多远(px):贴在底部 */\n offsetBottom?: number;\n /** 滚动的容器(sticky 相对的那个祖先);不写时是视口 */\n target?: () => HTMLElement | null | undefined;\n /** 贴住时加阴影,默认 true */\n shadow?: boolean;\n /** 贴住、离开时调用 */\n onChange?: (stuck: boolean) => void;\n children?: VNodeChild;\n}\n\n/** Affix 的样式:root、stuck、sentinel */\nexport const affixStyles = css.create({\n root: {\n position: 'sticky',\n zIndex: 5,\n transition: `box-shadow ${t.durations.sm} ${t.easings.standard}`,\n },\n stuck: { boxShadow: '_md' },\n // 哨兵:贴住的位置上一个零高度的元素,滚过它就是贴住了\n sentinel: { height: 0, pointerEvents: 'none', visibility: 'hidden' },\n});\n\n/** 贴住的位置 */\nexport const affixPositionStyles = css.create({\n top: (offset: number) => ({ top: offset }),\n bottom: (offset: number) => ({ bottom: offset }),\n});\n\n/** 固钉:sticky + 是否贴住的检测 */\nexport const Affix = _component(\n ({ offsetTop, offsetBottom, target, shadow = true, onChange, children, ...rest }: AffixProps) => {\n let sentinel = _state.raw<HTMLElement | null>(null);\n let stuck = _state(false);\n const atBottom = () => offsetBottom != null && offsetTop == null;\n\n // 贴顶:哨兵在上方,滚到它离顶部不到 offsetTop 就是贴住了;贴底:哨兵在下方,同理看底部\n useIntersectionObserver(\n () => sentinel,\n ([entry]) => {\n const next =\n !entry!.isIntersecting &&\n (atBottom()\n ? entry!.boundingClientRect.top > (entry!.rootBounds?.bottom ?? 0)\n : entry!.boundingClientRect.bottom < (entry!.rootBounds?.top ?? 0));\n if (next === stuck) return;\n stuck = next;\n onChange?.(next);\n },\n () => ({\n root: target?.() ?? null,\n rootMargin: atBottom()\n ? `0px 0px ${-(offsetBottom ?? 0)}px 0px`\n : `${-(offsetTop ?? 0)}px 0px 0px 0px`,\n threshold: [0, 1],\n }),\n );\n\n return () => {\n const bottom = atBottom();\n const marker = (\n <div\n aria-hidden=\"true\"\n ref={(element: unknown) => (sentinel = element instanceof HTMLElement ? element : null)}\n {...css.attrs(affixStyles.sentinel)}\n />\n );\n return (\n <>\n {!bottom && marker}\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n affixStyles.root,\n bottom\n ? affixPositionStyles.bottom(offsetBottom ?? 0)\n : affixPositionStyles.top(offsetTop ?? 0),\n shadow && stuck && affixStyles.stuck,\n ],\n },\n rest,\n )}\n data-stuck={stuck || undefined}\n >\n {children}\n </div>\n {bottom && marker}\n </>\n );\n };\n },\n);\n"],"mappings":";;;;;;;;;;AAwCA,IAAa,cAAc,IAAI,OAAO;CACpC,MAAM;EACJ,UAAU;EACV,QAAQ;EACR,YAAY,cAAc,EAAE,UAAU,GAAE,GAAI,EAAE,QAAQ;CACxD;CACA,OAAO,EAAE,WAAW,MAAM;CAE1B,UAAU;EAAE,QAAQ;EAAG,eAAe;EAAQ,YAAY;CAAS;AACrE,CAAC;;AAGD,IAAa,sBAAsB,IAAI,OAAO;CAC5C,MAAM,YAAoB,EAAE,KAAK,OAAO;CACxC,SAAS,YAAoB,EAAE,QAAQ,OAAO;AAChD,CAAC;;AAGD,IAAa,QAAQ,0BACnB,QAAA,SAAiG;CAAA,MAAA,SAAA,CAAA;CAAA,MAAA,YAAAA,aAAA,QAAA,WAAA;CAAA,MAAA,eAAAA,aAAA,QAAA,cAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,UAApD,IAAI;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,WAAAC,aAAA,MAAA;CAAA,MAAyB,OAAIC,UAAA,QAAA,MAAA,KAAA;CAC5E,IAAI,WAAQC,WAAkC,IAAI;CAClD,IAAI,QAAKC,IAAU,KAAK;CACxB,MAAM,iBAAiB,aAAA,SAAgB,QAAQ,UAAA,SAAa;CAG5D,8BACE,SAAA,QACC,CAAC,WAAW;EACX,MAAM,OACJ,CAAC,MAAO,mBACP,SAAS,IACN,MAAO,mBAAmB,OAAO,MAAO,YAAY,UAAU,KAC9D,MAAO,mBAAmB,UAAU,MAAO,YAAY,OAAO;EACpE,IAAI,SAAI,MAAA,OAAY;EACpB,MAAA,QAAQ;EACR,SAAA,QAAW,IAAI;CACjB,UACO;EACL,MAAM,OAAA,QAAS,KAAK;EACpB,YAAY,SAAS,IACjB,WAAW,EAAE,aAAA,SAAgB,GAAE,UAC/B,GAAG,EAAE,UAAA,SAAa,GAAE;EACxB,WAAW,CAAC,GAAG,CAAC;CAClB,EACF;CAEA,aAAa;EACX,MAAM,SAAS,SAAS;EACxB,MAAM,SAAMC,YAAA,OAAAC,WAAA;GAAA,eAAA;GAAA,OAAA,OAAA,OAAA,OAAA,MAGF,YAAsB,SAAA,QAAW,mBAAmB,cAAc,UAAU;EAAK,GACnF,IAAI,MAAM,YAAY,QAAQ,CAAC,GAAA,IAAA;EAGvC,OAAAD,YAAAE,UAAA,MAAA;GAEK,CAAC,UAAU;GAAMF,YAAA,OAAAC,WAEZ,WACF,EACE,IAAI;IACF,YAAY;IACZ,SAAM,IAAA,KACF,oBAAoB,cAAM,CAAC,aAAA,SAAgB,CAAC,GAAA,IAAA,IAAA,IAAA,KAC5C,oBAAoB,WAAG,CAAC,UAAA,SAAa,CAAC,GAAA,IAAA;IAC1C,OAAA,SAAA,MAAA,SAAmB,YAAY;GAAK,EAExC,GACA,IACF,GAAC,EAAA,cACW,MAAA,SAAS,KAAA,EAAS,CAAA,GAAA,CAAA,SAAA,KAAA,CAAA;GAI/B,UAAU;EAAM,CAAA;CAGvB;AACF,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
1
+ {"version":3,"file":"Affix.js","names":["_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_vue_shallowRef","_vue_ref","_createVNode","_mergeProps","_Fragment"],"sources":["../../src/layout/Affix.tsx"],"sourcesContent":["/**\n * 固钉:滚动到某个位置后贴住视口(或滚动容器)的顶部、底部不走,如表单的提交栏、长表格上方的筛选条、文章的目录。\n *\n * <Affix offsetTop={64}>\n * <FilterBar … />\n * </Affix>\n * <Affix offsetBottom={0} onChange={(stuck) => …}><ActionBar … /></Affix>\n *\n * 用 CSS position: sticky:在所在的滚动容器里贴住,不脱离文档流(不用占位、不用量宽度),容器滚出去时跟着走。\n * 是否已经贴住由 IntersectionObserver 看一个零高度的哨兵(useIntersectionObserver):贴住时加阴影(浮在内容上)、\n * 写 data-stuck,并报告 onChange。sticky 只在父元素的范围里生效:Affix 要放在跟着滚动的那一层里;\n * 祖先里有 overflow 不是 visible 的元素时,sticky 相对的是它(不是视口):这时把它作为 target 传进来。\n * 部件:Root(div,sticky 的那层)。\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 { useIntersectionObserver } from '../utils/dom/intersection';\nimport { mergeAttrs, type PartProps } from '../utils/props';\nimport { t } from '../config/theme/tokens';\n\n/** onChange 换成报告是否贴住 */\nexport type AffixManaged = 'onChange';\n\n/** 未声明的属性落到 sticky 的 div 上 */\nexport interface AffixProps extends PartProps<'div', AffixManaged> {\n /** 贴住时离顶部多远(px),默认 0;与 offsetBottom 二选一 */\n offsetTop?: number;\n /** 贴住时离底部多远(px):贴在底部 */\n offsetBottom?: number;\n /** 滚动的容器(sticky 相对的那个祖先);不写时是视口 */\n target?: () => HTMLElement | null | undefined;\n /** 贴住时加阴影,默认 true */\n shadow?: boolean;\n /** 贴住、离开时调用 */\n onChange?: (stuck: boolean) => void;\n children?: VNodeChild;\n}\n\n/** Affix 的样式:root、stuck、sentinel */\nexport const affixStyles = css.create({\n root: {\n position: 'sticky',\n zIndex: 5,\n transition: `box-shadow ${t.durations.sm} ${t.easings.standard}`,\n },\n stuck: { boxShadow: '_md' },\n // 哨兵:贴住的位置上一个零高度的元素,滚过它就是贴住了\n sentinel: { height: 0, pointerEvents: 'none', visibility: 'hidden' },\n});\n\n/** 贴住的位置 */\nexport const affixPositionStyles = css.create({\n top: (offset: number) => ({ top: offset }),\n bottom: (offset: number) => ({ bottom: offset }),\n});\n\n/** 固钉:sticky + 是否贴住的检测 */\nexport const Affix = _component(\n ({ offsetTop, offsetBottom, target, shadow = true, onChange, children, ...rest }: AffixProps) => {\n let sentinel = _state.raw<HTMLElement | null>(null);\n let stuck = _state(false);\n const atBottom = () => offsetBottom != null && offsetTop == null;\n\n // 贴顶:哨兵在上方,滚到它离顶部不到 offsetTop 就是贴住了;贴底:哨兵在下方,同理看底部\n useIntersectionObserver(\n () => sentinel,\n ([entry]) => {\n const next =\n !entry!.isIntersecting &&\n (atBottom()\n ? entry!.boundingClientRect.top > (entry!.rootBounds?.bottom ?? 0)\n : entry!.boundingClientRect.bottom < (entry!.rootBounds?.top ?? 0));\n if (next === stuck) return;\n stuck = next;\n onChange?.(next);\n },\n () => ({\n root: target?.() ?? null,\n rootMargin: atBottom()\n ? `0px 0px ${-(offsetBottom ?? 0)}px 0px`\n : `${-(offsetTop ?? 0)}px 0px 0px 0px`,\n threshold: [0, 1],\n }),\n );\n\n return () => {\n const bottom = atBottom();\n const marker = (\n <div\n aria-hidden=\"true\"\n ref={(element: unknown) => (sentinel = element instanceof HTMLElement ? element : null)}\n {...css.attrs(affixStyles.sentinel)}\n />\n );\n return (\n <>\n {!bottom && marker}\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n affixStyles.root,\n bottom\n ? affixPositionStyles.bottom(offsetBottom ?? 0)\n : affixPositionStyles.top(offsetTop ?? 0),\n shadow && stuck && affixStyles.stuck,\n ],\n },\n rest,\n )}\n data-stuck={stuck || undefined}\n >\n {children}\n </div>\n {bottom && marker}\n </>\n );\n };\n },\n);\n"],"mappings":";;;;;;;;;;AAwCA,IAAa,cAAc,IAAI,OAAO;CACpC,MAAM;EACJ,UAAU;EACV,QAAQ;EACR,YAAY,cAAc,EAAE,UAAU,GAAE,GAAI,EAAE,QAAQ;CACxD;CACA,OAAO,EAAE,WAAW,MAAM;CAE1B,UAAU;EAAE,QAAQ;EAAG,eAAe;EAAQ,YAAY;CAAS;AACrE,CAAC;;AAGD,IAAa,sBAAsB,IAAI,OAAO;CAC5C,MAAM,YAAoB,EAAE,KAAK,OAAO;CACxC,SAAS,YAAoB,EAAE,QAAQ,OAAO;AAChD,CAAC;;AAGD,IAAa,QAAQ,0BACnB,QAAA,SAAiG;CAAA,MAAA,SAAA,CAAA;CAAA,MAAA,YAAAA,aAAA,QAAA,WAAA;CAAA,MAAA,eAAAA,aAAA,QAAA,cAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,UAApD,IAAI;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,WAAAC,aAAA,MAAA;CAAA,MAAyB,OAAIC,UAAA,QAAA,MAAA,KAAA;CAC5E,IAAI,WAAQC,WAAkC,IAAI;CAClD,IAAI,QAAKC,IAAU,KAAK;CACxB,MAAM,iBAAiB,aAAA,SAAgB,QAAQ,UAAA,SAAa;CAG5D,8BACE,SAAA,QACC,CAAC,WAAW;EACX,MAAM,OACJ,CAAC,MAAO,mBACP,SAAS,IACN,MAAO,mBAAmB,OAAO,MAAO,YAAY,UAAU,KAC9D,MAAO,mBAAmB,UAAU,MAAO,YAAY,OAAO;EACpE,IAAI,SAAI,MAAA,OAAY;EACpB,MAAA,QAAQ;EACR,SAAA,QAAW,IAAI;CACjB,UACO;EACL,MAAM,OAAA,QAAS,KAAK;EACpB,YAAY,SAAS,IACjB,WAAW,EAAE,aAAA,SAAgB,GAAE,UAC/B,GAAG,EAAE,UAAA,SAAa,GAAE;EACxB,WAAW,CAAC,GAAG,CAAC;CAClB,EACF;CAEA,aAAa;EACX,MAAM,SAAS,SAAS;EACxB,MAAM,SAAMC,YAAA,OAAAC,cAAA;GAAA,eAAA;GAAA,OAAA,OAAA,OAAA,OAAA,MAGF,YAAsB,SAAA,QAAW,mBAAmB,cAAc,UAAU;EAAK,GACnF,IAAI,MAAM,YAAY,QAAQ,CAAC,GAAA,IAAA;EAGvC,OAAAD,YAAAE,UAAA,MAAA;GAEK,CAAC,UAAU;GAAMF,YAAA,OAAAC,cAEZ,WACF,EACE,IAAI;IACF,YAAY;IACZ,SAAM,IAAA,KACF,oBAAoB,cAAM,CAAC,aAAA,SAAgB,CAAC,GAAA,IAAA,IAAA,IAAA,KAC5C,oBAAoB,WAAG,CAAC,UAAA,SAAa,CAAC,GAAA,IAAA;IAC1C,OAAA,SAAA,MAAA,SAAmB,YAAY;GAAK,EAExC,GACA,IACF,GAAC,EAAA,cACW,MAAA,SAAS,KAAA,EAAS,CAAA,GAAA,CAAA,SAAA,KAAA,CAAA;GAI/B,UAAU;EAAM,CAAA;CAGvB;AACF,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
@@ -14,15 +14,19 @@ export interface ResizeHandleProps extends PartProps<'span', ResizeHandleManaged
14
14
  defaultWidth?: number;
15
15
  /** 键盘每按一次调整多少(px),默认 16 */
16
16
  step?: number;
17
- /** 手柄在父元素的哪一边,默认 end;start 时往起始方向拖是变宽(从结束边滑入的抽屉) */
17
+ /** 手柄在父元素的哪一边,默认 end;start 时往起始方向拖是变宽(从结束边滑入的抽屉);horizontal 时 start 是上边、end 是下边 */
18
18
  edge?: 'start' | 'end';
19
+ /** vertical(默认):竖线,调整宽度;horizontal:横线,调整高度(见文件开头) */
20
+ orientation?: 'vertical' | 'horizontal';
19
21
  /** 拖动或用键盘调整了宽度(已经夹在最小、最大宽度之间) */
20
22
  onWidthChange: (width: number) => void;
21
23
  }
22
24
  /** ResizeHandle 的样式:贴着父元素结束边的细线 */
23
25
  export declare const resizeHandleStyles: Readonly<{
24
26
  handle: css.CompiledStyles;
27
+ horizontal: css.CompiledStyles;
28
+ horizontalStart: css.CompiledStyles;
25
29
  start: css.CompiledStyles;
26
30
  }>;
27
- /** 宽度调整手柄:拖动或用 ← / → 调整父元素的宽度 */
31
+ /** 宽度调整手柄:拖动或用 ← / → 调整父元素的宽度;orientation="horizontal" 时调整高度(↑ / ↓) */
28
32
  export declare const ResizeHandle: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<ResizeHandleProps>;
@@ -29,9 +29,22 @@ var resizeHandleStyles = css.create({
29
29
  start: {
30
30
  insetInlineEnd: "auto",
31
31
  insetInlineStart: 0
32
+ },
33
+ horizontal: {
34
+ top: "auto",
35
+ bottom: 0,
36
+ insetInlineStart: 0,
37
+ insetInlineEnd: 0,
38
+ width: "auto",
39
+ height: "_space.sm",
40
+ cursor: "row-resize"
41
+ },
42
+ horizontalStart: {
43
+ top: 0,
44
+ bottom: "auto"
32
45
  }
33
46
  });
34
- /** 宽度调整手柄:拖动或用 ← / → 调整父元素的宽度 */
47
+ /** 宽度调整手柄:拖动或用 ← / → 调整父元素的宽度;orientation="horizontal" 时调整高度(↑ / ↓) */
35
48
  var ResizeHandle = /*#__PURE__*/ _component((_props, _ctx) => {
36
49
  const width = readonlyProp(_props, "width");
37
50
  const minWidth = readonlyProp(_props, "minWidth", 64);
@@ -39,36 +52,45 @@ var ResizeHandle = /*#__PURE__*/ _component((_props, _ctx) => {
39
52
  const defaultWidth = readonlyProp(_props, "defaultWidth");
40
53
  const step = readonlyProp(_props, "step", 16);
41
54
  const edge = readonlyProp(_props, "edge", "end");
55
+ const orientation = readonlyProp(_props, "orientation", "vertical");
42
56
  const onWidthChange = readonlyProp(_props, "onWidthChange");
43
57
  const rest = restProps(_props, _ctx, true);
58
+ const horizontal = () => orientation.value === "horizontal";
44
59
  const parentOf = (event) => event.currentTarget.parentElement;
60
+ const sizeOf = (element) => {
61
+ const rect = element.getBoundingClientRect();
62
+ return horizontal() ? rect.height : rect.width;
63
+ };
45
64
  const fit = (px) => Math.round(clamp(px, minWidth.value, maxWidth.value));
46
65
  let handle = shallowRef(null);
47
66
  let measured = ref(void 0);
48
67
  useResizeObserver(() => width.value == null ? handle.value?.parentElement : null, () => {
49
68
  const parent = handle.value?.parentElement;
50
- if (parent) measured.value = Math.round(parent.getBoundingClientRect().width);
69
+ if (parent) measured.value = Math.round(sizeOf(parent));
51
70
  });
52
71
  function onPointerdown(event) {
53
72
  const parent = parentOf(event);
54
- const from = parent.getBoundingClientRect().width;
55
- const sign = (isRtl(parent) ? -1 : 1) * (edge.value === "start" ? -1 : 1);
73
+ const from = sizeOf(parent);
74
+ const sign = (horizontal() ? 1 : isRtl(parent) ? -1 : 1) * (edge.value === "start" ? -1 : 1);
56
75
  event.preventDefault();
57
- startMove(event, { onMove: ({ deltaX }) => onWidthChange.value(fit(from + sign * deltaX)) });
76
+ startMove(event, { onMove: ({ deltaX, deltaY }) => onWidthChange.value(fit(from + sign * (horizontal() ? deltaY : deltaX))) });
58
77
  }
59
78
  function onKeydown(event) {
60
79
  const parent = parentOf(event);
61
- const { forward, backward } = inlineArrows(isRtl(parent));
80
+ const { forward, backward } = horizontal() ? {
81
+ forward: "ArrowDown",
82
+ backward: "ArrowUp"
83
+ } : inlineArrows(isRtl(parent));
62
84
  const delta = (event.key === forward ? step.value : event.key === backward ? -step.value : 0) * (edge.value === "start" ? -1 : 1);
63
85
  if (!delta) return;
64
86
  event.preventDefault();
65
- onWidthChange.value(fit((width.value ?? parent.getBoundingClientRect().width) + delta));
87
+ onWidthChange.value(fit((width.value ?? sizeOf(parent)) + delta));
66
88
  }
67
- return () => createVNode("span", mergeAttrs({ sx: [resizeHandleStyles.handle, edge.value === "start" && resizeHandleStyles.start] }, rest, {
89
+ return () => createVNode("span", mergeAttrs({ sx: [resizeHandleStyles.handle, horizontal() ? [resizeHandleStyles.horizontal, edge.value === "start" && resizeHandleStyles.horizontalStart] : edge.value === "start" && resizeHandleStyles.start] }, rest, {
68
90
  ref: (element) => handle.value = element instanceof HTMLElement ? element : null,
69
91
  role: "separator",
70
92
  tabindex: 0,
71
- "aria-orientation": "vertical",
93
+ "aria-orientation": orientation.value,
72
94
  "aria-valuenow": width.value ?? measured.value ?? minWidth.value,
73
95
  "aria-valuemin": minWidth.value,
74
96
  "aria-valuemax": Number.isFinite(maxWidth.value) ? maxWidth.value : void 0,
@@ -85,6 +107,7 @@ var ResizeHandle = /*#__PURE__*/ _component((_props, _ctx) => {
85
107
  "defaultWidth",
86
108
  "step",
87
109
  "edge",
110
+ "orientation",
88
111
  "onWidthChange"
89
112
  ]
90
113
  });
@@ -1 +1 @@
1
- {"version":3,"file":"ResizeHandle.js","names":["_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_vue_ref","_createVNode"],"sources":["../../src/layout/ResizeHandle.tsx"],"sourcesContent":["/**\n * 宽度调整手柄:所在元素结束边(edge=\"start\" 时是起始边,如从右侧滑入的抽屉)的一条细线(role=\"separator\"),悬停、聚焦时显示。\n * 拖动(startMove)或聚焦后用 ← / →(WCAG 2.5.7 拖动的替代操作)调整,从右到左排版下方向自动镜像;\n * 双击回到 defaultWidth。宽度从父元素量起,所以要放在要调整的那个元素里(它需要 position: relative 或 fixed)。\n * AppShell 的抽屉式侧栏、DataTable 的列宽(ColumnResizer)都用它。\n *\n * <aside style=\"position: relative; width: …\">…<ResizeHandle aria-label=\"调整侧栏宽度\" width={width} onWidthChange={(px) => (width = px)} /></aside>\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { clamp } from '../utils/data/number';\nimport { inlineArrows, isRtl } from '../utils/dom/direction';\nimport { startMove } from '../utils/dom/move';\nimport { useResizeObserver } from '../utils/dom/resize';\nimport { mergeAttrs, type PartProps } from '../utils/props';\n\n/** 分隔条的角色、可聚焦与取值由组件管理 */\nexport type ResizeHandleManaged =\n 'role' | 'tabindex' | 'aria-orientation' | 'aria-valuenow' | 'aria-valuemin' | 'aria-valuemax';\n\n/** 未声明的属性落到手柄(span)上;无障碍名称写 aria-label */\nexport interface ResizeHandleProps extends PartProps<'span', ResizeHandleManaged> {\n /** 当前宽度(px);没有时从父元素的实际宽度起算 */\n width?: number;\n /** 最小宽度(px),默认 64 */\n minWidth?: number;\n /** 最大宽度(px),默认不限 */\n maxWidth?: number;\n /** 双击回到的宽度(px);不写时双击不做什么 */\n defaultWidth?: number;\n /** 键盘每按一次调整多少(px),默认 16 */\n step?: number;\n /** 手柄在父元素的哪一边,默认 end;start 时往起始方向拖是变宽(从结束边滑入的抽屉) */\n edge?: 'start' | 'end';\n /** 拖动或用键盘调整了宽度(已经夹在最小、最大宽度之间) */\n onWidthChange: (width: number) => void;\n}\n\n/** ResizeHandle 的样式:贴着父元素结束边的细线 */\nexport const resizeHandleStyles = css.create({\n handle: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n insetInlineEnd: 0,\n width: '_space.sm',\n cursor: 'col-resize',\n touchAction: 'none',\n backgroundColor: {\n default: 'transparent',\n ':hover': '_borderStrong',\n ':focus-visible': '_accent',\n },\n outlineStyle: 'none',\n },\n start: { insetInlineEnd: 'auto', insetInlineStart: 0 },\n});\n\n/** 宽度调整手柄:拖动或用 ← / → 调整父元素的宽度 */\nexport const ResizeHandle = _component(\n ({\n width,\n minWidth = 64,\n maxWidth = Number.POSITIVE_INFINITY,\n defaultWidth,\n step = 16,\n edge = 'end',\n onWidthChange,\n ...rest\n }: ResizeHandleProps) => {\n const parentOf = (event: Event) => (event.currentTarget as HTMLElement).parentElement!;\n const fit = (px: number) => Math.round(clamp(px, minWidth, maxWidth));\n // 没给 width 时量父元素的实际宽度:可聚焦的分隔条必须有当前值(aria-valuenow)\n let handle = _state.raw<HTMLElement | null>(null);\n let measured = _state<number | undefined>(undefined);\n useResizeObserver(\n () => (width == null ? handle?.parentElement : null),\n () => {\n const parent = handle?.parentElement;\n if (parent) measured = Math.round(parent.getBoundingClientRect().width);\n },\n );\n\n function onPointerdown(event: PointerEvent) {\n const parent = parentOf(event);\n const from = parent.getBoundingClientRect().width;\n // 起始边的手柄往起始方向拖是变宽:方向与结束边相反\n const sign = (isRtl(parent) ? -1 : 1) * (edge === 'start' ? -1 : 1);\n event.preventDefault();\n startMove(event, {\n onMove: ({ deltaX }) => onWidthChange(fit(from + sign * deltaX)),\n });\n }\n\n function onKeydown(event: KeyboardEvent) {\n const parent = parentOf(event);\n const { forward, backward } = inlineArrows(isRtl(parent));\n const delta =\n (event.key === forward ? step : event.key === backward ? -step : 0) *\n (edge === 'start' ? -1 : 1);\n if (!delta) return;\n event.preventDefault();\n onWidthChange(fit((width ?? parent.getBoundingClientRect().width) + delta));\n }\n\n return () => (\n <span\n {...mergeAttrs<'span'>(\n { sx: [resizeHandleStyles.handle, edge === 'start' && resizeHandleStyles.start] },\n rest,\n {\n ref: (element: unknown) => (handle = element instanceof HTMLElement ? element : null),\n role: 'separator',\n tabindex: 0,\n 'aria-orientation': 'vertical',\n 'aria-valuenow': width ?? measured ?? minWidth,\n 'aria-valuemin': minWidth,\n 'aria-valuemax': Number.isFinite(maxWidth) ? maxWidth : undefined,\n onPointerdown,\n onKeydown,\n onDblclick: defaultWidth == null ? undefined : () => onWidthChange(fit(defaultWidth)),\n },\n )}\n />\n );\n },\n);\n"],"mappings":";;;;;;;;;;;;AAuCA,IAAa,qBAAqB,IAAI,OAAO;CAC3C,QAAQ;EACN,UAAU;EACV,KAAK;EACL,QAAQ;EACR,gBAAgB;EAChB,OAAO;EACP,QAAQ;EACR,aAAa;EACb,iBAAiB;GACf,SAAS;GACT,UAAU;GACV,kBAAkB;EACpB;EACA,cAAc;CAChB;CACA,OAAO;EAAE,gBAAgB;EAAQ,kBAAkB;CAAE;AACvD,CAAC;;AAGD,IAAa,eAAe,0BAC1B,QAAA,SASyB;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,YAPZ,EAAE;CAAA,MAAA,WAAAA,aAAA,QAAA,kBACF,OAAO,iBAAiB;CAAA,MAAA,eAAAA,aAAA,QAAA,cAAA;CAAA,MAAA,OAAAA,aAAA,QAAA,QAE5B,EAAE;CAAA,MAAA,OAAAA,aAAA,QAAA,QACF,KAAK;CAAA,MAAA,gBAAAA,aAAA,QAAA,eAAA;CAAA,MAET,OAAIC,UAAA,QAAA,MAAA,IAAA;CAEP,MAAM,YAAY,UAAkB,MAAM,cAA8B;CACxE,MAAM,OAAO,OAAe,KAAK,MAAM,MAAM,IAAE,SAAA,OAAA,SAAA,KAAoB,CAAC;CAEpE,IAAI,SAAMC,WAAkC,IAAI;CAChD,IAAI,WAAQC,IAA8B,KAAA,CAAS;CACnD,wBACS,MAAA,SAAS,OAAO,OAAA,OAAQ,gBAAgB,YACzC;EACJ,MAAM,SAAS,OAAA,OAAQ;EACvB,IAAI,QAAQ,SAAA,QAAW,KAAK,MAAM,OAAO,sBAAsB,CAAC,CAAC,KAAK;CACxE,CACF;CAEA,SAAS,cAAc,OAAqB;EAC1C,MAAM,SAAS,SAAS,KAAK;EAC7B,MAAM,OAAO,OAAO,sBAAsB,CAAC,CAAC;EAE5C,MAAM,QAAQ,MAAM,MAAM,IAAI,KAAK,MAAM,KAAA,UAAS,UAAU,KAAK;EACjE,MAAM,eAAe;EACrB,UAAU,OAAO,EACf,SAAS,EAAE,aAAa,cAAA,MAAc,IAAI,OAAO,OAAO,MAAM,CAAC,EACjE,CAAC;CACH;CAEA,SAAS,UAAU,OAAsB;EACvC,MAAM,SAAS,SAAS,KAAK;EAC7B,MAAM,EAAE,SAAS,aAAa,aAAa,MAAM,MAAM,CAAC;EACxD,MAAM,SACH,MAAM,QAAQ,UAAO,KAAA,QAAU,MAAM,QAAQ,WAAW,CAAA,KAAA,QAAQ,MAChE,KAAA,UAAS,UAAU,KAAK;EAC3B,IAAI,CAAC,OAAO;EACZ,MAAM,eAAe;EACrB,cAAA,MAAc,KAAK,MAAA,SAAS,OAAO,sBAAsB,CAAC,CAAC,SAAS,KAAK,CAAC;CAC5E;CAEA,aAAOC,YAAA,QAEC,WACF,EAAE,IAAI,CAAC,mBAAmB,QAAQ,KAAA,UAAS,WAAW,mBAAmB,KAAK,EAAE,GAChF,MACA;EACE,MAAM,YAAsB,OAAA,QAAS,mBAAmB,cAAc,UAAU;EAChF,MAAM;EACN,UAAU;EACV,oBAAoB;EACpB,iBAAiB,MAAA,SAAA,SAAA,SAAiB,SAAA;EAClC,iBAAe,SAAA;EACf,iBAAiB,OAAO,SAAQ,SAAA,KAAS,IAAC,SAAA,QAAc,KAAA;EACxD;EACA;EACA,YAAY,aAAA,SAAgB,OAAO,KAAA,UAAkB,cAAA,MAAc,IAAG,aAAA,KAAa,CAAC;CACtF,CACF,GAAC,IAAA;AAGP,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
1
+ {"version":3,"file":"ResizeHandle.js","names":["_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_vue_ref","_createVNode"],"sources":["../../src/layout/ResizeHandle.tsx"],"sourcesContent":["/**\n * 宽度调整手柄:所在元素结束边(edge=\"start\" 时是起始边,如从右侧滑入的抽屉)的一条细线(role=\"separator\"),悬停、聚焦时显示。\n * 拖动(startMove)或聚焦后用 ← / →(WCAG 2.5.7 拖动的替代操作)调整,从右到左排版下方向自动镜像;\n * 双击回到 defaultWidth。宽度从父元素量起,所以要放在要调整的那个元素里(它需要 position: relative 或 fixed)。\n * orientation=\"horizontal\" 时是一条横线,贴着父元素的下边(edge=\"start\" 时是上边,如从底部升起的抽屉),\n * 拖动或用 ↑ / ↓ 调整的是**高度**:width、minWidth、maxWidth、defaultWidth、onWidthChange 这时都指高度。\n * AppShell 的抽屉式侧栏、DataTable 的列宽(ColumnResizer)都用它。\n *\n * <aside style=\"position: relative; width: …\">…<ResizeHandle aria-label=\"调整侧栏宽度\" width={width} onWidthChange={(px) => (width = px)} /></aside>\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { clamp } from '../utils/data/number';\nimport { inlineArrows, isRtl } from '../utils/dom/direction';\nimport { startMove } from '../utils/dom/move';\nimport { useResizeObserver } from '../utils/dom/resize';\nimport { mergeAttrs, type PartProps } from '../utils/props';\n\n/** 分隔条的角色、可聚焦与取值由组件管理 */\nexport type ResizeHandleManaged =\n 'role' | 'tabindex' | 'aria-orientation' | 'aria-valuenow' | 'aria-valuemin' | 'aria-valuemax';\n\n/** 未声明的属性落到手柄(span)上;无障碍名称写 aria-label */\nexport interface ResizeHandleProps extends PartProps<'span', ResizeHandleManaged> {\n /** 当前宽度(px);没有时从父元素的实际宽度起算 */\n width?: number;\n /** 最小宽度(px),默认 64 */\n minWidth?: number;\n /** 最大宽度(px),默认不限 */\n maxWidth?: number;\n /** 双击回到的宽度(px);不写时双击不做什么 */\n defaultWidth?: number;\n /** 键盘每按一次调整多少(px),默认 16 */\n step?: number;\n /** 手柄在父元素的哪一边,默认 end;start 时往起始方向拖是变宽(从结束边滑入的抽屉);horizontal 时 start 是上边、end 是下边 */\n edge?: 'start' | 'end';\n /** vertical(默认):竖线,调整宽度;horizontal:横线,调整高度(见文件开头) */\n orientation?: 'vertical' | 'horizontal';\n /** 拖动或用键盘调整了宽度(已经夹在最小、最大宽度之间) */\n onWidthChange: (width: number) => void;\n}\n\n/** ResizeHandle 的样式:贴着父元素结束边的细线 */\nexport const resizeHandleStyles = css.create({\n handle: {\n position: 'absolute',\n top: 0,\n bottom: 0,\n insetInlineEnd: 0,\n width: '_space.sm',\n cursor: 'col-resize',\n touchAction: 'none',\n backgroundColor: {\n default: 'transparent',\n ':hover': '_borderStrong',\n ':focus-visible': '_accent',\n },\n outlineStyle: 'none',\n },\n start: { insetInlineEnd: 'auto', insetInlineStart: 0 },\n // 横线:贴着父元素的下边(start 时是上边),调整高度\n horizontal: {\n top: 'auto',\n bottom: 0,\n insetInlineStart: 0,\n insetInlineEnd: 0,\n width: 'auto',\n height: '_space.sm',\n cursor: 'row-resize',\n },\n horizontalStart: { top: 0, bottom: 'auto' },\n});\n\n/** 宽度调整手柄:拖动或用 ← / → 调整父元素的宽度;orientation=\"horizontal\" 时调整高度(↑ / ↓) */\nexport const ResizeHandle = _component(\n ({\n width,\n minWidth = 64,\n maxWidth = Number.POSITIVE_INFINITY,\n defaultWidth,\n step = 16,\n edge = 'end',\n orientation = 'vertical',\n onWidthChange,\n ...rest\n }: ResizeHandleProps) => {\n const horizontal = () => orientation === 'horizontal';\n const parentOf = (event: Event) => (event.currentTarget as HTMLElement).parentElement!;\n const sizeOf = (element: Element) => {\n const rect = element.getBoundingClientRect();\n return horizontal() ? rect.height : rect.width;\n };\n const fit = (px: number) => Math.round(clamp(px, minWidth, maxWidth));\n // 没给 width 时量父元素的实际宽度:可聚焦的分隔条必须有当前值(aria-valuenow)\n let handle = _state.raw<HTMLElement | null>(null);\n let measured = _state<number | undefined>(undefined);\n useResizeObserver(\n () => (width == null ? handle?.parentElement : null),\n () => {\n const parent = handle?.parentElement;\n if (parent) measured = Math.round(sizeOf(parent));\n },\n );\n\n function onPointerdown(event: PointerEvent) {\n const parent = parentOf(event);\n const from = sizeOf(parent);\n // 起始边的手柄往起始方向拖是变宽:方向与结束边相反;横线不受从右到左排版的影响\n const sign = (horizontal() ? 1 : isRtl(parent) ? -1 : 1) * (edge === 'start' ? -1 : 1);\n event.preventDefault();\n startMove(event, {\n onMove: ({ deltaX, deltaY }) =>\n onWidthChange(fit(from + sign * (horizontal() ? deltaY : deltaX))),\n });\n }\n\n function onKeydown(event: KeyboardEvent) {\n const parent = parentOf(event);\n const { forward, backward } = horizontal()\n ? { forward: 'ArrowDown', backward: 'ArrowUp' }\n : inlineArrows(isRtl(parent));\n const delta =\n (event.key === forward ? step : event.key === backward ? -step : 0) *\n (edge === 'start' ? -1 : 1);\n if (!delta) return;\n event.preventDefault();\n onWidthChange(fit((width ?? sizeOf(parent)) + delta));\n }\n\n return () => (\n <span\n {...mergeAttrs<'span'>(\n {\n sx: [\n resizeHandleStyles.handle,\n horizontal()\n ? [\n resizeHandleStyles.horizontal,\n edge === 'start' && resizeHandleStyles.horizontalStart,\n ]\n : edge === 'start' && resizeHandleStyles.start,\n ],\n },\n rest,\n {\n ref: (element: unknown) => (handle = element instanceof HTMLElement ? element : null),\n role: 'separator',\n tabindex: 0,\n 'aria-orientation': orientation,\n 'aria-valuenow': width ?? measured ?? minWidth,\n 'aria-valuemin': minWidth,\n 'aria-valuemax': Number.isFinite(maxWidth) ? maxWidth : undefined,\n onPointerdown,\n onKeydown,\n onDblclick: defaultWidth == null ? undefined : () => onWidthChange(fit(defaultWidth)),\n },\n )}\n />\n );\n },\n);\n"],"mappings":"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"}
@@ -5,8 +5,8 @@ import { startMove } from "../utils/dom/move.js";
5
5
  import { isRtl } from "../utils/dom/direction.js";
6
6
  import { batchLayout } from "../utils/dom/layout-batch.js";
7
7
  import { useResizeObserver } from "../utils/dom/resize.js";
8
- import { createVNode, mergeProps, ref, shallowRef } from "vue";
9
- import { _component, childrenProp, effect, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
8
+ import { createVNode, ref, shallowRef } from "vue";
9
+ import { _component, childrenProp, 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/layout/ScrollArea.tsx
12
12
  /** 哪个方向可以滚动 */
@@ -241,7 +241,7 @@ var OverlayScrollbar = /*#__PURE__*/ _component((_props, _ctx) => {
241
241
  }
242
242
  return () => {
243
243
  const visible = overflowing.value && (type.value === "always" || active.value);
244
- return createVNode("div", mergeProps(mergeAttrs({ sx: [
244
+ return createVNode("div", mergeJsxProps(mergeAttrs({ sx: [
245
245
  scrollAreaBarStyles.track,
246
246
  scrollAreaBarStyles[axis.value],
247
247
  fixed.value && scrollAreaBarStyles.fixed,
@@ -1 +1 @@
1
- {"version":3,"file":"ScrollArea.js","names":["_vtp_readonlyProp","_vue_shallowRef","_vue_ref","_createVNode","_mergeProps","_vtp_childrenProp","_vtp_restProps"],"sources":["../../src/layout/ScrollArea.tsx"],"sourcesContent":["/**\n * 滚动区域:浮层滚动条。滚动仍是浏览器原生的(触控板惯性、键盘、页内搜索、无障碍都不变),\n * 只把原生滚动条隐藏,换成半透明、绝对定位浮在内容上方的滚动条:出现、消失都不占位,不改变布局尺寸。\n * 参考 Radix ScrollArea。\n *\n * <ScrollArea sx={styles.panel}>…</ScrollArea> 高度(或最大高度)由使用方给\n * <ScrollArea axis=\"both\" type=\"always\">…</ScrollArea>\n *\n * 滚动条对读屏隐藏(滚动由视口本身承担);内容超出时视口可聚焦,键盘照常滚动。\n * 滚动条本身是 OverlayScrollbar:整页的浮层滚动条(PageScrollbar)也用它。\n *\n * 要在外面拿到真正滚动的元素(虚拟滚动、自己控制滚动)时用 propsViewport 的 ref:\n * <ScrollArea propsViewport={{ ref: (element) => (scroller = toElement(element)) }}>…</ScrollArea>\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 { startMove } from '../utils/dom/move';\nimport { mergeAttrs, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { isRtl } from '../utils/dom/direction';\nimport { batchLayout } from '../utils/dom/layout-batch';\nimport { useResizeObserver } from '../utils/dom/resize';\nimport { t } from '../config/theme/tokens';\n\n/** 哪个方向可以滚动 */\nexport interface ScrollAreaAxes {\n /** 纵向(默认),横向超出的部分裁掉 */\n y: unknown;\n /** 横向,纵向超出的部分裁掉 */\n x: unknown;\n /** 两个方向 */\n both: unknown;\n}\n\n/** 滚动条什么时候显示 */\nexport interface ScrollbarTypes {\n /** 指针在区域上方或正在滚动时显示(默认) */\n hover: unknown;\n /** 只在滚动时显示,停下后淡出 */\n scroll: unknown;\n /** 内容超出时一直显示 */\n always: unknown;\n}\n\n/** 未声明的属性落到外层(决定尺寸的那一层);视口的属性(aria-label 等)用 propsViewport */\nexport interface ScrollAreaProps extends PartProps<'div'> {\n /** 可以滚动的方向,默认 y */\n axis?: keyof ScrollAreaAxes;\n /** 滚动条什么时候显示,默认 hover */\n type?: keyof ScrollbarTypes;\n /** 停止滚动、指针离开后多久淡出(毫秒),默认 600 */\n hideDelay?: number;\n /**\n * 内容超出时视口可以用 Tab 聚焦(键盘滚动),默认 true。视口本身另有角色并自己管焦点(列表框、菜单),\n * 或焦点在别处、由那里控制滚动(命令面板的输入框)时关掉,tabindex 由使用方经 propsViewport 给\n */\n focusable?: boolean;\n /** 视口(真正滚动的元素)的部件属性;ref 拿到它可以自己控制滚动 */\n propsViewport?: PartProps<'div'>;\n /** 内容层(视口里包着 children 的 div)的部件属性 */\n propsContent?: PartProps<'div'>;\n /** 滚动条轨道的部件属性,两个方向都用它(data-axis 区分 x、y) */\n propsScrollbar?: PartProps<'div', 'aria-hidden'>;\n /** 滑块的部件属性;大小与位置由组件写在行内样式上 */\n propsThumb?: PartProps<'div'>;\n children?: VNodeChild;\n}\n\n/** 滑块的最小长度(px):内容再长也能抓得住 */\nconst MIN_THUMB = 20;\n\n/** ScrollArea 的样式:root、viewport、y、x、both、wideContent */\nexport const scrollAreaStyles = css.create({\n // flex 纵向:使用方只给 max-height 时视口也能被限制住(视口 min-height: 0 可以收缩)\n root: { position: 'relative', display: 'flex', flexDirection: 'column', overflow: 'hidden' },\n viewport: {\n flexGrow: 1,\n minHeight: 0,\n // 隐藏原生滚动条:Firefox、新版 Chromium 与 Safari 用标准属性,旧版 WebKit 用伪元素\n scrollbarWidth: 'none',\n '::-webkit-scrollbar': { display: 'none' },\n // 焦点环画在里面:外层 overflow: hidden 会裁掉画在外面的\n outlineOffset: `calc(-1 * ${t.borderWidths.sm})`,\n },\n y: { overflowX: 'hidden', overflowY: 'auto' },\n x: { overflowX: 'auto', overflowY: 'hidden' },\n both: { overflow: 'auto' },\n // 横向滚动时内容按自己的宽度撑开,宽度变化也能被 ResizeObserver 观察到\n wideContent: { display: 'table', minWidth: '_full' },\n});\n\n/** OverlayScrollbar 的样式:track、hidden、y、x、yCorner、xCorner、thumb 等 */\nexport const scrollAreaBarStyles = css.create({\n track: {\n position: 'absolute',\n zIndex: 1,\n boxSizing: 'border-box',\n touchAction: 'none',\n userSelect: 'none',\n transition: `opacity ${t.durations.md} ${t.easings.standard}`,\n },\n hidden: { opacity: 0, pointerEvents: 'none' },\n // 整页的滚动条:隐藏时仍接收指针,指针移到窗口边缘就显示出来\n hiddenReveal: { opacity: 0 },\n // 整页的滚动条固定在视口一侧,盖在粘性顶栏之上\n fixed: { position: 'fixed', zIndex: 20 },\n // 粗细:0.5em 的滑块加两侧各 2px 的留白\n y: {\n insetBlock: 0,\n insetInlineEnd: 0,\n width: `calc(${t.space.sm} + 2 * ${t.borderWidths.sm})`,\n },\n x: {\n insetInline: 0,\n bottom: 0,\n height: `calc(${t.space.sm} + 2 * ${t.borderWidths.sm})`,\n },\n // 两个方向都有时让出右下角,两条滚动条不重叠\n yCorner: { bottom: `calc(${t.space.sm} + 2 * ${t.borderWidths.sm})` },\n xCorner: { insetInlineEnd: `calc(${t.space.sm} + 2 * ${t.borderWidths.sm})` },\n thumb: {\n position: 'absolute',\n borderRadius: '_full',\n // 半透明:浮在内容上也不完全遮住下面的文字\n backgroundColor: {\n default: `color-mix(in srgb, ${t.colors.textMuted} 50%, transparent)`,\n ':hover': `color-mix(in srgb, ${t.colors.textMuted} 75%, transparent)`,\n },\n transition: `background-color ${t.durations.sm} ${t.easings.standard}`,\n },\n thumbY: { top: 0, insetInline: '_borderWidths.sm' },\n thumbX: { insetInlineStart: 0, insetBlock: '_borderWidths.sm' },\n});\n\n/** OverlayScrollbar 的属性 */\nexport interface OverlayScrollbarProps {\n /** 方向 */\n axis: 'x' | 'y';\n /** 真正滚动的元素;整页滚动时是 document.scrollingElement(滚动事件在 window 上) */\n viewport: HTMLElement | null;\n /** 内容:它的尺寸变化时重新计算滑块 */\n content: HTMLElement | null;\n /** 指针进入它时显示滚动条(type 为 hover 时);不给时只看指针是否在滚动条上 */\n hoverTarget?: HTMLElement | null;\n /** 什么时候显示,默认 hover */\n type?: keyof ScrollbarTypes;\n /** 停止滚动、指针离开后多久淡出(毫秒),默认 600 */\n hideDelay?: number;\n /** 两个方向都有滚动条:让出右下角 */\n corner?: boolean;\n /** 固定在视口一侧(整页的滚动条):隐藏时仍接收指针,移到窗口边缘就显示 */\n fixed?: boolean;\n /** 轨道的部件属性 */\n propsScrollbar?: PartProps<'div', 'aria-hidden'>;\n /** 滑块的部件属性 */\n propsThumb?: PartProps<'div'>;\n /** 内容是否超出视口(这个方向能不能滚动)变化时调用 */\n onOverflowChange?: (overflowing: boolean) => void;\n}\n\n/**\n * 一个方向的浮层滚动条:轨道与滑块,滚动、悬停时出现,停下后淡出;拖动滑块、点击轨道翻页、滚轮转交给视口。\n * ScrollArea 与 PageScrollbar 都用它。单独一个组件,滚动、悬停只让它自己重新渲染,不牵动内容\n */\nexport const OverlayScrollbar = _component(\n ({\n axis,\n viewport,\n content,\n hoverTarget,\n type = 'hover',\n hideDelay = 600,\n corner = false,\n fixed = false,\n propsScrollbar,\n propsThumb,\n onOverflowChange,\n }: OverlayScrollbarProps) => {\n let track = _state.raw<HTMLElement | null>(null);\n let thumb = _state.raw<HTMLElement | null>(null);\n let overflowing = _state(false);\n let active = _state(false);\n let hovering = false;\n let dragging = false;\n let hideTimer: ReturnType<typeof setTimeout> | undefined;\n\n /** 视口的尺寸与滚动位置;横向时滚动位置取绝对值(从右到左排版时 scrollLeft 为负) */\n const measure = (element: HTMLElement) =>\n axis === 'y'\n ? { view: element.clientHeight, size: element.scrollHeight, position: element.scrollTop }\n : {\n view: element.clientWidth,\n size: element.scrollWidth,\n position: Math.abs(element.scrollLeft),\n };\n /** 从右到左排版时横向的方向要反过来 */\n const sign = () => (axis === 'x' && viewport && isRtl(viewport) ? -1 : 1);\n const thumbSize = (view: number, size: number, trackSize: number) =>\n Math.max(MIN_THUMB, (view / size) * trackSize);\n\n // 滑块的大小与位置随滚动频繁变化,直接写到元素上,不经过渲染。read 量、返回的函数写\n function read() {\n if (!viewport || !track || !thumb) return;\n // 看不见的(收起的 Collapse 是 hidden=\"until-found\",即 content-visibility: hidden)不量:\n // 在这种子树里读尺寸,浏览器每次都要为它单独排一遍版。显示出来时 ResizeObserver 会再通知\n if (viewport.checkVisibility?.() === false) return;\n const element = thumb;\n const { view, size, position } = measure(viewport);\n const trackSize = axis === 'y' ? track.clientHeight : track.clientWidth;\n const length = thumbSize(view, size, trackSize);\n const offset = size > view ? (position / (size - view)) * (trackSize - length) : 0;\n const direction = sign();\n return () => {\n const next = size > view + 1;\n if (next !== overflowing) {\n overflowing = next;\n onOverflowChange?.(next);\n }\n if (axis === 'y') {\n element.style.height = `${length}px`;\n element.style.transform = `translateY(${offset}px)`;\n } else {\n element.style.width = `${length}px`;\n element.style.transform = `translateX(${direction * offset}px)`;\n }\n };\n }\n // 滚动时立即对齐;挂载、尺寸变化时合并到这一轮的先读后写里(一页十几个滚动区域只排一次版)\n const sync = () => read()?.();\n const syncLater = () => batchLayout(read);\n\n // 整页的滚动条(fixed)不论 type,指针移到它上面都显示\n const revealsOnHover = () => type === 'hover' || fixed;\n\n function show() {\n active = true;\n scheduleHide();\n }\n function scheduleHide() {\n clearTimeout(hideTimer);\n hideTimer = setTimeout(() => {\n if (!dragging && !(revealsOnHover() && hovering)) active = false;\n }, hideDelay);\n }\n\n _effect(() => {\n if (!viewport || !content) return;\n const element = viewport;\n // 整页滚动时滚动事件发在 window 上;窗口高度变了(不改变内容尺寸)也要重算\n const scroller = element === document.scrollingElement ? window : element;\n const hover = hoverTarget ?? track;\n syncLater();\n const onScroll = () => {\n sync();\n show();\n };\n const onEnter = () => {\n hovering = true;\n if (!revealsOnHover()) return;\n // 绝对定位的后代(图表的提示框)撑出、收回溢出时内容尺寸不变,ResizeObserver 察觉不到,显示前重新量\n sync();\n show();\n };\n const onLeave = () => {\n hovering = false;\n scheduleHide();\n };\n scroller.addEventListener('scroll', onScroll, { passive: true });\n if (scroller === window) window.addEventListener('resize', sync);\n hover?.addEventListener('pointerenter', onEnter);\n hover?.addEventListener('pointerleave', onLeave);\n return () => {\n scroller.removeEventListener('scroll', onScroll);\n window.removeEventListener('resize', sync);\n hover?.removeEventListener('pointerenter', onEnter);\n hover?.removeEventListener('pointerleave', onLeave);\n clearTimeout(hideTimer);\n };\n });\n useResizeObserver(() => [viewport, content], syncLater);\n\n /** 拖动滑块:位移按“可滚动距离 / 滑块可移动距离”换算成滚动距离 */\n function dragThumb(event: PointerEvent) {\n if (!viewport || !track || !thumb) return;\n event.stopPropagation();\n const element = viewport;\n const { view, size, position } = measure(element);\n const trackSize = axis === 'y' ? track.clientHeight : track.clientWidth;\n const ratio = (size - view) / (trackSize - thumbSize(view, size, trackSize));\n const direction = sign();\n dragging = true;\n startMove(event, {\n onMove: ({ deltaX, deltaY }) => {\n const target = position + (axis === 'y' ? deltaY : direction * deltaX) * ratio;\n if (axis === 'y') element.scrollTop = target;\n else element.scrollLeft = direction * target;\n },\n onEnd: () => {\n dragging = false;\n scheduleHide();\n },\n });\n }\n\n /** 点击轨道的空白处:朝那一侧翻一页 */\n function pageTo(event: PointerEvent) {\n if (!viewport || !thumb || event.button !== 0) return;\n const rect = thumb.getBoundingClientRect();\n const { view } = measure(viewport);\n // 点在滑块之前(上方;横向时为起始一侧)就往回翻\n const rtl = sign() === -1;\n const before =\n axis === 'y'\n ? event.clientY < rect.top\n : rtl\n ? event.clientX > rect.right\n : event.clientX < rect.left;\n const page = (before ? -1 : 1) * view * 0.9;\n viewport.scrollBy(axis === 'y' ? { top: page } : { left: sign() * page });\n }\n\n /** 滚动条盖在视口上面,滚轮落在它上面时转交给视口 */\n function forwardWheel(event: WheelEvent) {\n if (!viewport) return;\n event.preventDefault();\n viewport.scrollBy({ left: event.deltaX, top: event.deltaY });\n }\n\n return () => {\n const visible = overflowing && (type === 'always' || active);\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n scrollAreaBarStyles.track,\n scrollAreaBarStyles[axis],\n fixed && scrollAreaBarStyles.fixed,\n corner &&\n (axis === 'y' ? scrollAreaBarStyles.yCorner : scrollAreaBarStyles.xCorner),\n ],\n },\n propsScrollbar,\n {\n sx:\n !visible && (fixed ? scrollAreaBarStyles.hiddenReveal : scrollAreaBarStyles.hidden),\n ref: _toRef(track),\n 'aria-hidden': true,\n onPointerdown: pageTo,\n onWheel: forwardWheel,\n },\n )}\n data-axis={axis}\n data-state={visible ? 'visible' : 'hidden'}\n >\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n scrollAreaBarStyles.thumb,\n axis === 'y' ? scrollAreaBarStyles.thumbY : scrollAreaBarStyles.thumbX,\n ],\n },\n propsThumb,\n { ref: _toRef(thumb), onPointerdown: dragThumb },\n )}\n />\n </div>\n );\n };\n },\n { name: 'OverlayScrollbar' },\n);\n\n/** 滚动区域:原生滚动 + 半透明的浮层滚动条,出现与消失都不占位 */\nexport const ScrollArea = _component(\n ({\n axis = 'y',\n type = 'hover',\n hideDelay = 600,\n focusable = true,\n propsViewport,\n propsContent,\n propsScrollbar,\n propsThumb,\n children,\n ...rest\n }: ScrollAreaProps) => {\n let root = _state.raw<HTMLElement | null>(null);\n let viewport = _state.raw<HTMLElement | null>(null);\n let content = _state.raw<HTMLElement | null>(null);\n // 哪个方向的内容超出了视口:能滚动时视口才进 Tab 顺序,没超出的侧栏、代码块不多一个空的 Tab 位\n let overflowing = _state({ x: false, y: false });\n\n return () => {\n const both = axis === 'both';\n const bar = (barAxis: 'x' | 'y') => (\n <OverlayScrollbar\n axis={barAxis}\n hoverTarget={root}\n viewport={viewport}\n content={content}\n type={type}\n hideDelay={hideDelay}\n corner={both}\n propsScrollbar={propsScrollbar}\n propsThumb={propsThumb}\n onOverflowChange={(value) => (overflowing = { ...overflowing, [barAxis]: value })}\n />\n );\n return (\n <div {...mergeAttrs<'div'>({ sx: scrollAreaStyles.root }, rest, { ref: _toRef(root) })}>\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [focusRingStyles.visible, scrollAreaStyles.viewport, scrollAreaStyles[axis]],\n },\n propsViewport,\n {\n ref: _toRef(viewport),\n ...(focusable && (overflowing.x || overflowing.y) && { tabindex: 0 }),\n },\n )}\n >\n <div\n {...mergeAttrs<'div'>(\n { sx: axis !== 'y' && scrollAreaStyles.wideContent },\n propsContent,\n {\n ref: _toRef(content),\n },\n )}\n >\n {children}\n </div>\n </div>\n {axis !== 'x' && bar('y')}\n {axis !== 'y' && bar('x')}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"ScrollArea.js","names":["_vtp_readonlyProp","_vue_shallowRef","_vue_ref","_createVNode","_mergeProps","_vtp_childrenProp","_vtp_restProps"],"sources":["../../src/layout/ScrollArea.tsx"],"sourcesContent":["/**\n * 滚动区域:浮层滚动条。滚动仍是浏览器原生的(触控板惯性、键盘、页内搜索、无障碍都不变),\n * 只把原生滚动条隐藏,换成半透明、绝对定位浮在内容上方的滚动条:出现、消失都不占位,不改变布局尺寸。\n * 参考 Radix ScrollArea。\n *\n * <ScrollArea sx={styles.panel}>…</ScrollArea> 高度(或最大高度)由使用方给\n * <ScrollArea axis=\"both\" type=\"always\">…</ScrollArea>\n *\n * 滚动条对读屏隐藏(滚动由视口本身承担);内容超出时视口可聚焦,键盘照常滚动。\n * 滚动条本身是 OverlayScrollbar:整页的浮层滚动条(PageScrollbar)也用它。\n *\n * 要在外面拿到真正滚动的元素(虚拟滚动、自己控制滚动)时用 propsViewport 的 ref:\n * <ScrollArea propsViewport={{ ref: (element) => (scroller = toElement(element)) }}>…</ScrollArea>\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 { startMove } from '../utils/dom/move';\nimport { mergeAttrs, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { isRtl } from '../utils/dom/direction';\nimport { batchLayout } from '../utils/dom/layout-batch';\nimport { useResizeObserver } from '../utils/dom/resize';\nimport { t } from '../config/theme/tokens';\n\n/** 哪个方向可以滚动 */\nexport interface ScrollAreaAxes {\n /** 纵向(默认),横向超出的部分裁掉 */\n y: unknown;\n /** 横向,纵向超出的部分裁掉 */\n x: unknown;\n /** 两个方向 */\n both: unknown;\n}\n\n/** 滚动条什么时候显示 */\nexport interface ScrollbarTypes {\n /** 指针在区域上方或正在滚动时显示(默认) */\n hover: unknown;\n /** 只在滚动时显示,停下后淡出 */\n scroll: unknown;\n /** 内容超出时一直显示 */\n always: unknown;\n}\n\n/** 未声明的属性落到外层(决定尺寸的那一层);视口的属性(aria-label 等)用 propsViewport */\nexport interface ScrollAreaProps extends PartProps<'div'> {\n /** 可以滚动的方向,默认 y */\n axis?: keyof ScrollAreaAxes;\n /** 滚动条什么时候显示,默认 hover */\n type?: keyof ScrollbarTypes;\n /** 停止滚动、指针离开后多久淡出(毫秒),默认 600 */\n hideDelay?: number;\n /**\n * 内容超出时视口可以用 Tab 聚焦(键盘滚动),默认 true。视口本身另有角色并自己管焦点(列表框、菜单),\n * 或焦点在别处、由那里控制滚动(命令面板的输入框)时关掉,tabindex 由使用方经 propsViewport 给\n */\n focusable?: boolean;\n /** 视口(真正滚动的元素)的部件属性;ref 拿到它可以自己控制滚动 */\n propsViewport?: PartProps<'div'>;\n /** 内容层(视口里包着 children 的 div)的部件属性 */\n propsContent?: PartProps<'div'>;\n /** 滚动条轨道的部件属性,两个方向都用它(data-axis 区分 x、y) */\n propsScrollbar?: PartProps<'div', 'aria-hidden'>;\n /** 滑块的部件属性;大小与位置由组件写在行内样式上 */\n propsThumb?: PartProps<'div'>;\n children?: VNodeChild;\n}\n\n/** 滑块的最小长度(px):内容再长也能抓得住 */\nconst MIN_THUMB = 20;\n\n/** ScrollArea 的样式:root、viewport、y、x、both、wideContent */\nexport const scrollAreaStyles = css.create({\n // flex 纵向:使用方只给 max-height 时视口也能被限制住(视口 min-height: 0 可以收缩)\n root: { position: 'relative', display: 'flex', flexDirection: 'column', overflow: 'hidden' },\n viewport: {\n flexGrow: 1,\n minHeight: 0,\n // 隐藏原生滚动条:Firefox、新版 Chromium 与 Safari 用标准属性,旧版 WebKit 用伪元素\n scrollbarWidth: 'none',\n '::-webkit-scrollbar': { display: 'none' },\n // 焦点环画在里面:外层 overflow: hidden 会裁掉画在外面的\n outlineOffset: `calc(-1 * ${t.borderWidths.sm})`,\n },\n y: { overflowX: 'hidden', overflowY: 'auto' },\n x: { overflowX: 'auto', overflowY: 'hidden' },\n both: { overflow: 'auto' },\n // 横向滚动时内容按自己的宽度撑开,宽度变化也能被 ResizeObserver 观察到\n wideContent: { display: 'table', minWidth: '_full' },\n});\n\n/** OverlayScrollbar 的样式:track、hidden、y、x、yCorner、xCorner、thumb 等 */\nexport const scrollAreaBarStyles = css.create({\n track: {\n position: 'absolute',\n zIndex: 1,\n boxSizing: 'border-box',\n touchAction: 'none',\n userSelect: 'none',\n transition: `opacity ${t.durations.md} ${t.easings.standard}`,\n },\n hidden: { opacity: 0, pointerEvents: 'none' },\n // 整页的滚动条:隐藏时仍接收指针,指针移到窗口边缘就显示出来\n hiddenReveal: { opacity: 0 },\n // 整页的滚动条固定在视口一侧,盖在粘性顶栏之上\n fixed: { position: 'fixed', zIndex: 20 },\n // 粗细:0.5em 的滑块加两侧各 2px 的留白\n y: {\n insetBlock: 0,\n insetInlineEnd: 0,\n width: `calc(${t.space.sm} + 2 * ${t.borderWidths.sm})`,\n },\n x: {\n insetInline: 0,\n bottom: 0,\n height: `calc(${t.space.sm} + 2 * ${t.borderWidths.sm})`,\n },\n // 两个方向都有时让出右下角,两条滚动条不重叠\n yCorner: { bottom: `calc(${t.space.sm} + 2 * ${t.borderWidths.sm})` },\n xCorner: { insetInlineEnd: `calc(${t.space.sm} + 2 * ${t.borderWidths.sm})` },\n thumb: {\n position: 'absolute',\n borderRadius: '_full',\n // 半透明:浮在内容上也不完全遮住下面的文字\n backgroundColor: {\n default: `color-mix(in srgb, ${t.colors.textMuted} 50%, transparent)`,\n ':hover': `color-mix(in srgb, ${t.colors.textMuted} 75%, transparent)`,\n },\n transition: `background-color ${t.durations.sm} ${t.easings.standard}`,\n },\n thumbY: { top: 0, insetInline: '_borderWidths.sm' },\n thumbX: { insetInlineStart: 0, insetBlock: '_borderWidths.sm' },\n});\n\n/** OverlayScrollbar 的属性 */\nexport interface OverlayScrollbarProps {\n /** 方向 */\n axis: 'x' | 'y';\n /** 真正滚动的元素;整页滚动时是 document.scrollingElement(滚动事件在 window 上) */\n viewport: HTMLElement | null;\n /** 内容:它的尺寸变化时重新计算滑块 */\n content: HTMLElement | null;\n /** 指针进入它时显示滚动条(type 为 hover 时);不给时只看指针是否在滚动条上 */\n hoverTarget?: HTMLElement | null;\n /** 什么时候显示,默认 hover */\n type?: keyof ScrollbarTypes;\n /** 停止滚动、指针离开后多久淡出(毫秒),默认 600 */\n hideDelay?: number;\n /** 两个方向都有滚动条:让出右下角 */\n corner?: boolean;\n /** 固定在视口一侧(整页的滚动条):隐藏时仍接收指针,移到窗口边缘就显示 */\n fixed?: boolean;\n /** 轨道的部件属性 */\n propsScrollbar?: PartProps<'div', 'aria-hidden'>;\n /** 滑块的部件属性 */\n propsThumb?: PartProps<'div'>;\n /** 内容是否超出视口(这个方向能不能滚动)变化时调用 */\n onOverflowChange?: (overflowing: boolean) => void;\n}\n\n/**\n * 一个方向的浮层滚动条:轨道与滑块,滚动、悬停时出现,停下后淡出;拖动滑块、点击轨道翻页、滚轮转交给视口。\n * ScrollArea 与 PageScrollbar 都用它。单独一个组件,滚动、悬停只让它自己重新渲染,不牵动内容\n */\nexport const OverlayScrollbar = _component(\n ({\n axis,\n viewport,\n content,\n hoverTarget,\n type = 'hover',\n hideDelay = 600,\n corner = false,\n fixed = false,\n propsScrollbar,\n propsThumb,\n onOverflowChange,\n }: OverlayScrollbarProps) => {\n let track = _state.raw<HTMLElement | null>(null);\n let thumb = _state.raw<HTMLElement | null>(null);\n let overflowing = _state(false);\n let active = _state(false);\n let hovering = false;\n let dragging = false;\n let hideTimer: ReturnType<typeof setTimeout> | undefined;\n\n /** 视口的尺寸与滚动位置;横向时滚动位置取绝对值(从右到左排版时 scrollLeft 为负) */\n const measure = (element: HTMLElement) =>\n axis === 'y'\n ? { view: element.clientHeight, size: element.scrollHeight, position: element.scrollTop }\n : {\n view: element.clientWidth,\n size: element.scrollWidth,\n position: Math.abs(element.scrollLeft),\n };\n /** 从右到左排版时横向的方向要反过来 */\n const sign = () => (axis === 'x' && viewport && isRtl(viewport) ? -1 : 1);\n const thumbSize = (view: number, size: number, trackSize: number) =>\n Math.max(MIN_THUMB, (view / size) * trackSize);\n\n // 滑块的大小与位置随滚动频繁变化,直接写到元素上,不经过渲染。read 量、返回的函数写\n function read() {\n if (!viewport || !track || !thumb) return;\n // 看不见的(收起的 Collapse 是 hidden=\"until-found\",即 content-visibility: hidden)不量:\n // 在这种子树里读尺寸,浏览器每次都要为它单独排一遍版。显示出来时 ResizeObserver 会再通知\n if (viewport.checkVisibility?.() === false) return;\n const element = thumb;\n const { view, size, position } = measure(viewport);\n const trackSize = axis === 'y' ? track.clientHeight : track.clientWidth;\n const length = thumbSize(view, size, trackSize);\n const offset = size > view ? (position / (size - view)) * (trackSize - length) : 0;\n const direction = sign();\n return () => {\n const next = size > view + 1;\n if (next !== overflowing) {\n overflowing = next;\n onOverflowChange?.(next);\n }\n if (axis === 'y') {\n element.style.height = `${length}px`;\n element.style.transform = `translateY(${offset}px)`;\n } else {\n element.style.width = `${length}px`;\n element.style.transform = `translateX(${direction * offset}px)`;\n }\n };\n }\n // 滚动时立即对齐;挂载、尺寸变化时合并到这一轮的先读后写里(一页十几个滚动区域只排一次版)\n const sync = () => read()?.();\n const syncLater = () => batchLayout(read);\n\n // 整页的滚动条(fixed)不论 type,指针移到它上面都显示\n const revealsOnHover = () => type === 'hover' || fixed;\n\n function show() {\n active = true;\n scheduleHide();\n }\n function scheduleHide() {\n clearTimeout(hideTimer);\n hideTimer = setTimeout(() => {\n if (!dragging && !(revealsOnHover() && hovering)) active = false;\n }, hideDelay);\n }\n\n _effect(() => {\n if (!viewport || !content) return;\n const element = viewport;\n // 整页滚动时滚动事件发在 window 上;窗口高度变了(不改变内容尺寸)也要重算\n const scroller = element === document.scrollingElement ? window : element;\n const hover = hoverTarget ?? track;\n syncLater();\n const onScroll = () => {\n sync();\n show();\n };\n const onEnter = () => {\n hovering = true;\n if (!revealsOnHover()) return;\n // 绝对定位的后代(图表的提示框)撑出、收回溢出时内容尺寸不变,ResizeObserver 察觉不到,显示前重新量\n sync();\n show();\n };\n const onLeave = () => {\n hovering = false;\n scheduleHide();\n };\n scroller.addEventListener('scroll', onScroll, { passive: true });\n if (scroller === window) window.addEventListener('resize', sync);\n hover?.addEventListener('pointerenter', onEnter);\n hover?.addEventListener('pointerleave', onLeave);\n return () => {\n scroller.removeEventListener('scroll', onScroll);\n window.removeEventListener('resize', sync);\n hover?.removeEventListener('pointerenter', onEnter);\n hover?.removeEventListener('pointerleave', onLeave);\n clearTimeout(hideTimer);\n };\n });\n useResizeObserver(() => [viewport, content], syncLater);\n\n /** 拖动滑块:位移按“可滚动距离 / 滑块可移动距离”换算成滚动距离 */\n function dragThumb(event: PointerEvent) {\n if (!viewport || !track || !thumb) return;\n event.stopPropagation();\n const element = viewport;\n const { view, size, position } = measure(element);\n const trackSize = axis === 'y' ? track.clientHeight : track.clientWidth;\n const ratio = (size - view) / (trackSize - thumbSize(view, size, trackSize));\n const direction = sign();\n dragging = true;\n startMove(event, {\n onMove: ({ deltaX, deltaY }) => {\n const target = position + (axis === 'y' ? deltaY : direction * deltaX) * ratio;\n if (axis === 'y') element.scrollTop = target;\n else element.scrollLeft = direction * target;\n },\n onEnd: () => {\n dragging = false;\n scheduleHide();\n },\n });\n }\n\n /** 点击轨道的空白处:朝那一侧翻一页 */\n function pageTo(event: PointerEvent) {\n if (!viewport || !thumb || event.button !== 0) return;\n const rect = thumb.getBoundingClientRect();\n const { view } = measure(viewport);\n // 点在滑块之前(上方;横向时为起始一侧)就往回翻\n const rtl = sign() === -1;\n const before =\n axis === 'y'\n ? event.clientY < rect.top\n : rtl\n ? event.clientX > rect.right\n : event.clientX < rect.left;\n const page = (before ? -1 : 1) * view * 0.9;\n viewport.scrollBy(axis === 'y' ? { top: page } : { left: sign() * page });\n }\n\n /** 滚动条盖在视口上面,滚轮落在它上面时转交给视口 */\n function forwardWheel(event: WheelEvent) {\n if (!viewport) return;\n event.preventDefault();\n viewport.scrollBy({ left: event.deltaX, top: event.deltaY });\n }\n\n return () => {\n const visible = overflowing && (type === 'always' || active);\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n scrollAreaBarStyles.track,\n scrollAreaBarStyles[axis],\n fixed && scrollAreaBarStyles.fixed,\n corner &&\n (axis === 'y' ? scrollAreaBarStyles.yCorner : scrollAreaBarStyles.xCorner),\n ],\n },\n propsScrollbar,\n {\n sx:\n !visible && (fixed ? scrollAreaBarStyles.hiddenReveal : scrollAreaBarStyles.hidden),\n ref: _toRef(track),\n 'aria-hidden': true,\n onPointerdown: pageTo,\n onWheel: forwardWheel,\n },\n )}\n data-axis={axis}\n data-state={visible ? 'visible' : 'hidden'}\n >\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n scrollAreaBarStyles.thumb,\n axis === 'y' ? scrollAreaBarStyles.thumbY : scrollAreaBarStyles.thumbX,\n ],\n },\n propsThumb,\n { ref: _toRef(thumb), onPointerdown: dragThumb },\n )}\n />\n </div>\n );\n };\n },\n { name: 'OverlayScrollbar' },\n);\n\n/** 滚动区域:原生滚动 + 半透明的浮层滚动条,出现与消失都不占位 */\nexport const ScrollArea = _component(\n ({\n axis = 'y',\n type = 'hover',\n hideDelay = 600,\n focusable = true,\n propsViewport,\n propsContent,\n propsScrollbar,\n propsThumb,\n children,\n ...rest\n }: ScrollAreaProps) => {\n let root = _state.raw<HTMLElement | null>(null);\n let viewport = _state.raw<HTMLElement | null>(null);\n let content = _state.raw<HTMLElement | null>(null);\n // 哪个方向的内容超出了视口:能滚动时视口才进 Tab 顺序,没超出的侧栏、代码块不多一个空的 Tab 位\n let overflowing = _state({ x: false, y: false });\n\n return () => {\n const both = axis === 'both';\n const bar = (barAxis: 'x' | 'y') => (\n <OverlayScrollbar\n axis={barAxis}\n hoverTarget={root}\n viewport={viewport}\n content={content}\n type={type}\n hideDelay={hideDelay}\n corner={both}\n propsScrollbar={propsScrollbar}\n propsThumb={propsThumb}\n onOverflowChange={(value) => (overflowing = { ...overflowing, [barAxis]: value })}\n />\n );\n return (\n <div {...mergeAttrs<'div'>({ sx: scrollAreaStyles.root }, rest, { ref: _toRef(root) })}>\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [focusRingStyles.visible, scrollAreaStyles.viewport, scrollAreaStyles[axis]],\n },\n propsViewport,\n {\n ref: _toRef(viewport),\n ...(focusable && (overflowing.x || overflowing.y) && { tabindex: 0 }),\n },\n )}\n >\n <div\n {...mergeAttrs<'div'>(\n { sx: axis !== 'y' && scrollAreaStyles.wideContent },\n propsContent,\n {\n ref: _toRef(content),\n },\n )}\n >\n {children}\n </div>\n </div>\n {axis !== 'x' && bar('y')}\n {axis !== 'y' && bar('x')}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { mergeAttrs } from "../utils/props.js";
2
- import { createVNode, mergeProps, useId } from "vue";
3
- import { _component, childrenProp, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
2
+ import { createVNode, useId } from "vue";
3
+ import { _component, childrenProp, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
4
4
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
5
5
  //#region src/layout/Separator.tsx
6
6
  /** 角色与朝向由组件管理 */
@@ -71,7 +71,7 @@ var Separator = /*#__PURE__*/ _component((_props, _ctx) => {
71
71
  "aria-hidden": decorative.value ? "true" : void 0
72
72
  }), null);
73
73
  const line = () => createVNode("span", mergeAttrs({ sx: separatorStyles.line }, propsLine.value, { "aria-hidden": true }), null);
74
- return createVNode("div", mergeProps(mergeAttrs({ sx: separatorStyles.labelled }, rest, {
74
+ return createVNode("div", mergeJsxProps(mergeAttrs({ sx: separatorStyles.labelled }, rest, {
75
75
  role: decorative.value ? "none" : "separator",
76
76
  "aria-labelledby": decorative.value ? void 0 : labelId
77
77
  }), { "data-label-align": labelAlign.value }), [