@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,6 +1,6 @@
1
1
  import { t } from "../config/theme/tokens.js";
2
2
  import { useLang, useTextMatcher } from "../config/context.js";
3
- import { mergeAttrs, mergePartProps, mergeProps as mergeProps$1 } from "../utils/props.js";
3
+ import { mergeAttrs, mergePartProps, mergeProps } from "../utils/props.js";
4
4
  import { focusRingStyles } from "../utils/style/styles.js";
5
5
  import { useRecipe } from "../config/styles.js";
6
6
  import { Icon } from "../base/Icon.js";
@@ -23,8 +23,8 @@ import { checkStates, filterTree, flattenTree, indexTree, toggleChecked, useTree
23
23
  import { itemStyles } from "../utils/style/item-styles.js";
24
24
  import { defaultRangeExtractor } from "../utils/virtual/virtualizer.js";
25
25
  import { useVirtualizer } from "../utils/virtual/use-virtualizer.js";
26
- import { computed, createVNode, mergeProps, onScopeDispose, ref, shallowRef, useId, watch } from "vue";
27
- import { _component, bindable, readonlyProp, restProps, untrack } from "@zerodep-dev/vue-tsx-pro-tsx";
26
+ import { computed, createVNode, onScopeDispose, ref, shallowRef, useId, watch } from "vue";
27
+ import { _component, bindable, mergeJsxProps, readonlyProp, restProps, untrack } from "@zerodep-dev/vue-tsx-pro-tsx";
28
28
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
29
29
  import { Check, ChevronRight, Minus } from "@lucide/icons";
30
30
  //#region src/display/Tree.tsx
@@ -480,7 +480,7 @@ var Tree = /*#__PURE__*/ _component((_props, _ctx) => {
480
480
  const marked = state.checked !== "unchecked";
481
481
  const box = choice();
482
482
  const dropZone = drop.value?.key === row.key ? drop.value.zone : void 0;
483
- return createVNode("div", mergeProps(mergeAttrs({ sx: [
483
+ return createVNode("div", mergeJsxProps(mergeAttrs({ sx: [
484
484
  itemStyles.row,
485
485
  itemStyles.hoverable,
486
486
  treeStyles.item,
@@ -552,14 +552,14 @@ var Tree = /*#__PURE__*/ _component((_props, _ctx) => {
552
552
  }, null)]),
553
553
  icon && createVNode(Icon, { "icon": icon }, null),
554
554
  createVNode("span", mergeAttrs({ sx: [itemStyles.label, filtering.value?.matched.has(row.key) && treeStyles.matched] }, propsLabel.value), [renderItem.value ? renderItem.value(row.node, state) : getLabel.value(row.node)]),
555
- dropZone && dropZone !== "inside" && createVNode("span", mergeProps({ "aria-hidden": "true" }, css.attrs(treeStyles.dropLine, dropZone === "before" ? treeStyles.dropBefore : treeStyles.dropAfter, treeDynamicStyles.lineStart(row.depth * indent.value + 1.75))), null)
555
+ dropZone && dropZone !== "inside" && createVNode("span", mergeJsxProps({ "aria-hidden": "true" }, css.attrs(treeStyles.dropLine, dropZone === "before" ? treeStyles.dropBefore : treeStyles.dropAfter, treeDynamicStyles.lineStart(row.depth * indent.value + 1.75))), null)
556
556
  ]);
557
557
  }
558
558
  /** 没有节点时:加载中是几行骨架,否则是空状态 */
559
559
  function renderPlaceholder() {
560
560
  if (loading.value) {
561
561
  if (!indicator.value) return null;
562
- return Array.from({ length: SKELETON_ROWS }, (_, row) => createVNode(Skeleton, mergeProps({ "key": row }, mergePartProps({
562
+ return Array.from({ length: SKELETON_ROWS }, (_, row) => createVNode(Skeleton, mergeJsxProps({ "key": row }, mergePartProps({
563
563
  sx: [treeStyles.skeleton, treeDynamicStyles.width(`${85 - row * 15}%`)],
564
564
  delay: row * 120
565
565
  }, propsSkeleton.value)), null));
@@ -572,9 +572,9 @@ var Tree = /*#__PURE__*/ _component((_props, _ctx) => {
572
572
  }
573
573
  return () => {
574
574
  const position = activeRow();
575
- return createVNode(ScrollArea, mergeProps(mergePartProps({}, propsScrollArea.value), {
575
+ return createVNode(ScrollArea, mergeJsxProps(mergePartProps({}, propsScrollArea.value), {
576
576
  "focusable": false,
577
- "propsViewport": mergeProps$1({ sx: [treeStyles.root, focusRingStyles.visible] }, rest, {
577
+ "propsViewport": mergeProps({ sx: [treeStyles.root, focusRingStyles.visible] }, rest, {
578
578
  ref: root,
579
579
  id: prefix(),
580
580
  role: "tree",
@@ -588,10 +588,10 @@ var Tree = /*#__PURE__*/ _component((_props, _ctx) => {
588
588
  }),
589
589
  "key": "__site0"
590
590
  }), {
591
- default: () => [rows.value.length === 0 && renderPlaceholder(), createVNode("div", mergeProps({
591
+ default: () => [rows.value.length === 0 && renderPlaceholder(), createVNode("div", mergeJsxProps({
592
592
  "ref": sizer,
593
593
  "role": "presentation"
594
- }, css.attrs(treeStyles.sizer, css.bind(treeDynamicStyles.height, () => [virtual.total], true))), [virtual.items.map((item) => createVNode("div", mergeProps({ "key": item.key }, mergeAttrs({ sx: treeStyles.row }, propsRow.value, {
594
+ }, css.attrs(treeStyles.sizer, css.bind(treeDynamicStyles.height, () => [virtual.total], true))), [virtual.items.map((item) => createVNode("div", mergeJsxProps({ "key": item.key }, mergeAttrs({ sx: treeStyles.row }, propsRow.value, {
595
595
  ref: virtual.measure,
596
596
  role: "presentation",
597
597
  sx: css.bind(treeDynamicStyles.y, () => [item.start])
@@ -1 +1 @@
1
- {"version":3,"file":"Tree.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_shallowRef","_vue_ref","_vue_computed","_vtp_untrack","_createVNode","_mergeProps","mergeProps"],"sources":["../../src/display/Tree.tsx"],"sourcesContent":["/**\n * 树(WAI-ARIA Tree):可展开的层级列表(文件夹、组织架构、分类),可单选 / 多选、勾选(父子联动、半选)、懒加载子节点。\n * 数据驱动,始终虚拟滚动(上万个节点也只渲染看得见的几十个):\n *\n * <Tree\n * items={folders}\n * getKey={(node) => node.id}\n * getLabel={(node) => node.name}\n * getChildren={(node) => node.children}\n * _expanded={open}\n * selectionMode=\"single\"\n * _selected={current}\n * aria-label=\"目录\"\n * />\n *\n * - 键盘:焦点在树上,当前项经 aria-activedescendant 告诉读屏。↑↓ 移动,→ 展开 / 进入第一个子节点,← 收起 / 回到父节点,\n * Home / End,Enter 选中(没有选择时展开或收起),空格勾选(checkable 时)或选中,按字母跳到以它开头的节点。\n * - 勾选:checkable 时每项前有勾选框,_checked={keys} 是勾上的全部节点;勾上父节点会勾上它的子孙,\n * 子节点全勾上时父节点也勾上,只勾了一部分时父节点半选(aria-checked=\"mixed\")。\n * - 懒加载:hasChildren 说有子节点、getChildren 还没有时,展开会调用 loadChildren(加载中显示加载指示)。\n * - 节点平铺渲染(虚拟滚动没法嵌套 role=\"group\"),层级经 aria-level / aria-setsize / aria-posinset 告诉读屏。\n *\n * 展开状态与勾选联动见 utils/data/tree.ts(TreeDataTable 共用)。部件:Root(div,role=\"tree\")、\n * Row(虚拟滚动定位的一行,包着 Item)、Item(div,role=\"treeitem\")、Toggle(展开箭头)、\n * Checkbox(勾选框,只是外观,状态在 treeitem 的 aria-checked 上)、Label、ScrollArea(外层的滚动区域)。\n */\nimport { Check, ChevronRight, Minus } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { onScopeDispose, useId, watch, type VNodeChild } from 'vue';\nimport { Icon, type IconData } from '../base/Icon';\nimport { Spinner } from '../base/Spinner';\nimport { useLang, useTextMatcher } from '../config/context';\nimport { t } from '../config/theme/tokens';\nimport { announce } from '../utils/dom/announcer';\nimport { startMove } from '../utils/dom/move';\nimport { Empty, type EmptyProps } from '../feedback/Empty';\nimport { Skeleton, type SkeletonProps, type SkeletonShapeProps } from '../feedback/Skeleton';\nimport { useDelayedLoading } from '../utils/motion/delayed-loading';\nimport { SHIMMER_STAGGER } from '../utils/style/shimmer';\nimport { checkboxStyles } from '../input/Checkbox';\nimport { choiceInputStyles, choiceRecipe } from '../input/choice-styles';\nimport { useRecipe } from '../config/styles';\nimport { toneFillStyles } from '../utils/style/tone-styles';\nimport { inlineArrows, isRtl } from '../utils/dom/direction';\nimport { toggleSelection, type SelectionModes } from '../utils/data/selection';\nimport {\n checkStates,\n filterTree,\n flattenTree,\n indexTree,\n toggleChecked,\n useTreeExpansion,\n type CheckState,\n type TreeAccessors,\n type TreeMoveTarget,\n} from '../utils/data/tree';\nimport { createTypeahead } from '../utils/dom/typeahead';\nimport { mergeAttrs, mergePartProps, mergeProps, type PartProps } from '../utils/props';\nimport { ScrollArea, type ScrollAreaProps } from '../layout/ScrollArea';\nimport { itemStyles } from '../utils/style/item-styles';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { useVirtualizer } from '../utils/virtual/use-virtualizer';\nimport { defaultRangeExtractor } from '../utils/virtual/virtualizer';\nimport { disclosureStyles } from '../utils/style/transitions';\n\n/** 节点的渲染状态 */\nexport interface TreeItemRenderState {\n /** 层级,第一层为 0 */\n depth: number;\n /** 展开着 */\n expanded: boolean;\n /** 已选 */\n selected: boolean;\n /** 勾选状态(checkable 时) */\n checked: CheckState;\n /** 键盘所在的当前项 */\n active: boolean;\n}\n\n/** 一次移动:把 key 移到 target(交给 moveNode) */\nexport interface TreeMove<T> {\n /** 移动的节点的 key */\n key: string;\n /** 移动的节点 */\n node: T;\n /** 放到哪个节点下的第几位(按移走之后的同级算) */\n target: TreeMoveTarget;\n}\n\n/** 拖动时的落点:放在 key 这一项的前面、后面或里面 */\ninterface DropSpot {\n key: string;\n zone: 'before' | 'after' | 'inside';\n}\n\n/** 未声明的属性落到 div(role=\"tree\")上;aria-label 或 aria-labelledby 是树的名称 */\nexport interface TreeProps<T> extends PartProps<'div', 'role'> {\n /** 第一层的节点 */\n items: readonly T[];\n /** 节点的 key,整棵树里唯一 */\n getKey: (node: T) => string;\n /** 节点的文字:默认显示它,类型搜索也按它 */\n getLabel: (node: T) => string;\n /** 子节点;叶子或还没加载时返回 undefined / 空数组 */\n getChildren: (node: T) => readonly T[] | undefined;\n /** 有没有子节点(懒加载时子节点还没取回来也要能展开);不写时看 getChildren 是否非空 */\n hasChildren?: (node: T) => boolean;\n /** 展开一个还没有子节点的节点时调用:取回子节点并放进数据里;返回 Promise 时显示加载中 */\n loadChildren?: (node: T) => Promise<unknown> | void;\n /** 子节点加载失败(loadChildren 的 Promise 被拒绝):节点收回去,再展开会重试;不写时在控制台报错 */\n onLoadError?: (error: unknown, node: T) => void;\n /** 节点不可用:可以经过、展开,不能选中、勾选 */\n isDisabled?: (node: T) => boolean;\n /** 文字前的图标,可以按展开状态换(文件夹开 / 合) */\n getIcon?: (node: T, expanded: boolean) => IconData | undefined;\n /** 展开的节点:父级写 _expanded={keys} */\n _expanded?: string[];\n /** 选择方式;不写时不能选中 */\n selectionMode?: keyof SelectionModes;\n /** 选中的节点:父级写 _selected={keys} */\n _selected?: string[];\n /** 每项前显示勾选框,默认父子联动 */\n checkable?: boolean;\n /** 勾选父子不联动:每个节点各自勾选(权限树里“只给这一级”) */\n checkStrictly?: boolean;\n /** 勾上的节点(联动时含勾上的父节点与子孙):父级写 _checked={keys} */\n _checked?: string[];\n /** 正在取节点:还没有节点时显示骨架行,树带 aria-busy */\n loading?: boolean;\n /** 没有节点时显示的内容;默认是 Empty(文案取语言包) */\n empty?: VNodeChild;\n /** 每一层缩进多少(em),默认 1.25 */\n indent?: number;\n /** 每项的估计高度(px),默认 32;渲染后以实际高度为准 */\n estimateSize?: number;\n /**\n * 搜索过滤:字符串时按节点文字匹配(忽略大小写与重音,或 createUi 的 textMatcher),函数时自己判断。\n * 留下匹配的节点与它们的祖先并展开祖先,匹配的节点文字加粗;只看已加载的节点。清空后回到原来的展开状态\n */\n filter?: string | ((node: T) => boolean);\n /**\n * 拖动节点改变层级与顺序:放下(或 Alt + 方向键)时报告移动,用 moveNode 生成新数据交回 items;不写时不能拖。\n * 指针拖动只用鼠标、笔(触摸时照常滚动)\n */\n onMove?: (move: TreeMove<T>) => void;\n /** 能不能放到这里(如文件不能放进文件里);不写时都能放(放进自己和自己的子孙里除外) */\n canDrop?: (node: T, target: TreeMoveTarget) => boolean;\n /** 自定义文字部分的内容 */\n renderItem?: (node: T, state: TreeItemRenderState) => VNodeChild;\n /** 每一项的部件属性,可以按节点计算 */\n propsItem?:\n PartProps<'div', 'role' | 'id'> | ((node: T, state: TreeItemRenderState) => PartProps<'div'>);\n /** 每一行(虚拟滚动定位的容器,包着 treeitem)的部件属性 */\n propsRow?: PartProps<'div', 'role'>;\n /** 展开箭头的部件属性(只是外观,键盘与读屏走 treeitem) */\n propsToggle?: PartProps<'span', 'aria-hidden'>;\n /** 勾选框的部件属性(只是外观,状态在 treeitem 的 aria-checked 上) */\n propsCheckbox?: PartProps<'span', 'aria-hidden'>;\n /** 文字的部件属性 */\n propsLabel?: PartProps<'span'>;\n /** 默认空状态(Empty)的部件属性 */\n propsEmpty?: Partial<EmptyProps>;\n /** 加载中的骨架行的部件属性 */\n propsSkeleton?: SkeletonShapeProps;\n /** 外层滚动区域(ScrollArea)的部件属性:放进弹出层、弹性布局时给它 sx;树元素本身是它的视口 */\n propsScrollArea?: Partial<Omit<ScrollAreaProps, 'propsViewport'>>;\n}\n\n/** Tree 的样式:root、sizer、row、item、toggle、checkbox、label 等 */\nexport const treeStyles = css.create({\n // 树元素就是 ScrollArea 的视口(浮层滚动条);焦点与 aria-activedescendant 在它上面\n root: {\n position: 'relative',\n overscrollBehavior: 'contain',\n padding: '_xs',\n outlineStyle: 'none',\n },\n sizer: { position: 'relative', width: '_full' },\n skeleton: { display: 'block', height: '1em', marginBlock: '0.625em', marginInline: '_sm' },\n row: { position: 'absolute', top: 0, insetInline: 0, paddingBlock: '1px' },\n item: { gap: '_xs', minHeight: '_sizes.minTarget', paddingInlineStart: '_xs' },\n toggle: {\n display: 'grid',\n placeItems: 'center',\n flexShrink: 0,\n width: '1.5em',\n height: '1.5em',\n color: '_textMuted',\n },\n chevronOpen: { rotate: '90deg' },\n checkbox: { marginInlineEnd: '_xs' },\n checkMark: { width: '0.875em', height: '0.875em', color: '_accentContrast' },\n hidden: { visibility: 'hidden' },\n // 搜索时匹配的节点\n matched: { fontWeight: '_semibold' },\n // 拖动:被拖的那一项变淡;放进某一项里时它带品牌色的框;放在前后时画一条线\n dragging: { opacity: 0.5 },\n dropInside: {\n outlineStyle: 'solid',\n outlineWidth: '_borderWidths.sm',\n outlineColor: '_accent',\n outlineOffset: `calc(-1 * ${t.borderWidths.sm})`,\n backgroundColor: '_accentSoft',\n },\n dropLine: {\n position: 'absolute',\n insetInlineEnd: 0,\n height: '_borderWidths.sm',\n backgroundColor: '_accent',\n borderRadius: '_full',\n pointerEvents: 'none',\n },\n dropBefore: { top: `calc(-1 * ${t.borderWidths.xs})` },\n dropAfter: { bottom: `calc(-1 * ${t.borderWidths.xs})` },\n // 画线的那一项要作定位参照\n positioned: { position: 'relative' },\n});\n\n// 缩进与位置是任意值,用动态样式;单独一个 create,见 COMPONENTS.md §4\n/** Tree 的样式:indent(缩进)、y、height */\nexport const treeDynamicStyles = css.create({\n indent: (em: number) => ({ width: `${em}em`, flexShrink: 0 }),\n y: (px: number) => ({ transform: `translateY(${px}px)` }),\n height: (px: number) => ({ height: px }),\n width: (value: string) => ({ width: value }),\n // 落点线从这一层的缩进处开始\n lineStart: (em: number) => ({ insetInlineStart: `${em}em` }),\n});\n\n/** 加载中显示几行骨架 */\nconst SKELETON_ROWS = 4;\n\nconst ARIA_CHECKED: Record<CheckState, 'true' | 'false' | 'mixed'> = {\n checked: 'true',\n unchecked: 'false',\n indeterminate: 'mixed',\n};\n\n/** 树:可展开的层级列表,单选 / 多选、父子联动的勾选、懒加载、方向键导航、虚拟滚动 */\nexport const Tree = _component(\n <T,>({\n items,\n getKey,\n getLabel,\n getChildren,\n hasChildren,\n loadChildren,\n onLoadError,\n isDisabled,\n getIcon,\n _expanded: expanded = _bindable<string[]>([]),\n selectionMode,\n _selected: selected = _bindable<string[]>([]),\n checkable = false,\n checkStrictly = false,\n _checked: checked = _bindable<string[]>([]),\n loading = false,\n empty,\n indent = 1.25,\n estimateSize = 32,\n filter,\n onMove,\n canDrop,\n renderItem,\n propsItem,\n propsRow,\n propsToggle,\n propsCheckbox,\n propsLabel,\n propsEmpty,\n propsSkeleton,\n propsScrollArea,\n id,\n ...rest\n }: TreeProps<T>) => {\n const lang = useLang();\n // 骨架防闪烁:很快就取回来时不显示;aria-busy 按真实的 loading\n const indicator = useDelayedLoading(() => loading);\n const generatedId = useId();\n const prefix = () => id ?? generatedId;\n let root = _state.raw<HTMLElement | null>(null);\n let sizer = _state.raw<HTMLElement | null>(null);\n // 键盘所在的当前项;焦点在树上时才高亮\n let active = _state<string | undefined>(undefined);\n let focused = _state(false);\n const typeahead = createTypeahead();\n // 勾选框画成 Checkbox 的样子,跟着 styles.Choice 的定制\n const choice = useRecipe(choiceRecipe);\n\n const accessors = (): TreeAccessors<T> => ({\n getKey: (node) => getKey(node),\n getChildren,\n hasChildren,\n });\n\n // 搜索过滤:匹配的节点与祖先;为 null 时不过滤\n const textMatcher = useTextMatcher();\n const filtering = _derived.by(() => {\n const query = typeof filter === 'string' ? filter.trim() : filter;\n if (!query) return null;\n const match =\n typeof query === 'string' ? (node: T) => textMatcher()(getLabel(node), query) : query;\n return filterTree(items, accessors(), match);\n });\n // 过滤时的展开状态单独记:一开始展开匹配项的祖先,可以再收起;清空过滤后回到原来的 expanded\n let filterExpanded = _state<string[]>([]);\n watch(\n () => filtering,\n (result) => (filterExpanded = result ? [...result.expand] : []),\n { immediate: true },\n );\n const shownExpanded = () => (filtering ? filterExpanded : expanded);\n\n const expansion = useTreeExpansion<T>({\n expanded: shownExpanded,\n setExpanded: (keys) => (filtering ? (filterExpanded = keys) : (expanded = keys)),\n getChildren: (node) => getChildren(node),\n loadChildren: (node) => loadChildren?.(node),\n // 没给 onLoadError 时交给 useTreeExpansion 在控制台报错\n onLoadError: _untrack(onLoadError) && ((error, node) => onLoadError?.(error, node)),\n });\n\n const rows = _derived.by(() =>\n flattenTree(items, accessors(), new Set(shownExpanded()), { include: filtering?.include }),\n );\n const rowOf = _derived.by(() => new Map(rows.map((row, index) => [row.key, index])));\n // 勾选联动要看到折叠着的节点:只在联动勾选时建整棵树的索引\n const index = _derived.by(() =>\n checkable && !checkStrictly ? indexTree(items, accessors()) : null,\n );\n const states = _derived.by(() => (index ? checkStates(index, checked) : null));\n const checkedSet = _derived.by(() => new Set(checked));\n const selectedSet = _derived.by(() => new Set(selected));\n\n /** 当前项的行号;没有时 -1 */\n const activeRow = () => (active === undefined ? -1 : (rowOf.get(active) ?? -1));\n\n const virtual = useVirtualizer(() => {\n const current = rows;\n // 读一下当前项:它变了要重新算渲染范围(当前项总要渲染,aria-activedescendant 才指得到)\n const focusedRow = activeRow();\n // 先读出来:每一项都要调用一次估计高度,不要每次都经过 props 的响应式读取\n const size = estimateSize;\n return {\n count: current.length,\n scrollElement: root,\n list: sizer,\n estimateSize: () => size,\n getItemKey: (position: number) => current[position]!.key,\n overscan: 6,\n rangeExtractor: (range) => {\n const indices = defaultRangeExtractor(range);\n if (focusedRow >= 0 && !indices.includes(focusedRow)) {\n indices.push(focusedRow);\n indices.sort((a, b) => a - b);\n }\n return indices;\n },\n };\n });\n\n watch(\n () => active,\n () => {\n const position = activeRow();\n if (position >= 0) virtual.scrollToIndex(position, { align: 'auto' });\n },\n { flush: 'post' },\n );\n\n // 当前项所在的父节点被收起:当前项移到还看得见的最近祖先\n watch(\n () => rows,\n (next, previous) => {\n if (active === undefined || rowOf.has(active)) return;\n let parent = previous.find((row) => row.key === active)?.parent;\n while (parent !== undefined && !rowOf.has(parent)) {\n parent = previous.find((row) => row.key === parent)?.parent;\n }\n active = parent ?? next[0]?.key;\n },\n );\n\n const disabledAt = (position: number) => {\n const row = rows[position];\n return !row || (isDisabled?.(row.node) ?? false);\n };\n\n function select(position: number) {\n const row = rows[position];\n if (!row || !selectionMode || disabledAt(position)) return;\n selected = [...toggleSelection(selected, row.key, { mode: selectionMode })];\n }\n\n function check(position: number) {\n const row = rows[position];\n if (!row || !checkable || disabledAt(position)) return;\n checked = index\n ? toggleChecked(index, checked, row.key)\n : [...toggleSelection(checked, row.key, { mode: 'multiple' })];\n }\n\n function toggle(position: number) {\n const row = rows[position];\n if (row?.expandable)\n void expansion.setOpen(row.node, row.key, !expansion.isExpanded(row.key));\n }\n\n // —— 移动节点(onMove):指针拖动,或 Alt + 方向键 ——\n let dragging = _state<string | undefined>(undefined);\n let drop = _state.raw<DropSpot | null>(null);\n let expandTimer: ReturnType<typeof setTimeout> | undefined;\n let stopDrag: (() => void) | undefined;\n onScopeDispose(() => {\n clearTimeout(expandTimer);\n stopDrag?.();\n });\n\n const rowByKey = (key: string | undefined) =>\n key === undefined ? undefined : rows[rowOf.get(key) ?? -1];\n\n /** key 是不是 ancestor 自己或它的子孙(看得见的行里,祖先总是看得见的) */\n function isWithin(key: string, ancestor: string) {\n for (let at: string | undefined = key; at !== undefined; at = rowByKey(at)?.parent) {\n if (at === ancestor) return true;\n }\n return false;\n }\n\n /** 落点换算成移动的目标(按移走之后的同级算);放不下时 null */\n function targetOf(key: string, spot: DropSpot): TreeMoveTarget | null {\n const moving = rowByKey(key);\n const row = rowByKey(spot.key);\n if (!moving || !row || isWithin(spot.key, key)) return null;\n let target: TreeMoveTarget;\n if (spot.zone === 'inside') target = { parent: row.key, index: Number.MAX_SAFE_INTEGER };\n else {\n const offset = spot.zone === 'before' ? row.position - 1 : row.position;\n // 同一层里从前面移过来:移走之后,后面的都往前挪了一位\n const shift = moving.parent === row.parent && moving.position <= offset ? 1 : 0;\n target = { parent: row.parent, index: offset - shift };\n }\n return canDrop && !canDrop(moving.node, target) ? null : target;\n }\n\n /** 报告移动,并告诉读屏移到了哪里 */\n function emitMove(key: string, target: TreeMoveTarget) {\n const row = rowByKey(key);\n if (!row || !onMove) return;\n const parent = rowByKey(target.parent);\n // 移走之后的同级个数:同一层里移动时要去掉自己\n const count =\n (parent ? (getChildren(parent.node)?.length ?? 0) : items.length) -\n (row.parent === target.parent ? 1 : 0);\n onMove({ key, node: row.node, target });\n announce(\n lang.treeMoved(\n getLabel(row.node),\n parent && getLabel(parent.node),\n Math.min(target.index, count) + 1,\n ),\n );\n }\n\n /** 指针下的落点:一项的上四分之一放在它前面,下四分之一放在后面,中间放进它里面 */\n function spotAt(clientX: number, clientY: number): DropSpot | null {\n const element = document\n .elementFromPoint(clientX, clientY)\n ?.closest<HTMLElement>('[data-index]');\n if (!element || !root?.contains(element)) return null;\n const row = rows[Number(element.dataset.index)];\n if (!row) return null;\n const rect = element.getBoundingClientRect();\n const ratio = (clientY - rect.top) / rect.height;\n return { key: row.key, zone: ratio < 0.25 ? 'before' : ratio > 0.75 ? 'after' : 'inside' };\n }\n\n /** 拖到靠近上下边缘时滚动 */\n function autoScroll(clientY: number) {\n if (!root) return;\n const rect = root.getBoundingClientRect();\n if (clientY < rect.top + 32) root.scrollTop -= 12;\n else if (clientY > rect.bottom - 32) root.scrollTop += 12;\n }\n\n /** 拖到收起的节点里停一会儿:展开它,好放到更深的地方 */\n function scheduleExpand(spot: DropSpot | null) {\n clearTimeout(expandTimer);\n const row = spot?.zone === 'inside' ? rowByKey(spot.key) : undefined;\n if (!row?.expandable || expansion.isExpanded(row.key)) return;\n expandTimer = setTimeout(() => void expansion.setOpen(row.node, row.key, true), 600);\n }\n\n function onItemPointerdown(event: PointerEvent, key: string) {\n // 焦点留在树上\n event.preventDefault();\n // 触摸时照常滚动,不拖\n if (!onMove || event.pointerType === 'touch' || !root) return;\n stopDrag = startMove(event, {\n threshold: 4,\n // 虚拟滚动会换掉行元素:捕获在不动的树上\n captureTarget: root,\n onMove: ({ clientX, clientY }) => {\n dragging = key;\n // 先按当前的位置算落点,再滚动:滚动后指针下面换成了别的项\n const spot = spotAt(clientX, clientY);\n autoScroll(clientY);\n const next = spot && targetOf(key, spot) ? spot : null;\n if (next?.key === drop?.key && next?.zone === drop?.zone) return;\n drop = next;\n scheduleExpand(next);\n },\n onEnd: ({ moved, cancelled }) => {\n const spot = drop;\n dragging = undefined;\n drop = null;\n stopDrag = undefined;\n clearTimeout(expandTimer);\n if (!moved || cancelled || !spot) return;\n const target = targetOf(key, spot);\n if (target) emitMove(key, target);\n },\n });\n }\n\n /** Alt + ↑↓ 在同级里移动,Alt + → 放进上一个同级的最后,Alt + ← 移到父节点后面(从右到左时左右对调) */\n function moveByKey(event: KeyboardEvent): boolean {\n const row = rows[activeRow()];\n if (!row) return false;\n const { forward, backward } = inlineArrows(!!root && isRtl(root));\n let target: TreeMoveTarget | undefined;\n switch (event.key) {\n case 'ArrowUp':\n if (row.position > 1) target = { parent: row.parent, index: row.position - 2 };\n break;\n case 'ArrowDown':\n if (row.position < row.setSize) target = { parent: row.parent, index: row.position };\n break;\n case forward: {\n const previous = rows.find(\n (item) => item.parent === row.parent && item.position === row.position - 1,\n );\n if (!previous) break;\n target = { parent: previous.key, index: Number.MAX_SAFE_INTEGER };\n // 展开新的父节点:移过去之后还看得见\n void expansion.setOpen(previous.node, previous.key, true);\n break;\n }\n case backward: {\n const parent = rowByKey(row.parent);\n if (parent) target = { parent: parent.parent, index: parent.position };\n break;\n }\n default:\n return false;\n }\n if (target && (!canDrop || canDrop(row.node, target))) emitMove(row.key, target);\n return true;\n }\n\n function onKeydown(event: KeyboardEvent) {\n if (event.altKey && onMove && !event.ctrlKey && !event.metaKey) {\n if (moveByKey(event)) event.preventDefault();\n return;\n }\n if (event.altKey || event.ctrlKey || event.metaKey || rows.length === 0) return;\n const position = Math.max(activeRow(), 0);\n const row = rows[position]!;\n const open = row.expandable && expansion.isExpanded(row.key);\n const { forward, backward } = inlineArrows(!!root && isRtl(root));\n const go = (target: number) => (active = rows[target]?.key ?? active);\n switch (event.key) {\n case 'ArrowDown':\n go(Math.min(position + 1, rows.length - 1));\n break;\n case 'ArrowUp':\n go(Math.max(position - 1, 0));\n break;\n case 'Home':\n go(0);\n break;\n case 'End':\n go(rows.length - 1);\n break;\n case forward:\n if (!row.expandable) break;\n if (!open) void expansion.setOpen(row.node, row.key, true);\n // 已展开:进入第一个子节点(子节点还没加载出来时不动)\n else if (rows[position + 1]?.parent === row.key) go(position + 1);\n break;\n case backward:\n if (open) void expansion.setOpen(row.node, row.key, false);\n else if (row.parent !== undefined) active = row.parent;\n break;\n case 'Enter':\n if (selectionMode) select(position);\n else toggle(position);\n break;\n case ' ':\n if (checkable) check(position);\n else select(position);\n break;\n default: {\n const found = typeahead.next(\n event.key,\n rows.map((item) => getLabel(item.node)),\n activeRow(),\n );\n if (found < 0) return;\n go(found);\n }\n }\n event.preventDefault();\n }\n\n function onFocus() {\n focused = true;\n if (active !== undefined && rowOf.has(active)) return;\n // 第一次进入:落在第一个已选的可见节点上,没有时落在第一项\n active = rows.find((row) => selectedSet.has(row.key))?.key ?? rows[0]?.key;\n }\n\n function renderRow(position: number) {\n const row = rows[position]!;\n const open = row.expandable && expansion.isExpanded(row.key);\n const disabled = disabledAt(position);\n const state: TreeItemRenderState = {\n depth: row.depth,\n expanded: open,\n selected: selectedSet.has(row.key),\n checked: states\n ? (states.get(row.key) ?? 'unchecked')\n : checkedSet.has(row.key)\n ? 'checked'\n : 'unchecked',\n active: active === row.key,\n };\n const own = typeof propsItem === 'function' ? propsItem(row.node, state) : propsItem;\n const icon = getIcon?.(row.node, open);\n const loading = expansion.isLoading(row.key);\n const marked = state.checked !== 'unchecked';\n const box = choice();\n const dropZone = drop?.key === row.key ? drop.zone : undefined;\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n itemStyles.row,\n itemStyles.hoverable,\n treeStyles.item,\n focused && state.active && itemStyles.highlighted,\n state.selected && itemStyles.current,\n disabled && itemStyles.disabled,\n dragging === row.key && treeStyles.dragging,\n dropZone === 'inside' && treeStyles.dropInside,\n dropZone && dropZone !== 'inside' && treeStyles.positioned,\n ],\n },\n own,\n {\n id: `${prefix()}-${position}`,\n role: 'treeitem',\n 'aria-level': row.depth + 1,\n 'aria-setsize': row.setSize,\n 'aria-posinset': row.position,\n 'aria-expanded': row.expandable ? open : undefined,\n 'aria-selected': selectionMode ? state.selected : undefined,\n 'aria-checked': checkable ? ARIA_CHECKED[state.checked] : undefined,\n 'aria-disabled': disabled || undefined,\n 'aria-busy': loading || undefined,\n onPointerdown: (event: PointerEvent) => onItemPointerdown(event, row.key),\n onClick: () => {\n active = row.key;\n root?.focus({ preventScroll: true });\n if (selectionMode) select(position);\n else if (checkable) check(position);\n else toggle(position);\n },\n },\n )}\n data-state={state.selected ? 'selected' : undefined}\n data-active={state.active || undefined}\n data-disabled={disabled || undefined}\n >\n {row.depth > 0 && <span {...css.attrs(treeDynamicStyles.indent(row.depth * indent))} />}\n <span\n {...mergeAttrs<'span'>({ sx: treeStyles.toggle }, propsToggle, {\n 'aria-hidden': true,\n onClick: (event: MouseEvent) => {\n if (!row.expandable) return;\n event.stopPropagation();\n active = row.key;\n root?.focus({ preventScroll: true });\n toggle(position);\n },\n })}\n >\n {loading ? (\n <Spinner />\n ) : (\n row.expandable && (\n <Icon\n icon={ChevronRight}\n flipInRtl\n sx={[disclosureStyles.icon, open && treeStyles.chevronOpen]}\n />\n )\n )}\n </span>\n {checkable && (\n <span\n {...mergeAttrs<'span'>(\n // 勾选框的实底色取色调变量(同 Checkbox 的 choiceParts)\n { sx: [box.control.sx, toneFillStyles.accent, treeStyles.checkbox] },\n propsCheckbox,\n {\n 'aria-hidden': true,\n onClick: (event: MouseEvent) => {\n event.stopPropagation();\n active = row.key;\n root?.focus({ preventScroll: true });\n check(position);\n },\n },\n )}\n >\n <span\n {...css.attrs(\n box.input.sx,\n focusRingStyles.tight,\n checkboxStyles.box,\n marked && choiceInputStyles.checked,\n )}\n />\n <Icon\n icon={state.checked === 'indeterminate' ? Minus : Check}\n strokeWidth={3}\n sx={[box.indicator.sx, treeStyles.checkMark, !marked && treeStyles.hidden]}\n />\n </span>\n )}\n {icon && <Icon icon={icon} />}\n <span\n {...mergeAttrs<'span'>(\n { sx: [itemStyles.label, filtering?.matched.has(row.key) && treeStyles.matched] },\n propsLabel,\n )}\n >\n {renderItem ? renderItem(row.node, state) : getLabel(row.node)}\n </span>\n {dropZone && dropZone !== 'inside' && (\n <span\n aria-hidden=\"true\"\n {...css.attrs(\n treeStyles.dropLine,\n dropZone === 'before' ? treeStyles.dropBefore : treeStyles.dropAfter,\n treeDynamicStyles.lineStart(row.depth * indent + 1.75),\n )}\n />\n )}\n </div>\n );\n }\n\n /** 没有节点时:加载中是几行骨架,否则是空状态 */\n function renderPlaceholder() {\n if (loading) {\n if (!indicator.value) return null;\n return Array.from({ length: SKELETON_ROWS }, (_, row) => (\n <Skeleton\n key={row}\n {...mergePartProps<SkeletonProps>(\n {\n sx: [treeStyles.skeleton, treeDynamicStyles.width(`${85 - row * 15}%`)],\n delay: row * SHIMMER_STAGGER,\n },\n propsSkeleton,\n )}\n />\n ));\n }\n return (\n empty ?? (\n <Empty\n {...mergePartProps<EmptyProps>(\n {\n size: 'sm',\n icon: false,\n description: filtering ? lang.treeNoMatch : lang.treeEmpty,\n },\n propsEmpty,\n )}\n />\n )\n );\n }\n\n return () => {\n const position = activeRow();\n return (\n <ScrollArea\n {...mergePartProps<ScrollAreaProps>({}, propsScrollArea)}\n focusable={false}\n propsViewport={\n mergeProps<'div'>({ sx: [treeStyles.root, focusRingStyles.visible] }, rest, {\n ref: _toRef(root),\n id: prefix(),\n role: 'tree',\n tabindex: rows.length > 0 ? 0 : -1,\n 'aria-multiselectable': selectionMode === 'multiple' || undefined,\n 'aria-activedescendant': position >= 0 ? `${prefix()}-${position}` : undefined,\n 'aria-busy': loading || undefined,\n onFocus,\n onBlur: () => (focused = false),\n onKeydown,\n }) as PartProps<'div'>\n }\n >\n {rows.length === 0 && renderPlaceholder()}\n <div\n ref={_toRef(sizer)}\n role=\"presentation\"\n {...css.attrs(treeStyles.sizer, treeDynamicStyles.height(virtual.total))}\n >\n {virtual.items.map((item) => (\n <div\n key={item.key}\n {...mergeAttrs<'div'>({ sx: treeStyles.row }, propsRow, {\n ref: virtual.measure,\n role: 'presentation',\n sx: treeDynamicStyles.y(item.start),\n })}\n data-index={item.index}\n >\n {renderRow(item.index)}\n </div>\n ))}\n </div>\n </ScrollArea>\n );\n };\n },\n { name: 'Tree' },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"Tree.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_shallowRef","_vue_ref","_vue_computed","_vtp_untrack","_createVNode","_mergeProps"],"sources":["../../src/display/Tree.tsx"],"sourcesContent":["/**\n * 树(WAI-ARIA Tree):可展开的层级列表(文件夹、组织架构、分类),可单选 / 多选、勾选(父子联动、半选)、懒加载子节点。\n * 数据驱动,始终虚拟滚动(上万个节点也只渲染看得见的几十个):\n *\n * <Tree\n * items={folders}\n * getKey={(node) => node.id}\n * getLabel={(node) => node.name}\n * getChildren={(node) => node.children}\n * _expanded={open}\n * selectionMode=\"single\"\n * _selected={current}\n * aria-label=\"目录\"\n * />\n *\n * - 键盘:焦点在树上,当前项经 aria-activedescendant 告诉读屏。↑↓ 移动,→ 展开 / 进入第一个子节点,← 收起 / 回到父节点,\n * Home / End,Enter 选中(没有选择时展开或收起),空格勾选(checkable 时)或选中,按字母跳到以它开头的节点。\n * - 勾选:checkable 时每项前有勾选框,_checked={keys} 是勾上的全部节点;勾上父节点会勾上它的子孙,\n * 子节点全勾上时父节点也勾上,只勾了一部分时父节点半选(aria-checked=\"mixed\")。\n * - 懒加载:hasChildren 说有子节点、getChildren 还没有时,展开会调用 loadChildren(加载中显示加载指示)。\n * - 节点平铺渲染(虚拟滚动没法嵌套 role=\"group\"),层级经 aria-level / aria-setsize / aria-posinset 告诉读屏。\n *\n * 展开状态与勾选联动见 utils/data/tree.ts(TreeDataTable 共用)。部件:Root(div,role=\"tree\")、\n * Row(虚拟滚动定位的一行,包着 Item)、Item(div,role=\"treeitem\")、Toggle(展开箭头)、\n * Checkbox(勾选框,只是外观,状态在 treeitem 的 aria-checked 上)、Label、ScrollArea(外层的滚动区域)。\n */\nimport { Check, ChevronRight, Minus } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { onScopeDispose, useId, watch, type VNodeChild } from 'vue';\nimport { Icon, type IconData } from '../base/Icon';\nimport { Spinner } from '../base/Spinner';\nimport { useLang, useTextMatcher } from '../config/context';\nimport { t } from '../config/theme/tokens';\nimport { announce } from '../utils/dom/announcer';\nimport { startMove } from '../utils/dom/move';\nimport { Empty, type EmptyProps } from '../feedback/Empty';\nimport { Skeleton, type SkeletonProps, type SkeletonShapeProps } from '../feedback/Skeleton';\nimport { useDelayedLoading } from '../utils/motion/delayed-loading';\nimport { SHIMMER_STAGGER } from '../utils/style/shimmer';\nimport { checkboxStyles } from '../input/Checkbox';\nimport { choiceInputStyles, choiceRecipe } from '../input/choice-styles';\nimport { useRecipe } from '../config/styles';\nimport { toneFillStyles } from '../utils/style/tone-styles';\nimport { inlineArrows, isRtl } from '../utils/dom/direction';\nimport { toggleSelection, type SelectionModes } from '../utils/data/selection';\nimport {\n checkStates,\n filterTree,\n flattenTree,\n indexTree,\n toggleChecked,\n useTreeExpansion,\n type CheckState,\n type TreeAccessors,\n type TreeMoveTarget,\n} from '../utils/data/tree';\nimport { createTypeahead } from '../utils/dom/typeahead';\nimport { mergeAttrs, mergePartProps, mergeProps, type PartProps } from '../utils/props';\nimport { ScrollArea, type ScrollAreaProps } from '../layout/ScrollArea';\nimport { itemStyles } from '../utils/style/item-styles';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { useVirtualizer } from '../utils/virtual/use-virtualizer';\nimport { defaultRangeExtractor } from '../utils/virtual/virtualizer';\nimport { disclosureStyles } from '../utils/style/transitions';\n\n/** 节点的渲染状态 */\nexport interface TreeItemRenderState {\n /** 层级,第一层为 0 */\n depth: number;\n /** 展开着 */\n expanded: boolean;\n /** 已选 */\n selected: boolean;\n /** 勾选状态(checkable 时) */\n checked: CheckState;\n /** 键盘所在的当前项 */\n active: boolean;\n}\n\n/** 一次移动:把 key 移到 target(交给 moveNode) */\nexport interface TreeMove<T> {\n /** 移动的节点的 key */\n key: string;\n /** 移动的节点 */\n node: T;\n /** 放到哪个节点下的第几位(按移走之后的同级算) */\n target: TreeMoveTarget;\n}\n\n/** 拖动时的落点:放在 key 这一项的前面、后面或里面 */\ninterface DropSpot {\n key: string;\n zone: 'before' | 'after' | 'inside';\n}\n\n/** 未声明的属性落到 div(role=\"tree\")上;aria-label 或 aria-labelledby 是树的名称 */\nexport interface TreeProps<T> extends PartProps<'div', 'role'> {\n /** 第一层的节点 */\n items: readonly T[];\n /** 节点的 key,整棵树里唯一 */\n getKey: (node: T) => string;\n /** 节点的文字:默认显示它,类型搜索也按它 */\n getLabel: (node: T) => string;\n /** 子节点;叶子或还没加载时返回 undefined / 空数组 */\n getChildren: (node: T) => readonly T[] | undefined;\n /** 有没有子节点(懒加载时子节点还没取回来也要能展开);不写时看 getChildren 是否非空 */\n hasChildren?: (node: T) => boolean;\n /** 展开一个还没有子节点的节点时调用:取回子节点并放进数据里;返回 Promise 时显示加载中 */\n loadChildren?: (node: T) => Promise<unknown> | void;\n /** 子节点加载失败(loadChildren 的 Promise 被拒绝):节点收回去,再展开会重试;不写时在控制台报错 */\n onLoadError?: (error: unknown, node: T) => void;\n /** 节点不可用:可以经过、展开,不能选中、勾选 */\n isDisabled?: (node: T) => boolean;\n /** 文字前的图标,可以按展开状态换(文件夹开 / 合) */\n getIcon?: (node: T, expanded: boolean) => IconData | undefined;\n /** 展开的节点:父级写 _expanded={keys} */\n _expanded?: string[];\n /** 选择方式;不写时不能选中 */\n selectionMode?: keyof SelectionModes;\n /** 选中的节点:父级写 _selected={keys} */\n _selected?: string[];\n /** 每项前显示勾选框,默认父子联动 */\n checkable?: boolean;\n /** 勾选父子不联动:每个节点各自勾选(权限树里“只给这一级”) */\n checkStrictly?: boolean;\n /** 勾上的节点(联动时含勾上的父节点与子孙):父级写 _checked={keys} */\n _checked?: string[];\n /** 正在取节点:还没有节点时显示骨架行,树带 aria-busy */\n loading?: boolean;\n /** 没有节点时显示的内容;默认是 Empty(文案取语言包) */\n empty?: VNodeChild;\n /** 每一层缩进多少(em),默认 1.25 */\n indent?: number;\n /** 每项的估计高度(px),默认 32;渲染后以实际高度为准 */\n estimateSize?: number;\n /**\n * 搜索过滤:字符串时按节点文字匹配(忽略大小写与重音,或 createUi 的 textMatcher),函数时自己判断。\n * 留下匹配的节点与它们的祖先并展开祖先,匹配的节点文字加粗;只看已加载的节点。清空后回到原来的展开状态\n */\n filter?: string | ((node: T) => boolean);\n /**\n * 拖动节点改变层级与顺序:放下(或 Alt + 方向键)时报告移动,用 moveNode 生成新数据交回 items;不写时不能拖。\n * 指针拖动只用鼠标、笔(触摸时照常滚动)\n */\n onMove?: (move: TreeMove<T>) => void;\n /** 能不能放到这里(如文件不能放进文件里);不写时都能放(放进自己和自己的子孙里除外) */\n canDrop?: (node: T, target: TreeMoveTarget) => boolean;\n /** 自定义文字部分的内容 */\n renderItem?: (node: T, state: TreeItemRenderState) => VNodeChild;\n /** 每一项的部件属性,可以按节点计算 */\n propsItem?:\n PartProps<'div', 'role' | 'id'> | ((node: T, state: TreeItemRenderState) => PartProps<'div'>);\n /** 每一行(虚拟滚动定位的容器,包着 treeitem)的部件属性 */\n propsRow?: PartProps<'div', 'role'>;\n /** 展开箭头的部件属性(只是外观,键盘与读屏走 treeitem) */\n propsToggle?: PartProps<'span', 'aria-hidden'>;\n /** 勾选框的部件属性(只是外观,状态在 treeitem 的 aria-checked 上) */\n propsCheckbox?: PartProps<'span', 'aria-hidden'>;\n /** 文字的部件属性 */\n propsLabel?: PartProps<'span'>;\n /** 默认空状态(Empty)的部件属性 */\n propsEmpty?: Partial<EmptyProps>;\n /** 加载中的骨架行的部件属性 */\n propsSkeleton?: SkeletonShapeProps;\n /** 外层滚动区域(ScrollArea)的部件属性:放进弹出层、弹性布局时给它 sx;树元素本身是它的视口 */\n propsScrollArea?: Partial<Omit<ScrollAreaProps, 'propsViewport'>>;\n}\n\n/** Tree 的样式:root、sizer、row、item、toggle、checkbox、label 等 */\nexport const treeStyles = css.create({\n // 树元素就是 ScrollArea 的视口(浮层滚动条);焦点与 aria-activedescendant 在它上面\n root: {\n position: 'relative',\n overscrollBehavior: 'contain',\n padding: '_xs',\n outlineStyle: 'none',\n },\n sizer: { position: 'relative', width: '_full' },\n skeleton: { display: 'block', height: '1em', marginBlock: '0.625em', marginInline: '_sm' },\n row: { position: 'absolute', top: 0, insetInline: 0, paddingBlock: '1px' },\n item: { gap: '_xs', minHeight: '_sizes.minTarget', paddingInlineStart: '_xs' },\n toggle: {\n display: 'grid',\n placeItems: 'center',\n flexShrink: 0,\n width: '1.5em',\n height: '1.5em',\n color: '_textMuted',\n },\n chevronOpen: { rotate: '90deg' },\n checkbox: { marginInlineEnd: '_xs' },\n checkMark: { width: '0.875em', height: '0.875em', color: '_accentContrast' },\n hidden: { visibility: 'hidden' },\n // 搜索时匹配的节点\n matched: { fontWeight: '_semibold' },\n // 拖动:被拖的那一项变淡;放进某一项里时它带品牌色的框;放在前后时画一条线\n dragging: { opacity: 0.5 },\n dropInside: {\n outlineStyle: 'solid',\n outlineWidth: '_borderWidths.sm',\n outlineColor: '_accent',\n outlineOffset: `calc(-1 * ${t.borderWidths.sm})`,\n backgroundColor: '_accentSoft',\n },\n dropLine: {\n position: 'absolute',\n insetInlineEnd: 0,\n height: '_borderWidths.sm',\n backgroundColor: '_accent',\n borderRadius: '_full',\n pointerEvents: 'none',\n },\n dropBefore: { top: `calc(-1 * ${t.borderWidths.xs})` },\n dropAfter: { bottom: `calc(-1 * ${t.borderWidths.xs})` },\n // 画线的那一项要作定位参照\n positioned: { position: 'relative' },\n});\n\n// 缩进与位置是任意值,用动态样式;单独一个 create,见 COMPONENTS.md §4\n/** Tree 的样式:indent(缩进)、y、height */\nexport const treeDynamicStyles = css.create({\n indent: (em: number) => ({ width: `${em}em`, flexShrink: 0 }),\n y: (px: number) => ({ transform: `translateY(${px}px)` }),\n height: (px: number) => ({ height: px }),\n width: (value: string) => ({ width: value }),\n // 落点线从这一层的缩进处开始\n lineStart: (em: number) => ({ insetInlineStart: `${em}em` }),\n});\n\n/** 加载中显示几行骨架 */\nconst SKELETON_ROWS = 4;\n\nconst ARIA_CHECKED: Record<CheckState, 'true' | 'false' | 'mixed'> = {\n checked: 'true',\n unchecked: 'false',\n indeterminate: 'mixed',\n};\n\n/** 树:可展开的层级列表,单选 / 多选、父子联动的勾选、懒加载、方向键导航、虚拟滚动 */\nexport const Tree = _component(\n <T,>({\n items,\n getKey,\n getLabel,\n getChildren,\n hasChildren,\n loadChildren,\n onLoadError,\n isDisabled,\n getIcon,\n _expanded: expanded = _bindable<string[]>([]),\n selectionMode,\n _selected: selected = _bindable<string[]>([]),\n checkable = false,\n checkStrictly = false,\n _checked: checked = _bindable<string[]>([]),\n loading = false,\n empty,\n indent = 1.25,\n estimateSize = 32,\n filter,\n onMove,\n canDrop,\n renderItem,\n propsItem,\n propsRow,\n propsToggle,\n propsCheckbox,\n propsLabel,\n propsEmpty,\n propsSkeleton,\n propsScrollArea,\n id,\n ...rest\n }: TreeProps<T>) => {\n const lang = useLang();\n // 骨架防闪烁:很快就取回来时不显示;aria-busy 按真实的 loading\n const indicator = useDelayedLoading(() => loading);\n const generatedId = useId();\n const prefix = () => id ?? generatedId;\n let root = _state.raw<HTMLElement | null>(null);\n let sizer = _state.raw<HTMLElement | null>(null);\n // 键盘所在的当前项;焦点在树上时才高亮\n let active = _state<string | undefined>(undefined);\n let focused = _state(false);\n const typeahead = createTypeahead();\n // 勾选框画成 Checkbox 的样子,跟着 styles.Choice 的定制\n const choice = useRecipe(choiceRecipe);\n\n const accessors = (): TreeAccessors<T> => ({\n getKey: (node) => getKey(node),\n getChildren,\n hasChildren,\n });\n\n // 搜索过滤:匹配的节点与祖先;为 null 时不过滤\n const textMatcher = useTextMatcher();\n const filtering = _derived.by(() => {\n const query = typeof filter === 'string' ? filter.trim() : filter;\n if (!query) return null;\n const match =\n typeof query === 'string' ? (node: T) => textMatcher()(getLabel(node), query) : query;\n return filterTree(items, accessors(), match);\n });\n // 过滤时的展开状态单独记:一开始展开匹配项的祖先,可以再收起;清空过滤后回到原来的 expanded\n let filterExpanded = _state<string[]>([]);\n watch(\n () => filtering,\n (result) => (filterExpanded = result ? [...result.expand] : []),\n { immediate: true },\n );\n const shownExpanded = () => (filtering ? filterExpanded : expanded);\n\n const expansion = useTreeExpansion<T>({\n expanded: shownExpanded,\n setExpanded: (keys) => (filtering ? (filterExpanded = keys) : (expanded = keys)),\n getChildren: (node) => getChildren(node),\n loadChildren: (node) => loadChildren?.(node),\n // 没给 onLoadError 时交给 useTreeExpansion 在控制台报错\n onLoadError: _untrack(onLoadError) && ((error, node) => onLoadError?.(error, node)),\n });\n\n const rows = _derived.by(() =>\n flattenTree(items, accessors(), new Set(shownExpanded()), { include: filtering?.include }),\n );\n const rowOf = _derived.by(() => new Map(rows.map((row, index) => [row.key, index])));\n // 勾选联动要看到折叠着的节点:只在联动勾选时建整棵树的索引\n const index = _derived.by(() =>\n checkable && !checkStrictly ? indexTree(items, accessors()) : null,\n );\n const states = _derived.by(() => (index ? checkStates(index, checked) : null));\n const checkedSet = _derived.by(() => new Set(checked));\n const selectedSet = _derived.by(() => new Set(selected));\n\n /** 当前项的行号;没有时 -1 */\n const activeRow = () => (active === undefined ? -1 : (rowOf.get(active) ?? -1));\n\n const virtual = useVirtualizer(() => {\n const current = rows;\n // 读一下当前项:它变了要重新算渲染范围(当前项总要渲染,aria-activedescendant 才指得到)\n const focusedRow = activeRow();\n // 先读出来:每一项都要调用一次估计高度,不要每次都经过 props 的响应式读取\n const size = estimateSize;\n return {\n count: current.length,\n scrollElement: root,\n list: sizer,\n estimateSize: () => size,\n getItemKey: (position: number) => current[position]!.key,\n overscan: 6,\n rangeExtractor: (range) => {\n const indices = defaultRangeExtractor(range);\n if (focusedRow >= 0 && !indices.includes(focusedRow)) {\n indices.push(focusedRow);\n indices.sort((a, b) => a - b);\n }\n return indices;\n },\n };\n });\n\n watch(\n () => active,\n () => {\n const position = activeRow();\n if (position >= 0) virtual.scrollToIndex(position, { align: 'auto' });\n },\n { flush: 'post' },\n );\n\n // 当前项所在的父节点被收起:当前项移到还看得见的最近祖先\n watch(\n () => rows,\n (next, previous) => {\n if (active === undefined || rowOf.has(active)) return;\n let parent = previous.find((row) => row.key === active)?.parent;\n while (parent !== undefined && !rowOf.has(parent)) {\n parent = previous.find((row) => row.key === parent)?.parent;\n }\n active = parent ?? next[0]?.key;\n },\n );\n\n const disabledAt = (position: number) => {\n const row = rows[position];\n return !row || (isDisabled?.(row.node) ?? false);\n };\n\n function select(position: number) {\n const row = rows[position];\n if (!row || !selectionMode || disabledAt(position)) return;\n selected = [...toggleSelection(selected, row.key, { mode: selectionMode })];\n }\n\n function check(position: number) {\n const row = rows[position];\n if (!row || !checkable || disabledAt(position)) return;\n checked = index\n ? toggleChecked(index, checked, row.key)\n : [...toggleSelection(checked, row.key, { mode: 'multiple' })];\n }\n\n function toggle(position: number) {\n const row = rows[position];\n if (row?.expandable)\n void expansion.setOpen(row.node, row.key, !expansion.isExpanded(row.key));\n }\n\n // —— 移动节点(onMove):指针拖动,或 Alt + 方向键 ——\n let dragging = _state<string | undefined>(undefined);\n let drop = _state.raw<DropSpot | null>(null);\n let expandTimer: ReturnType<typeof setTimeout> | undefined;\n let stopDrag: (() => void) | undefined;\n onScopeDispose(() => {\n clearTimeout(expandTimer);\n stopDrag?.();\n });\n\n const rowByKey = (key: string | undefined) =>\n key === undefined ? undefined : rows[rowOf.get(key) ?? -1];\n\n /** key 是不是 ancestor 自己或它的子孙(看得见的行里,祖先总是看得见的) */\n function isWithin(key: string, ancestor: string) {\n for (let at: string | undefined = key; at !== undefined; at = rowByKey(at)?.parent) {\n if (at === ancestor) return true;\n }\n return false;\n }\n\n /** 落点换算成移动的目标(按移走之后的同级算);放不下时 null */\n function targetOf(key: string, spot: DropSpot): TreeMoveTarget | null {\n const moving = rowByKey(key);\n const row = rowByKey(spot.key);\n if (!moving || !row || isWithin(spot.key, key)) return null;\n let target: TreeMoveTarget;\n if (spot.zone === 'inside') target = { parent: row.key, index: Number.MAX_SAFE_INTEGER };\n else {\n const offset = spot.zone === 'before' ? row.position - 1 : row.position;\n // 同一层里从前面移过来:移走之后,后面的都往前挪了一位\n const shift = moving.parent === row.parent && moving.position <= offset ? 1 : 0;\n target = { parent: row.parent, index: offset - shift };\n }\n return canDrop && !canDrop(moving.node, target) ? null : target;\n }\n\n /** 报告移动,并告诉读屏移到了哪里 */\n function emitMove(key: string, target: TreeMoveTarget) {\n const row = rowByKey(key);\n if (!row || !onMove) return;\n const parent = rowByKey(target.parent);\n // 移走之后的同级个数:同一层里移动时要去掉自己\n const count =\n (parent ? (getChildren(parent.node)?.length ?? 0) : items.length) -\n (row.parent === target.parent ? 1 : 0);\n onMove({ key, node: row.node, target });\n announce(\n lang.treeMoved(\n getLabel(row.node),\n parent && getLabel(parent.node),\n Math.min(target.index, count) + 1,\n ),\n );\n }\n\n /** 指针下的落点:一项的上四分之一放在它前面,下四分之一放在后面,中间放进它里面 */\n function spotAt(clientX: number, clientY: number): DropSpot | null {\n const element = document\n .elementFromPoint(clientX, clientY)\n ?.closest<HTMLElement>('[data-index]');\n if (!element || !root?.contains(element)) return null;\n const row = rows[Number(element.dataset.index)];\n if (!row) return null;\n const rect = element.getBoundingClientRect();\n const ratio = (clientY - rect.top) / rect.height;\n return { key: row.key, zone: ratio < 0.25 ? 'before' : ratio > 0.75 ? 'after' : 'inside' };\n }\n\n /** 拖到靠近上下边缘时滚动 */\n function autoScroll(clientY: number) {\n if (!root) return;\n const rect = root.getBoundingClientRect();\n if (clientY < rect.top + 32) root.scrollTop -= 12;\n else if (clientY > rect.bottom - 32) root.scrollTop += 12;\n }\n\n /** 拖到收起的节点里停一会儿:展开它,好放到更深的地方 */\n function scheduleExpand(spot: DropSpot | null) {\n clearTimeout(expandTimer);\n const row = spot?.zone === 'inside' ? rowByKey(spot.key) : undefined;\n if (!row?.expandable || expansion.isExpanded(row.key)) return;\n expandTimer = setTimeout(() => void expansion.setOpen(row.node, row.key, true), 600);\n }\n\n function onItemPointerdown(event: PointerEvent, key: string) {\n // 焦点留在树上\n event.preventDefault();\n // 触摸时照常滚动,不拖\n if (!onMove || event.pointerType === 'touch' || !root) return;\n stopDrag = startMove(event, {\n threshold: 4,\n // 虚拟滚动会换掉行元素:捕获在不动的树上\n captureTarget: root,\n onMove: ({ clientX, clientY }) => {\n dragging = key;\n // 先按当前的位置算落点,再滚动:滚动后指针下面换成了别的项\n const spot = spotAt(clientX, clientY);\n autoScroll(clientY);\n const next = spot && targetOf(key, spot) ? spot : null;\n if (next?.key === drop?.key && next?.zone === drop?.zone) return;\n drop = next;\n scheduleExpand(next);\n },\n onEnd: ({ moved, cancelled }) => {\n const spot = drop;\n dragging = undefined;\n drop = null;\n stopDrag = undefined;\n clearTimeout(expandTimer);\n if (!moved || cancelled || !spot) return;\n const target = targetOf(key, spot);\n if (target) emitMove(key, target);\n },\n });\n }\n\n /** Alt + ↑↓ 在同级里移动,Alt + → 放进上一个同级的最后,Alt + ← 移到父节点后面(从右到左时左右对调) */\n function moveByKey(event: KeyboardEvent): boolean {\n const row = rows[activeRow()];\n if (!row) return false;\n const { forward, backward } = inlineArrows(!!root && isRtl(root));\n let target: TreeMoveTarget | undefined;\n switch (event.key) {\n case 'ArrowUp':\n if (row.position > 1) target = { parent: row.parent, index: row.position - 2 };\n break;\n case 'ArrowDown':\n if (row.position < row.setSize) target = { parent: row.parent, index: row.position };\n break;\n case forward: {\n const previous = rows.find(\n (item) => item.parent === row.parent && item.position === row.position - 1,\n );\n if (!previous) break;\n target = { parent: previous.key, index: Number.MAX_SAFE_INTEGER };\n // 展开新的父节点:移过去之后还看得见\n void expansion.setOpen(previous.node, previous.key, true);\n break;\n }\n case backward: {\n const parent = rowByKey(row.parent);\n if (parent) target = { parent: parent.parent, index: parent.position };\n break;\n }\n default:\n return false;\n }\n if (target && (!canDrop || canDrop(row.node, target))) emitMove(row.key, target);\n return true;\n }\n\n function onKeydown(event: KeyboardEvent) {\n if (event.altKey && onMove && !event.ctrlKey && !event.metaKey) {\n if (moveByKey(event)) event.preventDefault();\n return;\n }\n if (event.altKey || event.ctrlKey || event.metaKey || rows.length === 0) return;\n const position = Math.max(activeRow(), 0);\n const row = rows[position]!;\n const open = row.expandable && expansion.isExpanded(row.key);\n const { forward, backward } = inlineArrows(!!root && isRtl(root));\n const go = (target: number) => (active = rows[target]?.key ?? active);\n switch (event.key) {\n case 'ArrowDown':\n go(Math.min(position + 1, rows.length - 1));\n break;\n case 'ArrowUp':\n go(Math.max(position - 1, 0));\n break;\n case 'Home':\n go(0);\n break;\n case 'End':\n go(rows.length - 1);\n break;\n case forward:\n if (!row.expandable) break;\n if (!open) void expansion.setOpen(row.node, row.key, true);\n // 已展开:进入第一个子节点(子节点还没加载出来时不动)\n else if (rows[position + 1]?.parent === row.key) go(position + 1);\n break;\n case backward:\n if (open) void expansion.setOpen(row.node, row.key, false);\n else if (row.parent !== undefined) active = row.parent;\n break;\n case 'Enter':\n if (selectionMode) select(position);\n else toggle(position);\n break;\n case ' ':\n if (checkable) check(position);\n else select(position);\n break;\n default: {\n const found = typeahead.next(\n event.key,\n rows.map((item) => getLabel(item.node)),\n activeRow(),\n );\n if (found < 0) return;\n go(found);\n }\n }\n event.preventDefault();\n }\n\n function onFocus() {\n focused = true;\n if (active !== undefined && rowOf.has(active)) return;\n // 第一次进入:落在第一个已选的可见节点上,没有时落在第一项\n active = rows.find((row) => selectedSet.has(row.key))?.key ?? rows[0]?.key;\n }\n\n function renderRow(position: number) {\n const row = rows[position]!;\n const open = row.expandable && expansion.isExpanded(row.key);\n const disabled = disabledAt(position);\n const state: TreeItemRenderState = {\n depth: row.depth,\n expanded: open,\n selected: selectedSet.has(row.key),\n checked: states\n ? (states.get(row.key) ?? 'unchecked')\n : checkedSet.has(row.key)\n ? 'checked'\n : 'unchecked',\n active: active === row.key,\n };\n const own = typeof propsItem === 'function' ? propsItem(row.node, state) : propsItem;\n const icon = getIcon?.(row.node, open);\n const loading = expansion.isLoading(row.key);\n const marked = state.checked !== 'unchecked';\n const box = choice();\n const dropZone = drop?.key === row.key ? drop.zone : undefined;\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n itemStyles.row,\n itemStyles.hoverable,\n treeStyles.item,\n focused && state.active && itemStyles.highlighted,\n state.selected && itemStyles.current,\n disabled && itemStyles.disabled,\n dragging === row.key && treeStyles.dragging,\n dropZone === 'inside' && treeStyles.dropInside,\n dropZone && dropZone !== 'inside' && treeStyles.positioned,\n ],\n },\n own,\n {\n id: `${prefix()}-${position}`,\n role: 'treeitem',\n 'aria-level': row.depth + 1,\n 'aria-setsize': row.setSize,\n 'aria-posinset': row.position,\n 'aria-expanded': row.expandable ? open : undefined,\n 'aria-selected': selectionMode ? state.selected : undefined,\n 'aria-checked': checkable ? ARIA_CHECKED[state.checked] : undefined,\n 'aria-disabled': disabled || undefined,\n 'aria-busy': loading || undefined,\n onPointerdown: (event: PointerEvent) => onItemPointerdown(event, row.key),\n onClick: () => {\n active = row.key;\n root?.focus({ preventScroll: true });\n if (selectionMode) select(position);\n else if (checkable) check(position);\n else toggle(position);\n },\n },\n )}\n data-state={state.selected ? 'selected' : undefined}\n data-active={state.active || undefined}\n data-disabled={disabled || undefined}\n >\n {row.depth > 0 && <span {...css.attrs(treeDynamicStyles.indent(row.depth * indent))} />}\n <span\n {...mergeAttrs<'span'>({ sx: treeStyles.toggle }, propsToggle, {\n 'aria-hidden': true,\n onClick: (event: MouseEvent) => {\n if (!row.expandable) return;\n event.stopPropagation();\n active = row.key;\n root?.focus({ preventScroll: true });\n toggle(position);\n },\n })}\n >\n {loading ? (\n <Spinner />\n ) : (\n row.expandable && (\n <Icon\n icon={ChevronRight}\n flipInRtl\n sx={[disclosureStyles.icon, open && treeStyles.chevronOpen]}\n />\n )\n )}\n </span>\n {checkable && (\n <span\n {...mergeAttrs<'span'>(\n // 勾选框的实底色取色调变量(同 Checkbox 的 choiceParts)\n { sx: [box.control.sx, toneFillStyles.accent, treeStyles.checkbox] },\n propsCheckbox,\n {\n 'aria-hidden': true,\n onClick: (event: MouseEvent) => {\n event.stopPropagation();\n active = row.key;\n root?.focus({ preventScroll: true });\n check(position);\n },\n },\n )}\n >\n <span\n {...css.attrs(\n box.input.sx,\n focusRingStyles.tight,\n checkboxStyles.box,\n marked && choiceInputStyles.checked,\n )}\n />\n <Icon\n icon={state.checked === 'indeterminate' ? Minus : Check}\n strokeWidth={3}\n sx={[box.indicator.sx, treeStyles.checkMark, !marked && treeStyles.hidden]}\n />\n </span>\n )}\n {icon && <Icon icon={icon} />}\n <span\n {...mergeAttrs<'span'>(\n { sx: [itemStyles.label, filtering?.matched.has(row.key) && treeStyles.matched] },\n propsLabel,\n )}\n >\n {renderItem ? renderItem(row.node, state) : getLabel(row.node)}\n </span>\n {dropZone && dropZone !== 'inside' && (\n <span\n aria-hidden=\"true\"\n {...css.attrs(\n treeStyles.dropLine,\n dropZone === 'before' ? treeStyles.dropBefore : treeStyles.dropAfter,\n treeDynamicStyles.lineStart(row.depth * indent + 1.75),\n )}\n />\n )}\n </div>\n );\n }\n\n /** 没有节点时:加载中是几行骨架,否则是空状态 */\n function renderPlaceholder() {\n if (loading) {\n if (!indicator.value) return null;\n return Array.from({ length: SKELETON_ROWS }, (_, row) => (\n <Skeleton\n key={row}\n {...mergePartProps<SkeletonProps>(\n {\n sx: [treeStyles.skeleton, treeDynamicStyles.width(`${85 - row * 15}%`)],\n delay: row * SHIMMER_STAGGER,\n },\n propsSkeleton,\n )}\n />\n ));\n }\n return (\n empty ?? (\n <Empty\n {...mergePartProps<EmptyProps>(\n {\n size: 'sm',\n icon: false,\n description: filtering ? lang.treeNoMatch : lang.treeEmpty,\n },\n propsEmpty,\n )}\n />\n )\n );\n }\n\n return () => {\n const position = activeRow();\n return (\n <ScrollArea\n {...mergePartProps<ScrollAreaProps>({}, propsScrollArea)}\n focusable={false}\n propsViewport={\n mergeProps<'div'>({ sx: [treeStyles.root, focusRingStyles.visible] }, rest, {\n ref: _toRef(root),\n id: prefix(),\n role: 'tree',\n tabindex: rows.length > 0 ? 0 : -1,\n 'aria-multiselectable': selectionMode === 'multiple' || undefined,\n 'aria-activedescendant': position >= 0 ? `${prefix()}-${position}` : undefined,\n 'aria-busy': loading || undefined,\n onFocus,\n onBlur: () => (focused = false),\n onKeydown,\n }) as PartProps<'div'>\n }\n >\n {rows.length === 0 && renderPlaceholder()}\n <div\n ref={_toRef(sizer)}\n role=\"presentation\"\n {...css.attrs(treeStyles.sizer, treeDynamicStyles.height(virtual.total))}\n >\n {virtual.items.map((item) => (\n <div\n key={item.key}\n {...mergeAttrs<'div'>({ sx: treeStyles.row }, propsRow, {\n ref: virtual.measure,\n role: 'presentation',\n sx: treeDynamicStyles.y(item.start),\n })}\n data-index={item.index}\n >\n {renderRow(item.index)}\n </div>\n ))}\n </div>\n </ScrollArea>\n );\n };\n },\n { name: 'Tree' },\n);\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { useLang } from "../config/context.js";
2
- import { elementProps, mergeAttrs, mergePartProps, mergeProps as mergeProps$1 } from "../utils/props.js";
2
+ import { elementProps, mergeAttrs, mergePartProps, mergeProps } from "../utils/props.js";
3
3
  import { focusRingStyles } from "../utils/style/styles.js";
4
4
  import { useDelayedLoading } from "../utils/motion/delayed-loading.js";
5
5
  import { ScrollArea } from "../layout/ScrollArea.js";
@@ -7,8 +7,8 @@ import "../utils/style/shimmer.js";
7
7
  import { Skeleton } from "../feedback/Skeleton.js";
8
8
  import { Progress } from "../feedback/Progress.js";
9
9
  import { useVirtualizer } from "../utils/virtual/use-virtualizer.js";
10
- import { Fragment, createVNode, isVNode, mergeProps, shallowRef, watch } from "vue";
11
- import { _component, childrenProp, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
10
+ import { Fragment, createVNode, isVNode, shallowRef, watch } from "vue";
11
+ import { _component, childrenProp, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
12
12
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
13
13
  //#region src/display/VirtualList.tsx
14
14
  /** 跟着谁滚动 */
@@ -106,13 +106,13 @@ var VirtualList = /*#__PURE__*/ _component((_props, _ctx) => {
106
106
  return () => {
107
107
  const isContainer = scroll.value === "container";
108
108
  const hasItems = items.value.length > 0;
109
- const props = mergeProps$1({ sx: [virtualListStyles.root, isContainer && [virtualListStyles.container, focusRingStyles.visible]] }, rest, {
109
+ const props = mergeProps({ sx: [virtualListStyles.root, isContainer && [virtualListStyles.container, focusRingStyles.visible]] }, rest, {
110
110
  ref: root,
111
111
  role: hasItems ? "list" : "group",
112
112
  "aria-busy": loading.value || void 0,
113
113
  tabindex: isContainer ? 0 : void 0
114
114
  });
115
- const content = createVNode(Fragment, null, [indicator.value && hasItems && createVNode("div", mergeProps({ "aria-hidden": "true" }, css.attrs(virtualListStyles.progress)), [createVNode(Progress, {
115
+ const content = createVNode(Fragment, null, [indicator.value && hasItems && createVNode("div", mergeJsxProps({ "aria-hidden": "true" }, css.attrs(virtualListStyles.progress)), [createVNode(Progress, {
116
116
  "size": "xs",
117
117
  "aria-label": lang.loading
118
118
  }, null)]), hasItems ? createVNode("div", mergeAttrs({ sx: virtualListStyles.list }, propsList.value, {
@@ -122,14 +122,14 @@ var VirtualList = /*#__PURE__*/ _component((_props, _ctx) => {
122
122
  }), [virtual.items.map((item) => {
123
123
  const data = items.value[item.index];
124
124
  const own = typeof propsItem.value === "function" ? propsItem.value(data, item.index) : propsItem.value;
125
- return createVNode("div", mergeProps({ "key": item.key }, mergeAttrs({ sx: [virtualListStyles.item, horizontal.value ? virtualListStyles.itemHorizontal : virtualListStyles.itemVertical] }, own, {
125
+ return createVNode("div", mergeJsxProps({ "key": item.key }, mergeAttrs({ sx: [virtualListStyles.item, horizontal.value ? virtualListStyles.itemHorizontal : virtualListStyles.itemVertical] }, own, {
126
126
  sx: horizontal.value ? css.bind(virtualListSizeStyles.x, () => [item.start]) : css.bind(virtualListSizeStyles.y, () => [item.start]),
127
127
  ref: virtual.measure,
128
128
  role: "listitem",
129
129
  "aria-setsize": items.value.length,
130
130
  "aria-posinset": item.index + 1
131
131
  }), { "data-index": item.index }), [children.value(data, item.index)]);
132
- })]) : loading.value ? indicator.value && Array.from({ length: SKELETON_ROWS }, (_, index) => createVNode("div", mergeProps({
132
+ })]) : loading.value ? indicator.value && Array.from({ length: SKELETON_ROWS }, (_, index) => createVNode("div", mergeJsxProps({
133
133
  "key": index,
134
134
  "aria-hidden": "true"
135
135
  }, css.attrs(virtualListStyles.skeletonRow)), [createVNode(Skeleton, mergePartProps({
@@ -1 +1 @@
1
- {"version":3,"file":"VirtualList.js","names":["_isVNode","_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_vue_shallowRef","mergeProps","_createVNode","_Fragment","_mergeProps"],"sources":["../../src/display/VirtualList.tsx"],"sourcesContent":["/**\n * 虚拟列表:只渲染可见范围内的项,上万条数据也流畅。行高可以不固定,渲染后自动测量(COMPONENTS.md §10.7)。\n *\n * <VirtualList items={users} getKey={(user) => user.id} estimateSize={48} sx={styles.list}>\n * {(user) => <UserRow user={user} />}\n * </VirtualList>\n *\n * 默认组件自己是滚动容器,高度由使用方给(sx、class 或 style);scroll=\"window\" 时随页面滚动。\n * 读屏:role=\"list\",每项带 aria-setsize / aria-posinset,未渲染的项也算在总数里;没有数据时是 role=\"group\"(空状态、骨架不是列表项)。\n * loading:没有数据时显示骨架行(按 estimateSize 的高度),已有数据(刷新、加载更多)时顶部显示进度条;带 aria-busy。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { watch, type VNodeChild } from 'vue';\nimport { useDelayedLoading } from '../utils/motion/delayed-loading';\nimport { useLang } from '../config/context';\nimport { Progress } from '../feedback/Progress';\nimport { Skeleton, type SkeletonProps, type SkeletonShapeProps } from '../feedback/Skeleton';\nimport { SHIMMER_STAGGER } from '../utils/style/shimmer';\nimport {\n elementProps,\n mergeAttrs,\n mergePartProps,\n mergeProps,\n type PartProps,\n} from '../utils/props';\nimport { ScrollArea } from '../layout/ScrollArea';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { useVirtualizer } from '../utils/virtual/use-virtualizer';\nimport type { VirtualScrollOptions, VisibleRange } from '../utils/virtual/virtualizer';\n\n/** 跟着谁滚动 */\nexport interface VirtualListScrolls {\n /** 组件自己是滚动容器(默认):要给它高度(横向时给宽度) */\n container: unknown;\n /** 随页面(window)滚动:列表按总高度撑开,放在页面的普通流里 */\n window: unknown;\n}\n\n/** handle 拿到的方法 */\nexport interface VirtualListHandle {\n /** 滚动到第 index 项;align 默认 auto(已经完整可见就不动) */\n scrollToIndex: (index: number, options?: VirtualScrollOptions) => void;\n /** 滚动到相对列表开头的位置(px) */\n scrollToOffset: (offset: number, options?: VirtualScrollOptions) => void;\n}\n\n/** 受管属性:角色与可聚焦由组件决定 */\nexport type VirtualListManaged = 'role' | 'tabindex';\n\n/** 未声明的属性落到外层元素(滚动容器)上;aria-label 写在这里就是列表的名称 */\nexport interface VirtualListProps<T> extends PartProps<'div', VirtualListManaged> {\n /** 数据 */\n items: readonly T[];\n /** 渲染一项:`{(item, index) => …}` */\n children: (item: T, index: number) => VNodeChild;\n /** 每项的 key,默认用序号;数据会重排、增删时一定要给,测量结果与组件状态才对得上 */\n getKey?: (item: T, index: number) => PropertyKey;\n /** 每项的估计大小(px),数字或按项计算;渲染后以实际大小为准,默认 40 */\n estimateSize?: number | ((item: T, index: number) => number);\n /** 可见范围前后各多渲染几项,默认 4 */\n overscan?: number;\n /** 跟着谁滚动,默认 container */\n scroll?: keyof VirtualListScrolls;\n /** 横向排列与滚动 */\n horizontal?: boolean;\n /** 没有数据时显示的内容 */\n empty?: VNodeChild;\n /** 加载中:没有数据时显示骨架行,已有数据时顶部显示进度条 */\n loading?: boolean;\n /** 加载中占位行的部件属性 */\n propsSkeleton?: SkeletonShapeProps;\n /** 拿到滚动方法:`handle={(list) => (listHandle = list)}` */\n handle?: (handle: VirtualListHandle) => void;\n /** 可见范围变化(不含 overscan):接近末尾时加载更多 */\n onRangeChange?: (range: VisibleRange) => void;\n /** 列表层(撑开总高度、role=\"list\" 的项都在它里面)的部件属性 */\n propsList?: PartProps<'div', 'role'>;\n /**\n * 每一项外层(role=\"listitem\")的部件属性;可以按项计算:`(item, index) => ({ class: … })`。\n * 位置、序号与无障碍属性由组件管理\n */\n propsItem?: ItemProps | ((item: T, index: number) => ItemProps);\n}\n\n/** 项外层可以定制的属性 */\ntype ItemProps = PartProps<'div', 'role' | 'aria-setsize' | 'aria-posinset'>;\n\n/** 加载中显示几行骨架 */\nconst SKELETON_ROWS = 5;\n\n/** VirtualList 的样式:root、container、list、item、itemVertical、itemHorizontal 等 */\nexport const virtualListStyles = css.create({\n // 自己调整滚动位置(见 virtualizer.ts),不要浏览器再按锚点调整一次\n root: { overflowAnchor: 'none' },\n // 容器模式:列表元素是 ScrollArea 的视口(浮层滚动条)\n container: { overscrollBehavior: 'contain' },\n list: { position: 'relative', overflowAnchor: 'none' },\n item: { position: 'absolute', top: 0, left: 0, overflowAnchor: 'none' },\n itemVertical: { width: '_full' },\n itemHorizontal: { height: '_full' },\n // 刷新中的进度条贴在可见区域顶部\n progress: { position: 'sticky', top: 0, zIndex: 1, height: 0 },\n skeletonRow: { paddingBlock: '_xs' },\n skeleton: { display: 'block', width: '_full' },\n});\n\n// 总大小与位置是任意值,用动态样式(编译为 CSS 变量);单独一个 create,见 COMPONENTS.md §4\n/** VirtualList 的样式:height、width、y、x、skeleton */\nexport const virtualListSizeStyles = css.create({\n height: (px: number) => ({ height: px }),\n width: (px: number) => ({ width: px, height: '_full' }),\n y: (px: number) => ({ transform: `translateY(${px}px)` }),\n x: (px: number) => ({ transform: `translateX(${px}px)` }),\n // 骨架行比一项略矮:上下留出间隔\n skeleton: (px: number) => ({ height: Math.max(8, px - 8) }),\n});\n\n/** 虚拟列表:只渲染可见范围内的项,行高渲染后自动测量 */\nexport const VirtualList = _component(\n <T,>({\n items,\n children,\n getKey,\n estimateSize = 40,\n overscan = 4,\n scroll = 'container',\n horizontal = false,\n empty,\n loading = false,\n propsSkeleton,\n handle,\n onRangeChange,\n propsList,\n propsItem,\n ...rest\n }: VirtualListProps<T>) => {\n const lang = useLang();\n // 骨架、进度条防闪烁;aria-busy 按真实的 loading\n const indicator = useDelayedLoading(() => loading);\n let root = _state.raw<HTMLElement | null>(null);\n let list = _state.raw<HTMLElement | null>(null);\n const virtual = useVirtualizer(() => {\n const data = items;\n const estimate = estimateSize;\n const keyOf = getKey;\n return {\n count: data.length,\n overscan,\n horizontal,\n scrollElement: scroll === 'window' ? window : root,\n list,\n estimateSize: (index: number) =>\n typeof estimate === 'number' ? estimate : estimate(data[index]!, index),\n getItemKey: keyOf ? (index: number) => keyOf(data[index]!, index) : undefined,\n onRangeChange,\n };\n });\n\n // 挂载之后才交出 handle:使用方在回调里立即滚动(恢复上次的位置)也能生效。\n // handle 不放进监听源:父级写的箭头函数每次渲染都是新的,不该因此重新交出\n const api: VirtualListHandle = {\n scrollToIndex: virtual.scrollToIndex,\n scrollToOffset: virtual.scrollToOffset,\n };\n watch(\n () => root,\n (element) => {\n if (element) handle?.(api);\n },\n { flush: 'post' },\n );\n\n return () => {\n const isContainer = scroll === 'container';\n const hasItems = items.length > 0;\n const props = mergeProps<'div'>(\n {\n sx: [\n virtualListStyles.root,\n isContainer && [virtualListStyles.container, focusRingStyles.visible],\n ],\n },\n rest,\n {\n ref: _toRef(root),\n // 没有数据(空状态、首次加载的骨架)时不是列表;仍给 group 角色,写在外层的 aria-label 才有效\n role: hasItems ? 'list' : 'group',\n 'aria-busy': loading || undefined,\n // 容器模式下可以用键盘滚动\n tabindex: isContainer ? 0 : undefined,\n },\n );\n const content = (\n <>\n {indicator.value && hasItems && (\n <div aria-hidden=\"true\" {...css.attrs(virtualListStyles.progress)}>\n <Progress size=\"xs\" aria-label={lang.loading} />\n </div>\n )}\n {hasItems ? (\n <div\n {...mergeAttrs<'div'>({ sx: virtualListStyles.list }, propsList, {\n sx: horizontal\n ? virtualListSizeStyles.width(virtual.total)\n : virtualListSizeStyles.height(virtual.total),\n ref: _toRef(list),\n role: 'presentation',\n })}\n >\n {virtual.items.map((item) => {\n const data = items[item.index]!;\n const own =\n typeof propsItem === 'function' ? propsItem(data, item.index) : propsItem;\n return (\n <div\n key={item.key}\n {...mergeAttrs<'div'>(\n {\n sx: [\n virtualListStyles.item,\n horizontal\n ? virtualListStyles.itemHorizontal\n : virtualListStyles.itemVertical,\n ],\n },\n own,\n {\n sx: horizontal\n ? virtualListSizeStyles.x(item.start)\n : virtualListSizeStyles.y(item.start),\n ref: virtual.measure,\n role: 'listitem',\n 'aria-setsize': items.length,\n 'aria-posinset': item.index + 1,\n },\n )}\n data-index={item.index}\n >\n {children(data, item.index)}\n </div>\n );\n })}\n </div>\n ) : loading ? (\n indicator.value &&\n Array.from({ length: SKELETON_ROWS }, (_, index) => (\n <div key={index} aria-hidden=\"true\" {...css.attrs(virtualListStyles.skeletonRow)}>\n <Skeleton\n {...mergePartProps<SkeletonProps>(\n {\n sx: [\n virtualListStyles.skeleton,\n virtualListSizeStyles.skeleton(\n typeof estimateSize === 'number' ? estimateSize : 40,\n ),\n ],\n delay: index * SHIMMER_STAGGER,\n },\n propsSkeleton,\n )}\n />\n </div>\n ))\n ) : (\n empty\n )}\n </>\n );\n // 容器模式:列表元素就是 ScrollArea 的视口,滚动条是浮层的;跟着页面滚动时就是普通的 div\n return isContainer ? (\n <ScrollArea\n axis={horizontal ? 'x' : 'y'}\n focusable={false}\n propsViewport={props as PartProps<'div'>}\n >\n {content}\n </ScrollArea>\n ) : (\n <div {...elementProps(props)}>{content}</div>\n );\n };\n },\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;AAqFA,SAAA,QAAA,GAAA;CAAA,OAAA,OAAA,MAAA,cAAA,OAAA,UAAA,SAAA,KAAA,CAAA,MAAA,qBAAA,CAAAA,QAAA,CAAA;AAAA;;AAIA,IAAM,gBAAgB;;AAGtB,IAAa,oBAAoB,IAAI,OAAO;CAE1C,MAAM,EAAE,gBAAgB,OAAO;CAE/B,WAAW,EAAE,oBAAoB,UAAU;CAC3C,MAAM;EAAE,UAAU;EAAY,gBAAgB;CAAO;CACrD,MAAM;EAAE,UAAU;EAAY,KAAK;EAAG,MAAM;EAAG,gBAAgB;CAAO;CACtE,cAAc,EAAE,OAAO,QAAQ;CAC/B,gBAAgB,EAAE,QAAQ,QAAQ;CAElC,UAAU;EAAE,UAAU;EAAU,KAAK;EAAG,QAAQ;EAAG,QAAQ;CAAE;CAC7D,aAAa,EAAE,cAAc,MAAM;CACnC,UAAU;EAAE,SAAS;EAAS,OAAO;CAAQ;AAC/C,CAAC;;AAID,IAAa,wBAAwB,IAAI,OAAO;CAC9C,SAAS,QAAgB,EAAE,QAAQ,GAAG;CACtC,QAAQ,QAAgB;EAAE,OAAO;EAAI,QAAQ;CAAQ;CACrD,IAAI,QAAgB,EAAE,WAAW,cAAc,GAAE,KAAM;CACvD,IAAI,QAAgB,EAAE,WAAW,cAAc,GAAE,KAAM;CAEvD,WAAW,QAAgB,EAAE,QAAQ,KAAK,IAAI,GAAG,KAAK,CAAC,EAAE;AAC3D,CAAC;;AAGD,IAAa,cAAc,0BACzB,QAAA,SAgB2B;CAAA,MAAA,QAAAC,aAAA,QAAA,OAAA;CAAA,MAAA,WAAAC,aAAA,MAAA;CAAA,MAAA,SAAAD,aAAA,QAAA,QAAA;CAAA,MAAA,eAAAA,aAAA,QAAA,gBAZV,EAAE;CAAA,MAAA,WAAAA,aAAA,QAAA,YACN,CAAC;CAAA,MAAA,SAAAA,aAAA,QAAA,UACH,WAAW;CAAA,MAAA,aAAAA,aAAA,QAAA,cACP,KAAK;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,UAAAA,aAAA,QAAA,WAER,KAAK;CAAA,MAAA,gBAAAA,aAAA,QAAA,eAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,gBAAAA,aAAA,QAAA,eAAA;CAAA,MAAA,YAAAA,aAAA,QAAA,WAAA;CAAA,MAAA,YAAAA,aAAA,QAAA,WAAA;CAAA,MAMZ,OAAIE,UAAA,QAAA,MAAA,KAAA;CAEP,MAAM,OAAO,QAAQ;CAErB,MAAM,YAAY,wBAAkB,QAAA,KAAa;CACjD,IAAI,OAAIC,WAAkC,IAAI;CAC9C,IAAI,OAAIA,WAAkC,IAAI;CAC9C,MAAM,UAAU,qBAAqB;EACnC,MAAM,OAAI,MAAA;EACV,MAAM,WAAQ,aAAA;EACd,MAAM,QAAK,OAAA;EACX,OAAO;GACL,OAAO,KAAK;GACZ,UAAQ,SAAA;GACR,YAAU,WAAA;GACV,eAAe,OAAA,UAAW,WAAW,SAAM,KAAA;GAC3C,MAAI,KAAA;GACJ,eAAe,UACb,OAAO,aAAa,WAAW,WAAW,SAAS,KAAK,QAAS,KAAK;GACxE,YAAY,SAAS,UAAkB,MAAM,KAAK,QAAS,KAAK,IAAI,KAAA;GACpE,eAAa,cAAA;EACf;CACF,CAAC;CAID,MAAM,MAAyB;EAC7B,eAAe,QAAQ;EACvB,gBAAgB,QAAQ;CAC1B;CACA,YACE,KAAA,QACC,YAAY;EACX,IAAI,SAAS,OAAA,QAAS,GAAG;CAC3B,GACA,EAAE,OAAO,OAAO,CAClB;CAEA,aAAa;EACX,MAAM,cAAc,OAAA,UAAW;EAC/B,MAAM,WAAW,MAAA,MAAM,SAAS;EAChC,MAAM,QAAQC,aACZ,EACE,IAAI,CACF,kBAAkB,MAClB,eAAe,CAAC,kBAAkB,WAAW,gBAAgB,OAAO,CAAC,EAEzE,GACA,MACA;GACE,KAAG;GAEH,MAAM,WAAW,SAAS;GAC1B,aAAa,QAAA,SAAW,KAAA;GAExB,UAAU,cAAc,IAAI,KAAA;EAC9B,CACF;EACA,MAAM,UAAOC,YAAAC,UAAA,MAAA,CAER,UAAU,SAAS,YAAQD,YAAA,OAAAE,WAAA,EAAA,eAAA,OAAA,GACE,IAAI,MAAM,kBAAkB,QAAQ,CAAC,GAAA,CAAAF,YAAA,UAAA;GAAA,QAAA;GAAA,cAC/B,KAAK;EAAO,GAAA,IAAA,CAAA,CAAA,GAG/C,WAAQA,YAAA,OAED,WAAkB,EAAE,IAAI,kBAAkB,KAAK,GAAC,UAAA,OAAa;GAC/D,IAAI,WAAA,QAAA,IAAA,KACA,sBAAsB,aAAK,CAAC,QAAQ,KAAK,GAAA,IAAA,IAAA,IAAA,KACzC,sBAAsB,cAAM,CAAC,QAAQ,KAAK,GAAA,IAAA;GAC9C,KAAG;GACH,MAAM;EACR,CAAC,GAAC,CAED,QAAQ,MAAM,KAAK,SAAS;GAC3B,MAAM,OAAO,MAAA,MAAM,KAAK;GACxB,MAAM,MACJ,OAAA,UAAA,UAAqB,aAAa,UAAA,MAAU,MAAM,KAAK,KAAK,IAAC,UAAA;GAC/D,OAAAA,YAAA,OAAAE,WAAA,EAAA,OAES,KAAK,IAAG,GACT,WACF,EACE,IAAI,CACF,kBAAkB,MAClB,WAAA,QACI,kBAAkB,iBAClB,kBAAkB,YAAY,EAEtC,GACA,KACA;IACE,IAAI,WAAA,QAAA,IAAA,KACA,sBAAsB,SAAC,CAAC,KAAK,KAAK,CAAA,IAAA,IAAA,KAClC,sBAAsB,SAAC,CAAC,KAAK,KAAK,CAAA;IACtC,KAAK,QAAQ;IACb,MAAM;IACN,gBAAgB,MAAA,MAAM;IACtB,iBAAiB,KAAK,QAAQ;GAChC,CACF,GAAC,EAAA,cACW,KAAK,MAAK,CAAA,GAAA,CAErB,SAAA,MAAS,MAAM,KAAK,KAAK,CAAC,CAAA;EAGjC,CAAC,CAAC,CAAA,IAEF,QAAA,QACF,UAAU,SACV,MAAM,KAAK,EAAE,QAAQ,cAAc,IAAI,GAAG,UAAKF,YAAA,OAAAE,WAAA;GAAA,OACnC;GAAK,eAAA;EAAA,GAAyB,IAAI,MAAM,kBAAkB,WAAW,CAAC,GAAA,CAAAF,YAAA,UAExE,eACF;GACE,IAAI,CACF,kBAAkB,UAAQ,IAAA,KAC1B,sBAAsB,gBAAQ,CAC5B,OAAA,aAAA,UAAwB,WAAQ,aAAA,QAAkB,EAAE,GAAA,IAAA,CAAA;GAGxD,OAAO,QAAA;EACT,GAAC,cAAA,KAEH,GAAC,IAAA,CAAA,CAAA,CAGN,IAAC,MAAA,KAGH,CAAA;EAIL,OAAO,cAAWA,YAAA,YAAA;GAAA,QAER,WAAA,QAAa,MAAM;GAAG,aACjB;GAAK,iBACD;EAAK,GAAA,QAEnB,OAAO,IAAP,UAAO,EAAA,eAAA,CAAP,OAAO,EAAA,CAAA,IAAAA,YAAA,OAGD,aAAa,KAAK,GAAC,CAAG,OAAO,CAAA;CAE1C;AACF,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
1
+ {"version":3,"file":"VirtualList.js","names":["_isVNode","_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_vue_shallowRef","_createVNode","_Fragment","_mergeProps"],"sources":["../../src/display/VirtualList.tsx"],"sourcesContent":["/**\n * 虚拟列表:只渲染可见范围内的项,上万条数据也流畅。行高可以不固定,渲染后自动测量(COMPONENTS.md §10.7)。\n *\n * <VirtualList items={users} getKey={(user) => user.id} estimateSize={48} sx={styles.list}>\n * {(user) => <UserRow user={user} />}\n * </VirtualList>\n *\n * 默认组件自己是滚动容器,高度由使用方给(sx、class 或 style);scroll=\"window\" 时随页面滚动。\n * 读屏:role=\"list\",每项带 aria-setsize / aria-posinset,未渲染的项也算在总数里;没有数据时是 role=\"group\"(空状态、骨架不是列表项)。\n * loading:没有数据时显示骨架行(按 estimateSize 的高度),已有数据(刷新、加载更多)时顶部显示进度条;带 aria-busy。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { watch, type VNodeChild } from 'vue';\nimport { useDelayedLoading } from '../utils/motion/delayed-loading';\nimport { useLang } from '../config/context';\nimport { Progress } from '../feedback/Progress';\nimport { Skeleton, type SkeletonProps, type SkeletonShapeProps } from '../feedback/Skeleton';\nimport { SHIMMER_STAGGER } from '../utils/style/shimmer';\nimport {\n elementProps,\n mergeAttrs,\n mergePartProps,\n mergeProps,\n type PartProps,\n} from '../utils/props';\nimport { ScrollArea } from '../layout/ScrollArea';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { useVirtualizer } from '../utils/virtual/use-virtualizer';\nimport type { VirtualScrollOptions, VisibleRange } from '../utils/virtual/virtualizer';\n\n/** 跟着谁滚动 */\nexport interface VirtualListScrolls {\n /** 组件自己是滚动容器(默认):要给它高度(横向时给宽度) */\n container: unknown;\n /** 随页面(window)滚动:列表按总高度撑开,放在页面的普通流里 */\n window: unknown;\n}\n\n/** handle 拿到的方法 */\nexport interface VirtualListHandle {\n /** 滚动到第 index 项;align 默认 auto(已经完整可见就不动) */\n scrollToIndex: (index: number, options?: VirtualScrollOptions) => void;\n /** 滚动到相对列表开头的位置(px) */\n scrollToOffset: (offset: number, options?: VirtualScrollOptions) => void;\n}\n\n/** 受管属性:角色与可聚焦由组件决定 */\nexport type VirtualListManaged = 'role' | 'tabindex';\n\n/** 未声明的属性落到外层元素(滚动容器)上;aria-label 写在这里就是列表的名称 */\nexport interface VirtualListProps<T> extends PartProps<'div', VirtualListManaged> {\n /** 数据 */\n items: readonly T[];\n /** 渲染一项:`{(item, index) => …}` */\n children: (item: T, index: number) => VNodeChild;\n /** 每项的 key,默认用序号;数据会重排、增删时一定要给,测量结果与组件状态才对得上 */\n getKey?: (item: T, index: number) => PropertyKey;\n /** 每项的估计大小(px),数字或按项计算;渲染后以实际大小为准,默认 40 */\n estimateSize?: number | ((item: T, index: number) => number);\n /** 可见范围前后各多渲染几项,默认 4 */\n overscan?: number;\n /** 跟着谁滚动,默认 container */\n scroll?: keyof VirtualListScrolls;\n /** 横向排列与滚动 */\n horizontal?: boolean;\n /** 没有数据时显示的内容 */\n empty?: VNodeChild;\n /** 加载中:没有数据时显示骨架行,已有数据时顶部显示进度条 */\n loading?: boolean;\n /** 加载中占位行的部件属性 */\n propsSkeleton?: SkeletonShapeProps;\n /** 拿到滚动方法:`handle={(list) => (listHandle = list)}` */\n handle?: (handle: VirtualListHandle) => void;\n /** 可见范围变化(不含 overscan):接近末尾时加载更多 */\n onRangeChange?: (range: VisibleRange) => void;\n /** 列表层(撑开总高度、role=\"list\" 的项都在它里面)的部件属性 */\n propsList?: PartProps<'div', 'role'>;\n /**\n * 每一项外层(role=\"listitem\")的部件属性;可以按项计算:`(item, index) => ({ class: … })`。\n * 位置、序号与无障碍属性由组件管理\n */\n propsItem?: ItemProps | ((item: T, index: number) => ItemProps);\n}\n\n/** 项外层可以定制的属性 */\ntype ItemProps = PartProps<'div', 'role' | 'aria-setsize' | 'aria-posinset'>;\n\n/** 加载中显示几行骨架 */\nconst SKELETON_ROWS = 5;\n\n/** VirtualList 的样式:root、container、list、item、itemVertical、itemHorizontal 等 */\nexport const virtualListStyles = css.create({\n // 自己调整滚动位置(见 virtualizer.ts),不要浏览器再按锚点调整一次\n root: { overflowAnchor: 'none' },\n // 容器模式:列表元素是 ScrollArea 的视口(浮层滚动条)\n container: { overscrollBehavior: 'contain' },\n list: { position: 'relative', overflowAnchor: 'none' },\n item: { position: 'absolute', top: 0, left: 0, overflowAnchor: 'none' },\n itemVertical: { width: '_full' },\n itemHorizontal: { height: '_full' },\n // 刷新中的进度条贴在可见区域顶部\n progress: { position: 'sticky', top: 0, zIndex: 1, height: 0 },\n skeletonRow: { paddingBlock: '_xs' },\n skeleton: { display: 'block', width: '_full' },\n});\n\n// 总大小与位置是任意值,用动态样式(编译为 CSS 变量);单独一个 create,见 COMPONENTS.md §4\n/** VirtualList 的样式:height、width、y、x、skeleton */\nexport const virtualListSizeStyles = css.create({\n height: (px: number) => ({ height: px }),\n width: (px: number) => ({ width: px, height: '_full' }),\n y: (px: number) => ({ transform: `translateY(${px}px)` }),\n x: (px: number) => ({ transform: `translateX(${px}px)` }),\n // 骨架行比一项略矮:上下留出间隔\n skeleton: (px: number) => ({ height: Math.max(8, px - 8) }),\n});\n\n/** 虚拟列表:只渲染可见范围内的项,行高渲染后自动测量 */\nexport const VirtualList = _component(\n <T,>({\n items,\n children,\n getKey,\n estimateSize = 40,\n overscan = 4,\n scroll = 'container',\n horizontal = false,\n empty,\n loading = false,\n propsSkeleton,\n handle,\n onRangeChange,\n propsList,\n propsItem,\n ...rest\n }: VirtualListProps<T>) => {\n const lang = useLang();\n // 骨架、进度条防闪烁;aria-busy 按真实的 loading\n const indicator = useDelayedLoading(() => loading);\n let root = _state.raw<HTMLElement | null>(null);\n let list = _state.raw<HTMLElement | null>(null);\n const virtual = useVirtualizer(() => {\n const data = items;\n const estimate = estimateSize;\n const keyOf = getKey;\n return {\n count: data.length,\n overscan,\n horizontal,\n scrollElement: scroll === 'window' ? window : root,\n list,\n estimateSize: (index: number) =>\n typeof estimate === 'number' ? estimate : estimate(data[index]!, index),\n getItemKey: keyOf ? (index: number) => keyOf(data[index]!, index) : undefined,\n onRangeChange,\n };\n });\n\n // 挂载之后才交出 handle:使用方在回调里立即滚动(恢复上次的位置)也能生效。\n // handle 不放进监听源:父级写的箭头函数每次渲染都是新的,不该因此重新交出\n const api: VirtualListHandle = {\n scrollToIndex: virtual.scrollToIndex,\n scrollToOffset: virtual.scrollToOffset,\n };\n watch(\n () => root,\n (element) => {\n if (element) handle?.(api);\n },\n { flush: 'post' },\n );\n\n return () => {\n const isContainer = scroll === 'container';\n const hasItems = items.length > 0;\n const props = mergeProps<'div'>(\n {\n sx: [\n virtualListStyles.root,\n isContainer && [virtualListStyles.container, focusRingStyles.visible],\n ],\n },\n rest,\n {\n ref: _toRef(root),\n // 没有数据(空状态、首次加载的骨架)时不是列表;仍给 group 角色,写在外层的 aria-label 才有效\n role: hasItems ? 'list' : 'group',\n 'aria-busy': loading || undefined,\n // 容器模式下可以用键盘滚动\n tabindex: isContainer ? 0 : undefined,\n },\n );\n const content = (\n <>\n {indicator.value && hasItems && (\n <div aria-hidden=\"true\" {...css.attrs(virtualListStyles.progress)}>\n <Progress size=\"xs\" aria-label={lang.loading} />\n </div>\n )}\n {hasItems ? (\n <div\n {...mergeAttrs<'div'>({ sx: virtualListStyles.list }, propsList, {\n sx: horizontal\n ? virtualListSizeStyles.width(virtual.total)\n : virtualListSizeStyles.height(virtual.total),\n ref: _toRef(list),\n role: 'presentation',\n })}\n >\n {virtual.items.map((item) => {\n const data = items[item.index]!;\n const own =\n typeof propsItem === 'function' ? propsItem(data, item.index) : propsItem;\n return (\n <div\n key={item.key}\n {...mergeAttrs<'div'>(\n {\n sx: [\n virtualListStyles.item,\n horizontal\n ? virtualListStyles.itemHorizontal\n : virtualListStyles.itemVertical,\n ],\n },\n own,\n {\n sx: horizontal\n ? virtualListSizeStyles.x(item.start)\n : virtualListSizeStyles.y(item.start),\n ref: virtual.measure,\n role: 'listitem',\n 'aria-setsize': items.length,\n 'aria-posinset': item.index + 1,\n },\n )}\n data-index={item.index}\n >\n {children(data, item.index)}\n </div>\n );\n })}\n </div>\n ) : loading ? (\n indicator.value &&\n Array.from({ length: SKELETON_ROWS }, (_, index) => (\n <div key={index} aria-hidden=\"true\" {...css.attrs(virtualListStyles.skeletonRow)}>\n <Skeleton\n {...mergePartProps<SkeletonProps>(\n {\n sx: [\n virtualListStyles.skeleton,\n virtualListSizeStyles.skeleton(\n typeof estimateSize === 'number' ? estimateSize : 40,\n ),\n ],\n delay: index * SHIMMER_STAGGER,\n },\n propsSkeleton,\n )}\n />\n </div>\n ))\n ) : (\n empty\n )}\n </>\n );\n // 容器模式:列表元素就是 ScrollArea 的视口,滚动条是浮层的;跟着页面滚动时就是普通的 div\n return isContainer ? (\n <ScrollArea\n axis={horizontal ? 'x' : 'y'}\n focusable={false}\n propsViewport={props as PartProps<'div'>}\n >\n {content}\n </ScrollArea>\n ) : (\n <div {...elementProps(props)}>{content}</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, onMounted, ref, watch } from "vue";
3
- import { _component, childrenProp, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
2
+ import { createVNode, onMounted, ref, watch } 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/display/Watermark.tsx
6
6
  /** 未声明的属性落到外层 div 上 */
@@ -101,7 +101,7 @@ var Watermark = /*#__PURE__*/ _component((_props, _ctx) => {
101
101
  color.value
102
102
  ], () => void draw(), { deep: true });
103
103
  return () => {
104
- const layer = createVNode("div", mergeProps({ "aria-hidden": "true" }, mergeAttrs({ sx: [
104
+ const layer = createVNode("div", mergeJsxProps({ "aria-hidden": "true" }, mergeAttrs({ sx: [
105
105
  watermarkStyles.layer,
106
106
  fullscreen.value && watermarkStyles.fullscreen,
107
107
  tile.value && css.bind(watermarkTileStyles.tile, () => [`url(${tile.value.url})`, `${tile.value.width}px ${tile.value.height}px`], true)
@@ -1 +1 @@
1
- {"version":3,"file":"Watermark.js","names":["_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_vue_ref","_createVNode","_mergeProps"],"sources":["../../src/display/Watermark.tsx"],"sourcesContent":["/**\n * 水印:在内容上(或整页)铺满斜着的文字或图片,截图、拍屏时能看出来源(查看人、时间、密级)。\n *\n * <Watermark content={['林小满', '2026-10-24']}>{report}</Watermark>\n * <Watermark content=\"内部资料\" fullscreen /> 整页\n * <Watermark image=\"/logo.svg\" width={120} height={40}>…</Watermark>\n *\n * 用 canvas 画一格(按设备像素比放大,高分屏不糊),作为一层盖在内容上的背景平铺:pointer-events: none,\n * 不挡点击与选择;aria-hidden,读屏不念。默认颜色是半透明的灰,亮色、暗色主题上都看得见、不抢内容。\n * 只是提示性的:前端的水印删得掉,真正的保密要靠服务端(导出时打水印、权限)。\n * 部件:Root(div:包着内容,position: relative)、Layer(div:水印那一层)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { onMounted, watch, type VNodeChild } from 'vue';\nimport { mergeAttrs, type PartProps } from '../utils/props';\n\n/** 未声明的属性落到外层 div 上 */\nexport interface WatermarkProps extends PartProps<'div'> {\n /** 文字:一行写字符串,多行写数组(姓名、日期) */\n content?: string | readonly string[];\n /** 图片地址:给了就画图片(同源或允许跨域的图片),不画文字 */\n image?: string;\n /** 图片的宽(px),默认 120 */\n width?: number;\n /** 图片的高(px),默认 40 */\n height?: number;\n /** 旋转角度(度),默认 -22 */\n rotate?: number;\n /** 每格之间的空隙 [横, 竖](px),默认 [120, 100] */\n gap?: readonly [number, number];\n /** 字号(px),默认 14 */\n fontSize?: number;\n /** 颜色,默认半透明的灰 */\n color?: string;\n /** 盖住整页(position: fixed),而不只是包着的内容 */\n fullscreen?: boolean;\n /** 水印那一层的部件属性 */\n propsLayer?: PartProps<'div'>;\n children?: VNodeChild;\n}\n\n/** Watermark 的样式:root、layer、fullscreen */\nexport const watermarkStyles = css.create({\n root: { position: 'relative' },\n layer: {\n position: 'absolute',\n inset: 0,\n zIndex: 9,\n pointerEvents: 'none',\n backgroundRepeat: 'repeat',\n // Windows 高对比下系统会去掉背景图:水印本来就是装饰,不需要\n forcedColorAdjust: 'auto',\n },\n fullscreen: { position: 'fixed', zIndex: 1000 },\n});\n\n/** 水印那一层的背景(data URL 与一格的大小) */\nexport const watermarkTileStyles = css.create({\n tile: (url: string, size: string) => ({ backgroundImage: url, backgroundSize: size }),\n});\n\nconst DEFAULT_COLOR = 'rgba(128, 128, 128, 0.16)';\n\n/** 水印:一层不挡操作的平铺文字或图片 */\nexport const Watermark = _component(\n ({\n content,\n image,\n width = 120,\n height = 40,\n rotate = -22,\n gap = [120, 100],\n fontSize = 14,\n color = DEFAULT_COLOR,\n fullscreen = false,\n propsLayer,\n children,\n ...rest\n }: WatermarkProps) => {\n // 一格的图(data URL)与它在页面上的大小(CSS px)\n let tile = _state<{ url: string; width: number; height: number } | null>(null);\n\n let drawing = 0;\n\n /**\n * 画一块平铺单元:两行两列的格子里斜对角各画一份(同 antd),平铺后相邻两行错开半格,铺得匀;\n * 每份居中、旋转,四周留出 gap 的一半\n */\n async function draw() {\n if (typeof document === 'undefined') return;\n const current = ++drawing;\n const ratio = window.devicePixelRatio || 1;\n const lines = typeof content === 'string' ? [content] : [...(content ?? [])];\n const canvas = document.createElement('canvas');\n const context = canvas.getContext('2d');\n if (!context) return;\n const font = `${fontSize}px sans-serif`;\n context.font = font;\n const lineHeight = fontSize * 1.4;\n const [contentWidth, contentHeight] = image\n ? [width, height]\n : [\n Math.max(1, ...lines.map((line) => context.measureText(line).width)),\n lines.length * lineHeight,\n ];\n const cellWidth = contentWidth + gap[0];\n const cellHeight = contentHeight + gap[1];\n let picture: HTMLImageElement | undefined;\n if (image) {\n picture = new Image();\n picture.crossOrigin = 'anonymous';\n picture.src = image;\n await picture.decode().catch(() => undefined);\n // 等图片时参数又变了:交给后一次\n if (current !== drawing) return;\n }\n canvas.width = cellWidth * 2 * ratio;\n canvas.height = cellHeight * 2 * ratio;\n context.scale(ratio, ratio);\n // canvas 的尺寸改过之后要重新设字体\n context.font = font;\n context.fillStyle = color;\n context.textAlign = 'center';\n context.textBaseline = 'middle';\n for (const [x, y] of [\n [cellWidth / 2, cellHeight / 2],\n [cellWidth * 1.5, cellHeight * 1.5],\n ] as const) {\n context.save();\n context.translate(x, y);\n context.rotate((rotate * Math.PI) / 180);\n if (picture?.naturalWidth)\n context.drawImage(picture, -width / 2, -height / 2, width, height);\n else if (!image)\n lines.forEach((line, index) =>\n context.fillText(line, 0, (index - (lines.length - 1) / 2) * lineHeight),\n );\n context.restore();\n }\n tile = { url: canvas.toDataURL(), width: cellWidth * 2, height: cellHeight * 2 };\n }\n\n onMounted(() => void draw());\n watch(\n () => [content, image, width, height, rotate, gap, fontSize, color],\n () => void draw(),\n {\n deep: true,\n },\n );\n\n return () => {\n const layer = (\n <div\n aria-hidden=\"true\"\n {...mergeAttrs<'div'>(\n {\n sx: [\n watermarkStyles.layer,\n fullscreen && watermarkStyles.fullscreen,\n tile &&\n watermarkTileStyles.tile(`url(${tile.url})`, `${tile.width}px ${tile.height}px`),\n ],\n },\n propsLayer,\n )}\n data-watermark=\"\"\n />\n );\n // 整页且没有包着内容:只渲染那一层\n if (fullscreen && children == null) return layer;\n return (\n <div {...mergeAttrs<'div'>({ sx: watermarkStyles.root }, rest)}>\n {children}\n {layer}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"Watermark.js","names":["_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_vue_ref","_createVNode","_mergeProps"],"sources":["../../src/display/Watermark.tsx"],"sourcesContent":["/**\n * 水印:在内容上(或整页)铺满斜着的文字或图片,截图、拍屏时能看出来源(查看人、时间、密级)。\n *\n * <Watermark content={['林小满', '2026-10-24']}>{report}</Watermark>\n * <Watermark content=\"内部资料\" fullscreen /> 整页\n * <Watermark image=\"/logo.svg\" width={120} height={40}>…</Watermark>\n *\n * 用 canvas 画一格(按设备像素比放大,高分屏不糊),作为一层盖在内容上的背景平铺:pointer-events: none,\n * 不挡点击与选择;aria-hidden,读屏不念。默认颜色是半透明的灰,亮色、暗色主题上都看得见、不抢内容。\n * 只是提示性的:前端的水印删得掉,真正的保密要靠服务端(导出时打水印、权限)。\n * 部件:Root(div:包着内容,position: relative)、Layer(div:水印那一层)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { onMounted, watch, type VNodeChild } from 'vue';\nimport { mergeAttrs, type PartProps } from '../utils/props';\n\n/** 未声明的属性落到外层 div 上 */\nexport interface WatermarkProps extends PartProps<'div'> {\n /** 文字:一行写字符串,多行写数组(姓名、日期) */\n content?: string | readonly string[];\n /** 图片地址:给了就画图片(同源或允许跨域的图片),不画文字 */\n image?: string;\n /** 图片的宽(px),默认 120 */\n width?: number;\n /** 图片的高(px),默认 40 */\n height?: number;\n /** 旋转角度(度),默认 -22 */\n rotate?: number;\n /** 每格之间的空隙 [横, 竖](px),默认 [120, 100] */\n gap?: readonly [number, number];\n /** 字号(px),默认 14 */\n fontSize?: number;\n /** 颜色,默认半透明的灰 */\n color?: string;\n /** 盖住整页(position: fixed),而不只是包着的内容 */\n fullscreen?: boolean;\n /** 水印那一层的部件属性 */\n propsLayer?: PartProps<'div'>;\n children?: VNodeChild;\n}\n\n/** Watermark 的样式:root、layer、fullscreen */\nexport const watermarkStyles = css.create({\n root: { position: 'relative' },\n layer: {\n position: 'absolute',\n inset: 0,\n zIndex: 9,\n pointerEvents: 'none',\n backgroundRepeat: 'repeat',\n // Windows 高对比下系统会去掉背景图:水印本来就是装饰,不需要\n forcedColorAdjust: 'auto',\n },\n fullscreen: { position: 'fixed', zIndex: 1000 },\n});\n\n/** 水印那一层的背景(data URL 与一格的大小) */\nexport const watermarkTileStyles = css.create({\n tile: (url: string, size: string) => ({ backgroundImage: url, backgroundSize: size }),\n});\n\nconst DEFAULT_COLOR = 'rgba(128, 128, 128, 0.16)';\n\n/** 水印:一层不挡操作的平铺文字或图片 */\nexport const Watermark = _component(\n ({\n content,\n image,\n width = 120,\n height = 40,\n rotate = -22,\n gap = [120, 100],\n fontSize = 14,\n color = DEFAULT_COLOR,\n fullscreen = false,\n propsLayer,\n children,\n ...rest\n }: WatermarkProps) => {\n // 一格的图(data URL)与它在页面上的大小(CSS px)\n let tile = _state<{ url: string; width: number; height: number } | null>(null);\n\n let drawing = 0;\n\n /**\n * 画一块平铺单元:两行两列的格子里斜对角各画一份(同 antd),平铺后相邻两行错开半格,铺得匀;\n * 每份居中、旋转,四周留出 gap 的一半\n */\n async function draw() {\n if (typeof document === 'undefined') return;\n const current = ++drawing;\n const ratio = window.devicePixelRatio || 1;\n const lines = typeof content === 'string' ? [content] : [...(content ?? [])];\n const canvas = document.createElement('canvas');\n const context = canvas.getContext('2d');\n if (!context) return;\n const font = `${fontSize}px sans-serif`;\n context.font = font;\n const lineHeight = fontSize * 1.4;\n const [contentWidth, contentHeight] = image\n ? [width, height]\n : [\n Math.max(1, ...lines.map((line) => context.measureText(line).width)),\n lines.length * lineHeight,\n ];\n const cellWidth = contentWidth + gap[0];\n const cellHeight = contentHeight + gap[1];\n let picture: HTMLImageElement | undefined;\n if (image) {\n picture = new Image();\n picture.crossOrigin = 'anonymous';\n picture.src = image;\n await picture.decode().catch(() => undefined);\n // 等图片时参数又变了:交给后一次\n if (current !== drawing) return;\n }\n canvas.width = cellWidth * 2 * ratio;\n canvas.height = cellHeight * 2 * ratio;\n context.scale(ratio, ratio);\n // canvas 的尺寸改过之后要重新设字体\n context.font = font;\n context.fillStyle = color;\n context.textAlign = 'center';\n context.textBaseline = 'middle';\n for (const [x, y] of [\n [cellWidth / 2, cellHeight / 2],\n [cellWidth * 1.5, cellHeight * 1.5],\n ] as const) {\n context.save();\n context.translate(x, y);\n context.rotate((rotate * Math.PI) / 180);\n if (picture?.naturalWidth)\n context.drawImage(picture, -width / 2, -height / 2, width, height);\n else if (!image)\n lines.forEach((line, index) =>\n context.fillText(line, 0, (index - (lines.length - 1) / 2) * lineHeight),\n );\n context.restore();\n }\n tile = { url: canvas.toDataURL(), width: cellWidth * 2, height: cellHeight * 2 };\n }\n\n onMounted(() => void draw());\n watch(\n () => [content, image, width, height, rotate, gap, fontSize, color],\n () => void draw(),\n {\n deep: true,\n },\n );\n\n return () => {\n const layer = (\n <div\n aria-hidden=\"true\"\n {...mergeAttrs<'div'>(\n {\n sx: [\n watermarkStyles.layer,\n fullscreen && watermarkStyles.fullscreen,\n tile &&\n watermarkTileStyles.tile(`url(${tile.url})`, `${tile.width}px ${tile.height}px`),\n ],\n },\n propsLayer,\n )}\n data-watermark=\"\"\n />\n );\n // 整页且没有包着内容:只渲染那一层\n if (fullscreen && children == null) return layer;\n return (\n <div {...mergeAttrs<'div'>({ sx: watermarkStyles.root }, rest)}>\n {children}\n {layer}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  import { t } from "../config/theme/tokens.js";
2
- import { mergeAttrs, mergePartProps, mergeProps as mergeProps$1 } from "../utils/props.js";
2
+ import { mergeAttrs, mergePartProps, mergeProps } from "../utils/props.js";
3
3
  import { CodeBlock } from "../base/CodeBlock.js";
4
4
  import { Tab, TabList, TabPanel, Tabs } from "../navigation/Tabs.js";
5
- import { createVNode, mergeProps } from "vue";
6
- import { _component, bindable, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
5
+ import { createVNode } from "vue";
6
+ import { _component, bindable, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
7
7
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
8
8
  //#region src/docs-kit/CodeGroup.tsx
9
9
  /** 一组代码里的一段 */
@@ -46,7 +46,7 @@ var CodeGroup = /*#__PURE__*/ _component((_props, _ctx) => {
46
46
  "size": "sm",
47
47
  "key": "__site1"
48
48
  }, {
49
- default: () => [createVNode(TabList, mergeProps(mergePartProps({
49
+ default: () => [createVNode(TabList, mergeJsxProps(mergePartProps({
50
50
  sx: codeGroupStyles.list,
51
51
  "aria-label": items.value.map((item) => item.label).join(" / ")
52
52
  }, propsList.value), { "key": "__site0" }), {
@@ -61,7 +61,7 @@ var CodeGroup = /*#__PURE__*/ _component((_props, _ctx) => {
61
61
  "key": keyOf(item),
62
62
  "value": keyOf(item),
63
63
  "sx": codeGroupStyles.panel
64
- }, { default: () => [createVNode(CodeBlock, mergeProps(block, { "propsRoot": mergeProps$1({ sx: codeGroupStyles.block }, propsRoot) }), null)] });
64
+ }, { default: () => [createVNode(CodeBlock, mergeJsxProps(block, { "propsRoot": mergeProps({ sx: codeGroupStyles.block }, propsRoot) }), null)] });
65
65
  })],
66
66
  $stable: true
67
67
  })]);
@@ -1 +1 @@
1
- {"version":3,"file":"CodeGroup.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_createVNode","_mergeProps","mergeProps"],"sources":["../../src/docs-kit/CodeGroup.tsx"],"sourcesContent":["/**\n * 一组代码,用标签页切换:安装命令(pnpm / npm / yarn)、同一段逻辑的几个文件。由 Tabs 与 CodeBlock 组合,\n * 标签栏就是代码块的标题栏。\n *\n * <CodeGroup items={[\n * { label: 'pnpm', code: 'pnpm add @zerodep-dev/vue-tsx-pro-ui', lang: 'bash' },\n * { label: 'npm', code: 'npm i @zerodep-dev/vue-tsx-pro-ui', lang: 'bash' },\n * ]} />\n *\n * 选中哪一个可以双向绑定(_value={manager}),几组代码绑同一个变量就一起切换。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { CodeBlock, type CodeBlockProps } from '../base/CodeBlock';\nimport { Tab, TabList, TabPanel, Tabs, type TabListProps } from '../navigation/Tabs';\nimport { mergeAttrs, mergePartProps, mergeProps, type PartProps } from '../utils/props';\nimport { t } from '../config/theme/tokens';\n\n/** 一组代码里的一段 */\nexport interface CodeGroupItem extends Omit<CodeBlockProps, 'title'> {\n /** 标签上的文字;也是这一段的值(没给 value 时) */\n label: string;\n /** 这一段的值,默认等于 label */\n value?: string;\n}\n\n/** 未声明的属性落到外层的 div 上 */\nexport interface CodeGroupProps extends PartProps<'div'> {\n /** 各段代码 */\n items: readonly CodeGroupItem[];\n /** 选中的那一段的值:父级可以写 _value={x};默认第一段 */\n _value?: string;\n /** 标签栏的部件属性;名称(aria-label)默认是各段标签连起来 */\n propsList?: Partial<TabListProps>;\n}\n\n/** CodeGroup 的样式:外框与标签栏;代码块去掉自己的外框 */\nexport const codeGroupStyles = css.create({\n root: {\n minWidth: 0,\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_borderMuted',\n borderRadius: '_md',\n backgroundColor: '_surface',\n overflow: 'hidden',\n },\n list: { paddingInline: '_sm', backgroundColor: '_surfaceMuted', fontSize: '_sm' },\n panel: { outlineOffset: `calc(-1 * ${t.borderWidths.sm})` },\n block: { borderWidth: 0, borderRadius: 0 },\n});\n\nconst keyOf = (item: CodeGroupItem) => item.value ?? item.label;\n\n/** 一组代码,标签页切换 */\nexport const CodeGroup = _component(\n ({\n items,\n _value: value = _bindable<string | undefined>(undefined),\n propsList,\n ...rest\n }: CodeGroupProps) =>\n () => {\n const selected = value ?? (items[0] && keyOf(items[0]));\n return (\n <div {...mergeAttrs<'div'>({ sx: codeGroupStyles.root }, rest)}>\n <Tabs\n _value={selected}\n // 默认选第一段时 value 是 undefined,不能直接 _bind:选中时写回\n onUpdate:_value={(next: string) => (value = next)}\n size=\"sm\"\n >\n <TabList\n {...mergePartProps<TabListProps>(\n {\n sx: codeGroupStyles.list,\n 'aria-label': items.map((item) => item.label).join(' / '),\n },\n propsList,\n )}\n >\n {items.map((item) => (\n <Tab key={keyOf(item)} value={keyOf(item)}>\n {item.label}\n </Tab>\n ))}\n </TabList>\n {items.map((item) => {\n const { label: _label, value: _value, propsRoot, ...block } = item;\n return (\n <TabPanel key={keyOf(item)} value={keyOf(item)} sx={codeGroupStyles.panel}>\n <CodeBlock\n {...block}\n propsRoot={mergeProps<'div'>({ sx: codeGroupStyles.block }, propsRoot)}\n />\n </TabPanel>\n );\n })}\n </Tabs>\n </div>\n );\n },\n);\n"],"mappings":";;;;;;;;;;;AAqCA,IAAa,kBAAkB,IAAI,OAAO;CACxC,MAAM;EACJ,UAAU;EACV,aAAa;EACb,aAAa;EACb,aAAa;EACb,cAAc;EACd,iBAAiB;EACjB,UAAU;CACZ;CACA,MAAM;EAAE,eAAe;EAAO,iBAAiB;EAAiB,UAAU;CAAM;CAChF,OAAO,EAAE,eAAe,aAAa,EAAE,aAAa,GAAE,GAAI;CAC1D,OAAO;EAAE,aAAa;EAAG,cAAc;CAAE;AAC3C,CAAC;AAED,IAAM,SAAS,SAAwB,KAAK,SAAS,KAAK;;AAG1D,IAAa,YAAY,0BACvB,QAAA,SAAA;CAAA,MAAA,SAAA,CAAA;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,QAAAC,SAAA,QAAA,gBAEgD,KAAA,GAAS,KAAA,IAAA;CAAA,MAAA,YAAAD,aAAA,QAAA,WAAA;CAAA,MAEpD,OAAIE,UAAA,QAAA,MAAA,IAAA;CAAA,aAED;EACJ,MAAM,WAAW,MAAA,UAAU,MAAA,MAAM,MAAM,MAAM,MAAA,MAAM,EAAE;EACrD,OAAAC,YAAA,OACW,WAAkB,EAAE,IAAI,gBAAgB,KAAK,GAAG,IAAI,GAAC,CAAAA,YAAA,MAAA;GAAA,UAElD;GAAQ,mBAAA,OAAA,OAAA,OAAA,MAEE,SAAkB,MAAA,QAAQ;GAAK,QAAA;GAAA,OAAA;EAAA,GAAA;GAAA,eAAA,CAAAA,YAAA,SAAAC,WAI3C,eACF;IACE,IAAI,gBAAgB;IACpB,cAAc,MAAA,MAAM,KAAK,SAAS,KAAK,KAAK,CAAC,CAAC,KAAK,KAAK;GAC1D,GAAC,UAAA,KAEH,GAAC,EAAA,OAAA,UAAA,CAAA,GAAA;IAAA,eAAA,CAEA,MAAA,MAAM,KAAK,SAAID,YAAA,KAAA;KAAA,OACJ,MAAM,IAAI;KAAC,SAAS,MAAM,IAAI;IAAC,GAAA,EAAA,eAAA,CACtC,KAAK,KAAK,EAAA,CAAA,CAEd,CAAC;IAAA,SAAA;GAAA,CAAA,GAEH,MAAA,MAAM,KAAK,SAAS;IACnB,MAAM,EAAE,OAAO,QAAQ,OAAO,QAAQ,WAAW,GAAG,UAAU;IAC9D,OAAAA,YAAA,UAAA;KAAA,OACiB,MAAM,IAAI;KAAC,SAAS,MAAM,IAAI;KAAC,MAAM,gBAAgB;IAAK,GAAA,EAAA,eAAA,CAAAA,YAAA,WAAAC,WAEjE,OAAK,EAAA,aACEC,aAAkB,EAAE,IAAI,gBAAgB,MAAM,GAAG,SAAS,EAAC,CAAA,GAAA,IAAA,CAAA,EAAA,CAAA;GAI9E,CAAC,CAAC;GAAA,SAAA;EAAA,CAAA,CAAA,CAAA;CAIV;AAAC,GAAA;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACL"}
1
+ {"version":3,"file":"CodeGroup.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../src/docs-kit/CodeGroup.tsx"],"sourcesContent":["/**\n * 一组代码,用标签页切换:安装命令(pnpm / npm / yarn)、同一段逻辑的几个文件。由 Tabs 与 CodeBlock 组合,\n * 标签栏就是代码块的标题栏。\n *\n * <CodeGroup items={[\n * { label: 'pnpm', code: 'pnpm add @zerodep-dev/vue-tsx-pro-ui', lang: 'bash' },\n * { label: 'npm', code: 'npm i @zerodep-dev/vue-tsx-pro-ui', lang: 'bash' },\n * ]} />\n *\n * 选中哪一个可以双向绑定(_value={manager}),几组代码绑同一个变量就一起切换。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { CodeBlock, type CodeBlockProps } from '../base/CodeBlock';\nimport { Tab, TabList, TabPanel, Tabs, type TabListProps } from '../navigation/Tabs';\nimport { mergeAttrs, mergePartProps, mergeProps, type PartProps } from '../utils/props';\nimport { t } from '../config/theme/tokens';\n\n/** 一组代码里的一段 */\nexport interface CodeGroupItem extends Omit<CodeBlockProps, 'title'> {\n /** 标签上的文字;也是这一段的值(没给 value 时) */\n label: string;\n /** 这一段的值,默认等于 label */\n value?: string;\n}\n\n/** 未声明的属性落到外层的 div 上 */\nexport interface CodeGroupProps extends PartProps<'div'> {\n /** 各段代码 */\n items: readonly CodeGroupItem[];\n /** 选中的那一段的值:父级可以写 _value={x};默认第一段 */\n _value?: string;\n /** 标签栏的部件属性;名称(aria-label)默认是各段标签连起来 */\n propsList?: Partial<TabListProps>;\n}\n\n/** CodeGroup 的样式:外框与标签栏;代码块去掉自己的外框 */\nexport const codeGroupStyles = css.create({\n root: {\n minWidth: 0,\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_borderMuted',\n borderRadius: '_md',\n backgroundColor: '_surface',\n overflow: 'hidden',\n },\n list: { paddingInline: '_sm', backgroundColor: '_surfaceMuted', fontSize: '_sm' },\n panel: { outlineOffset: `calc(-1 * ${t.borderWidths.sm})` },\n block: { borderWidth: 0, borderRadius: 0 },\n});\n\nconst keyOf = (item: CodeGroupItem) => item.value ?? item.label;\n\n/** 一组代码,标签页切换 */\nexport const CodeGroup = _component(\n ({\n items,\n _value: value = _bindable<string | undefined>(undefined),\n propsList,\n ...rest\n }: CodeGroupProps) =>\n () => {\n const selected = value ?? (items[0] && keyOf(items[0]));\n return (\n <div {...mergeAttrs<'div'>({ sx: codeGroupStyles.root }, rest)}>\n <Tabs\n _value={selected}\n // 默认选第一段时 value 是 undefined,不能直接 _bind:选中时写回\n onUpdate:_value={(next: string) => (value = next)}\n size=\"sm\"\n >\n <TabList\n {...mergePartProps<TabListProps>(\n {\n sx: codeGroupStyles.list,\n 'aria-label': items.map((item) => item.label).join(' / '),\n },\n propsList,\n )}\n >\n {items.map((item) => (\n <Tab key={keyOf(item)} value={keyOf(item)}>\n {item.label}\n </Tab>\n ))}\n </TabList>\n {items.map((item) => {\n const { label: _label, value: _value, propsRoot, ...block } = item;\n return (\n <TabPanel key={keyOf(item)} value={keyOf(item)} sx={codeGroupStyles.panel}>\n <CodeBlock\n {...block}\n propsRoot={mergeProps<'div'>({ sx: codeGroupStyles.block }, propsRoot)}\n />\n </TabPanel>\n );\n })}\n </Tabs>\n </div>\n );\n },\n);\n"],"mappings":";;;;;;;;;;;AAqCA,IAAa,kBAAkB,IAAI,OAAO;CACxC,MAAM;EACJ,UAAU;EACV,aAAa;EACb,aAAa;EACb,aAAa;EACb,cAAc;EACd,iBAAiB;EACjB,UAAU;CACZ;CACA,MAAM;EAAE,eAAe;EAAO,iBAAiB;EAAiB,UAAU;CAAM;CAChF,OAAO,EAAE,eAAe,aAAa,EAAE,aAAa,GAAE,GAAI;CAC1D,OAAO;EAAE,aAAa;EAAG,cAAc;CAAE;AAC3C,CAAC;AAED,IAAM,SAAS,SAAwB,KAAK,SAAS,KAAK;;AAG1D,IAAa,YAAY,0BACvB,QAAA,SAAA;CAAA,MAAA,SAAA,CAAA;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,QAAAC,SAAA,QAAA,gBAEgD,KAAA,GAAS,KAAA,IAAA;CAAA,MAAA,YAAAD,aAAA,QAAA,WAAA;CAAA,MAEpD,OAAIE,UAAA,QAAA,MAAA,IAAA;CAAA,aAED;EACJ,MAAM,WAAW,MAAA,UAAU,MAAA,MAAM,MAAM,MAAM,MAAA,MAAM,EAAE;EACrD,OAAAC,YAAA,OACW,WAAkB,EAAE,IAAI,gBAAgB,KAAK,GAAG,IAAI,GAAC,CAAAA,YAAA,MAAA;GAAA,UAElD;GAAQ,mBAAA,OAAA,OAAA,OAAA,MAEE,SAAkB,MAAA,QAAQ;GAAK,QAAA;GAAA,OAAA;EAAA,GAAA;GAAA,eAAA,CAAAA,YAAA,SAAAC,cAI3C,eACF;IACE,IAAI,gBAAgB;IACpB,cAAc,MAAA,MAAM,KAAK,SAAS,KAAK,KAAK,CAAC,CAAC,KAAK,KAAK;GAC1D,GAAC,UAAA,KAEH,GAAC,EAAA,OAAA,UAAA,CAAA,GAAA;IAAA,eAAA,CAEA,MAAA,MAAM,KAAK,SAAID,YAAA,KAAA;KAAA,OACJ,MAAM,IAAI;KAAC,SAAS,MAAM,IAAI;IAAC,GAAA,EAAA,eAAA,CACtC,KAAK,KAAK,EAAA,CAAA,CAEd,CAAC;IAAA,SAAA;GAAA,CAAA,GAEH,MAAA,MAAM,KAAK,SAAS;IACnB,MAAM,EAAE,OAAO,QAAQ,OAAO,QAAQ,WAAW,GAAG,UAAU;IAC9D,OAAAA,YAAA,UAAA;KAAA,OACiB,MAAM,IAAI;KAAC,SAAS,MAAM,IAAI;KAAC,MAAM,gBAAgB;IAAK,GAAA,EAAA,eAAA,CAAAA,YAAA,WAAAC,cAEjE,OAAK,EAAA,aACE,WAAkB,EAAE,IAAI,gBAAgB,MAAM,GAAG,SAAS,EAAC,CAAA,GAAA,IAAA,CAAA,EAAA,CAAA;GAI9E,CAAC,CAAC;GAAA,SAAA;EAAA,CAAA,CAAA,CAAA;CAIV;AAAC,GAAA;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACL"}