@zerodep-dev/vue-tsx-pro-ui 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (470) hide show
  1. package/dist/base/Badge.js +3 -3
  2. package/dist/base/Badge.js.map +1 -1
  3. package/dist/base/Can.d.ts +12 -0
  4. package/dist/base/Can.js +20 -0
  5. package/dist/base/Can.js.map +1 -0
  6. package/dist/base/ClientOnly.d.ts +10 -0
  7. package/dist/base/ClientOnly.js +18 -0
  8. package/dist/base/ClientOnly.js.map +1 -0
  9. package/dist/base/CloseButton.js +3 -3
  10. package/dist/base/CloseButton.js.map +1 -1
  11. package/dist/base/CodeBlock.js +5 -5
  12. package/dist/base/CodeBlock.js.map +1 -1
  13. package/dist/base/CopyButton.js +3 -3
  14. package/dist/base/CopyButton.js.map +1 -1
  15. package/dist/base/Icon.js +3 -3
  16. package/dist/base/Icon.js.map +1 -1
  17. package/dist/base/Indicator.js +3 -3
  18. package/dist/base/Indicator.js.map +1 -1
  19. package/dist/base/StatusDot.js +3 -3
  20. package/dist/base/StatusDot.js.map +1 -1
  21. package/dist/base/Tag.js +5 -5
  22. package/dist/base/Tag.js.map +1 -1
  23. package/dist/base/button-core.js +4 -4
  24. package/dist/base/button-core.js.map +1 -1
  25. package/dist/charts/AreaChart.js +3 -3
  26. package/dist/charts/AreaChart.js.map +1 -1
  27. package/dist/charts/BarChart.js +3 -3
  28. package/dist/charts/BarChart.js.map +1 -1
  29. package/dist/charts/ChordChart.js +3 -3
  30. package/dist/charts/ChordChart.js.map +1 -1
  31. package/dist/charts/ComboChart.js +3 -3
  32. package/dist/charts/ComboChart.js.map +1 -1
  33. package/dist/charts/DonutChart.js +3 -3
  34. package/dist/charts/DonutChart.js.map +1 -1
  35. package/dist/charts/FunnelChart.js +5 -5
  36. package/dist/charts/FunnelChart.js.map +1 -1
  37. package/dist/charts/GraphChart.js +3 -3
  38. package/dist/charts/GraphChart.js.map +1 -1
  39. package/dist/charts/LineChart.js +3 -3
  40. package/dist/charts/LineChart.js.map +1 -1
  41. package/dist/charts/MapChart.js +7 -7
  42. package/dist/charts/MapChart.js.map +1 -1
  43. package/dist/charts/RadarChart.js +16 -15
  44. package/dist/charts/RadarChart.js.map +1 -1
  45. package/dist/charts/SankeyChart.js +3 -3
  46. package/dist/charts/SankeyChart.js.map +1 -1
  47. package/dist/charts/ScatterChart.js +3 -3
  48. package/dist/charts/ScatterChart.js.map +1 -1
  49. package/dist/charts/TimelineChart.js +6 -5
  50. package/dist/charts/TimelineChart.js.map +1 -1
  51. package/dist/charts/TreemapChart.js +3 -3
  52. package/dist/charts/TreemapChart.js.map +1 -1
  53. package/dist/charts/WaterfallChart.js +3 -3
  54. package/dist/charts/WaterfallChart.js.map +1 -1
  55. package/dist/charts/XYChart.js +9 -7
  56. package/dist/charts/XYChart.js.map +1 -1
  57. package/dist/charts/frame.js +10 -8
  58. package/dist/charts/frame.js.map +1 -1
  59. package/dist/charts/single.js +4 -3
  60. package/dist/charts/single.js.map +1 -1
  61. package/dist/code-editor/CodeEditor.d.ts +18 -0
  62. package/dist/code-editor/CodeEditor.js +57 -0
  63. package/dist/code-editor/CodeEditor.js.map +1 -0
  64. package/dist/code-editor/editor.d.ts +52 -0
  65. package/dist/code-editor/editor.js +225 -0
  66. package/dist/code-editor/editor.js.map +1 -0
  67. package/dist/code-editor/index.d.ts +9 -0
  68. package/dist/code-editor/index.js +3 -0
  69. package/dist/config/Provider.d.ts +3 -1
  70. package/dist/config/Provider.js +9 -4
  71. package/dist/config/Provider.js.map +1 -1
  72. package/dist/config/context.d.ts +18 -0
  73. package/dist/config/context.js +16 -1
  74. package/dist/config/context.js.map +1 -1
  75. package/dist/config/createUi.d.ts +20 -3
  76. package/dist/config/createUi.js +80 -49
  77. package/dist/config/createUi.js.map +1 -1
  78. package/dist/config/lang/en-US.js +21 -3
  79. package/dist/config/lang/en-US.js.map +1 -1
  80. package/dist/config/lang/format.d.ts +2 -1
  81. package/dist/config/lang/format.js +9 -2
  82. package/dist/config/lang/format.js.map +1 -1
  83. package/dist/config/lang/lang.d.ts +19 -6
  84. package/dist/config/lang/lang.js +11 -2
  85. package/dist/config/lang/lang.js.map +1 -1
  86. package/dist/config/lang/zh-CN.js +21 -3
  87. package/dist/config/lang/zh-CN.js.map +1 -1
  88. package/dist/config/layout/preference.d.ts +43 -0
  89. package/dist/config/layout/preference.js +108 -0
  90. package/dist/config/layout/preference.js.map +1 -0
  91. package/dist/date/Calendar.js +3 -3
  92. package/dist/date/Calendar.js.map +1 -1
  93. package/dist/date/CalendarBoard.js +9 -9
  94. package/dist/date/CalendarBoard.js.map +1 -1
  95. package/dist/date/CalendarView.js +7 -7
  96. package/dist/date/CalendarView.js.map +1 -1
  97. package/dist/date/DateField.js +3 -3
  98. package/dist/date/DateField.js.map +1 -1
  99. package/dist/date/DatePicker.js +5 -5
  100. package/dist/date/DatePicker.js.map +1 -1
  101. package/dist/date/DateRangePicker.js +5 -5
  102. package/dist/date/DateRangePicker.js.map +1 -1
  103. package/dist/date/DateSegmentGroup.js +5 -5
  104. package/dist/date/DateSegmentGroup.js.map +1 -1
  105. package/dist/date/QuarterCalendar.js +6 -6
  106. package/dist/date/QuarterCalendar.js.map +1 -1
  107. package/dist/date/RangeCalendar.js +3 -3
  108. package/dist/date/RangeCalendar.js.map +1 -1
  109. package/dist/date/SegmentedField.js +3 -3
  110. package/dist/date/SegmentedField.js.map +1 -1
  111. package/dist/date/TimeField.js +3 -3
  112. package/dist/date/TimeField.js.map +1 -1
  113. package/dist/date/TimePicker.js +4 -4
  114. package/dist/date/TimePicker.js.map +1 -1
  115. package/dist/date/date-segments.js +1 -1
  116. package/dist/date/date-segments.js.map +1 -1
  117. package/dist/date/picker-popover.js +3 -2
  118. package/dist/date/picker-popover.js.map +1 -1
  119. package/dist/diagram/Diagram.js +12 -12
  120. package/dist/diagram/Diagram.js.map +1 -1
  121. package/dist/diagram/DiagramLanes.js +3 -3
  122. package/dist/diagram/DiagramLanes.js.map +1 -1
  123. package/dist/diagram/DiagramMinimap.js +4 -4
  124. package/dist/diagram/DiagramMinimap.js.map +1 -1
  125. package/dist/diagram/index.d.ts +2 -1
  126. package/dist/diagram/index.js +2 -1
  127. package/dist/diagram/layout.d.ts +57 -0
  128. package/dist/diagram/layout.js +50 -0
  129. package/dist/diagram/layout.js.map +1 -0
  130. package/dist/display/Accordion.js +6 -6
  131. package/dist/display/Accordion.js.map +1 -1
  132. package/dist/display/AnimatedNumber.js +4 -4
  133. package/dist/display/AnimatedNumber.js.map +1 -1
  134. package/dist/display/Avatar.js +4 -4
  135. package/dist/display/Avatar.js.map +1 -1
  136. package/dist/display/Checklist.js +7 -7
  137. package/dist/display/Checklist.js.map +1 -1
  138. package/dist/display/Collapse.js +8 -5
  139. package/dist/display/Collapse.js.map +1 -1
  140. package/dist/display/Collapsible.js +3 -3
  141. package/dist/display/Collapsible.js.map +1 -1
  142. package/dist/display/Descriptions.js +5 -5
  143. package/dist/display/Descriptions.js.map +1 -1
  144. package/dist/display/Ellipsis.js +3 -3
  145. package/dist/display/Ellipsis.js.map +1 -1
  146. package/dist/display/FieldCompare.js +4 -4
  147. package/dist/display/FieldCompare.js.map +1 -1
  148. package/dist/display/Gauge.js +11 -11
  149. package/dist/display/Gauge.js.map +1 -1
  150. package/dist/display/Image.js +4 -4
  151. package/dist/display/Image.js.map +1 -1
  152. package/dist/display/Marquee.js +3 -3
  153. package/dist/display/Marquee.js.map +1 -1
  154. package/dist/display/ProportionBar.js +4 -4
  155. package/dist/display/ProportionBar.js.map +1 -1
  156. package/dist/display/Sortable.js +4 -4
  157. package/dist/display/Sortable.js.map +1 -1
  158. package/dist/display/Sparkline.js +6 -6
  159. package/dist/display/Sparkline.js.map +1 -1
  160. package/dist/display/Stat.js +3 -3
  161. package/dist/display/Stat.js.map +1 -1
  162. package/dist/display/Timeline.js +7 -7
  163. package/dist/display/Timeline.js.map +1 -1
  164. package/dist/display/Tree.js +10 -10
  165. package/dist/display/Tree.js.map +1 -1
  166. package/dist/display/VirtualList.js +7 -7
  167. package/dist/display/VirtualList.js.map +1 -1
  168. package/dist/display/Watermark.js +3 -3
  169. package/dist/display/Watermark.js.map +1 -1
  170. package/dist/docs-kit/CodeGroup.js +5 -5
  171. package/dist/docs-kit/CodeGroup.js.map +1 -1
  172. package/dist/docs-kit/CodePreview.js +6 -6
  173. package/dist/docs-kit/CodePreview.js.map +1 -1
  174. package/dist/docs-kit/PropsTable.js +4 -4
  175. package/dist/docs-kit/PropsTable.js.map +1 -1
  176. package/dist/feedback/Alert.js +5 -5
  177. package/dist/feedback/Alert.js.map +1 -1
  178. package/dist/feedback/Banner.js +5 -5
  179. package/dist/feedback/Banner.js.map +1 -1
  180. package/dist/feedback/Empty.js +4 -4
  181. package/dist/feedback/Empty.js.map +1 -1
  182. package/dist/feedback/LoadingBar.js +20 -13
  183. package/dist/feedback/LoadingBar.js.map +1 -1
  184. package/dist/feedback/LoadingOverlay.js +3 -3
  185. package/dist/feedback/LoadingOverlay.js.map +1 -1
  186. package/dist/feedback/Progress.js +14 -14
  187. package/dist/feedback/Progress.js.map +1 -1
  188. package/dist/feedback/Result.js +4 -4
  189. package/dist/feedback/Result.js.map +1 -1
  190. package/dist/feedback/SkeletonText.js +3 -3
  191. package/dist/feedback/SkeletonText.js.map +1 -1
  192. package/dist/feedback/Toast.js +6 -6
  193. package/dist/feedback/Toast.js.map +1 -1
  194. package/dist/form/Field.d.ts +7 -0
  195. package/dist/form/Field.js +20 -9
  196. package/dist/form/Field.js.map +1 -1
  197. package/dist/form/Form.js +3 -3
  198. package/dist/form/Form.js.map +1 -1
  199. package/dist/form/FormErrorSummary.js +3 -3
  200. package/dist/form/FormErrorSummary.js.map +1 -1
  201. package/dist/form/FormSection.js +6 -6
  202. package/dist/form/FormSection.js.map +1 -1
  203. package/dist/form/useForm.d.ts +4 -1
  204. package/dist/form/useForm.js +35 -13
  205. package/dist/form/useForm.js.map +1 -1
  206. package/dist/index.d.ts +18 -10
  207. package/dist/index.js +17 -9
  208. package/dist/input/Autocomplete.js +3 -3
  209. package/dist/input/Autocomplete.js.map +1 -1
  210. package/dist/input/Cascader.js +7 -7
  211. package/dist/input/Cascader.js.map +1 -1
  212. package/dist/input/CharacterCount.js +3 -3
  213. package/dist/input/CharacterCount.js.map +1 -1
  214. package/dist/input/Checkbox.js +5 -5
  215. package/dist/input/Checkbox.js.map +1 -1
  216. package/dist/input/ColorField.js +4 -4
  217. package/dist/input/ColorField.js.map +1 -1
  218. package/dist/input/Combobox.js +5 -5
  219. package/dist/input/Combobox.js.map +1 -1
  220. package/dist/input/ConditionBuilder.js +15 -14
  221. package/dist/input/ConditionBuilder.js.map +1 -1
  222. package/dist/input/FileDrop.js +3 -3
  223. package/dist/input/FileDrop.js.map +1 -1
  224. package/dist/input/Listbox.js +9 -9
  225. package/dist/input/Listbox.js.map +1 -1
  226. package/dist/input/Mentions.js +4 -4
  227. package/dist/input/Mentions.js.map +1 -1
  228. package/dist/input/NumberField.js +3 -3
  229. package/dist/input/NumberField.js.map +1 -1
  230. package/dist/input/NumberRangeField.js +5 -5
  231. package/dist/input/NumberRangeField.js.map +1 -1
  232. package/dist/input/OtpField.js +5 -5
  233. package/dist/input/OtpField.js.map +1 -1
  234. package/dist/input/PeoplePicker.js +6 -6
  235. package/dist/input/PeoplePicker.js.map +1 -1
  236. package/dist/input/PeoplePickerPanel.js +15 -15
  237. package/dist/input/PeoplePickerPanel.js.map +1 -1
  238. package/dist/input/Radio.js +4 -4
  239. package/dist/input/Radio.js.map +1 -1
  240. package/dist/input/Rating.js +5 -5
  241. package/dist/input/Rating.js.map +1 -1
  242. package/dist/input/Select.js +5 -5
  243. package/dist/input/Select.js.map +1 -1
  244. package/dist/input/SelectedTags.js +4 -4
  245. package/dist/input/SelectedTags.js.map +1 -1
  246. package/dist/input/Slider.js +6 -6
  247. package/dist/input/Slider.js.map +1 -1
  248. package/dist/input/Switch.js +3 -3
  249. package/dist/input/Switch.js.map +1 -1
  250. package/dist/input/TagsInput.js +5 -5
  251. package/dist/input/TagsInput.js.map +1 -1
  252. package/dist/input/TextField.js +5 -5
  253. package/dist/input/TextField.js.map +1 -1
  254. package/dist/input/Textarea.js +4 -4
  255. package/dist/input/Textarea.js.map +1 -1
  256. package/dist/input/ToggleGroup.js +4 -4
  257. package/dist/input/ToggleGroup.js.map +1 -1
  258. package/dist/input/Transfer.js +8 -8
  259. package/dist/input/Transfer.js.map +1 -1
  260. package/dist/input/TreeSelect.js +7 -7
  261. package/dist/input/TreeSelect.js.map +1 -1
  262. package/dist/input/Upload.js +10 -9
  263. package/dist/input/Upload.js.map +1 -1
  264. package/dist/input/condition.d.ts +1 -1
  265. package/dist/input/condition.js +32 -14
  266. package/dist/input/condition.js.map +1 -1
  267. package/dist/input/people.d.ts +15 -14
  268. package/dist/input/people.js +5 -5
  269. package/dist/input/people.js.map +1 -1
  270. package/dist/input/remote-items.d.ts +4 -2
  271. package/dist/input/remote-items.js +7 -2
  272. package/dist/input/remote-items.js.map +1 -1
  273. package/dist/layout/Affix.js +4 -4
  274. package/dist/layout/Affix.js.map +1 -1
  275. package/dist/layout/ResizeHandle.d.ts +6 -2
  276. package/dist/layout/ResizeHandle.js +32 -9
  277. package/dist/layout/ResizeHandle.js.map +1 -1
  278. package/dist/layout/ScrollArea.js +3 -3
  279. package/dist/layout/ScrollArea.js.map +1 -1
  280. package/dist/layout/Separator.js +3 -3
  281. package/dist/layout/Separator.js.map +1 -1
  282. package/dist/layout/Splitter.js +3 -3
  283. package/dist/layout/Splitter.js.map +1 -1
  284. package/dist/layout/ViewportFill.d.ts +2 -2
  285. package/dist/layout/ViewportFill.js +4 -4
  286. package/dist/layout/ViewportFill.js.map +1 -1
  287. package/dist/navigation/Breadcrumbs.js +4 -4
  288. package/dist/navigation/Breadcrumbs.js.map +1 -1
  289. package/dist/navigation/NavBar.js +6 -6
  290. package/dist/navigation/NavBar.js.map +1 -1
  291. package/dist/navigation/NavList.d.ts +1 -0
  292. package/dist/navigation/NavList.js +20 -12
  293. package/dist/navigation/NavList.js.map +1 -1
  294. package/dist/navigation/NavMenu.d.ts +27 -0
  295. package/dist/navigation/NavMenu.js +54 -0
  296. package/dist/navigation/NavMenu.js.map +1 -0
  297. package/dist/navigation/PageJump.js +3 -3
  298. package/dist/navigation/PageJump.js.map +1 -1
  299. package/dist/navigation/PageSizeSelect.js +4 -4
  300. package/dist/navigation/PageSizeSelect.js.map +1 -1
  301. package/dist/navigation/Pagination.js +6 -6
  302. package/dist/navigation/Pagination.js.map +1 -1
  303. package/dist/navigation/PaginationBar.js +5 -5
  304. package/dist/navigation/PaginationBar.js.map +1 -1
  305. package/dist/navigation/Steps.js +4 -4
  306. package/dist/navigation/Steps.js.map +1 -1
  307. package/dist/navigation/TableOfContents.js +5 -5
  308. package/dist/navigation/TableOfContents.js.map +1 -1
  309. package/dist/navigation/Tabs.js +7 -7
  310. package/dist/navigation/Tabs.js.map +1 -1
  311. package/dist/navigation/Toolbar.js +3 -3
  312. package/dist/navigation/Toolbar.js.map +1 -1
  313. package/dist/overlay/AlertDialog.js +4 -4
  314. package/dist/overlay/AlertDialog.js.map +1 -1
  315. package/dist/overlay/CommandPalette.js +4 -4
  316. package/dist/overlay/CommandPalette.js.map +1 -1
  317. package/dist/overlay/ContextMenu.js +3 -3
  318. package/dist/overlay/ContextMenu.js.map +1 -1
  319. package/dist/overlay/Dialog.js +4 -4
  320. package/dist/overlay/Dialog.js.map +1 -1
  321. package/dist/overlay/Drawer.js +5 -5
  322. package/dist/overlay/Drawer.js.map +1 -1
  323. package/dist/overlay/HoverCard.js +5 -3
  324. package/dist/overlay/HoverCard.js.map +1 -1
  325. package/dist/overlay/Lightbox.js +5 -5
  326. package/dist/overlay/Lightbox.js.map +1 -1
  327. package/dist/overlay/Menu.js +7 -7
  328. package/dist/overlay/Menu.js.map +1 -1
  329. package/dist/overlay/ModalCore.js +9 -9
  330. package/dist/overlay/ModalCore.js.map +1 -1
  331. package/dist/overlay/Popconfirm.js +6 -6
  332. package/dist/overlay/Popconfirm.js.map +1 -1
  333. package/dist/overlay/Popover.js +5 -3
  334. package/dist/overlay/Popover.js.map +1 -1
  335. package/dist/overlay/Tooltip.js +5 -3
  336. package/dist/overlay/Tooltip.js.map +1 -1
  337. package/dist/overlay/Tour.js +8 -8
  338. package/dist/overlay/Tour.js.map +1 -1
  339. package/dist/overlay/detached.d.ts +2 -0
  340. package/dist/overlay/detached.js +73 -42
  341. package/dist/overlay/detached.js.map +1 -1
  342. package/dist/patterns/ActionBar.js +3 -3
  343. package/dist/patterns/ActionBar.js.map +1 -1
  344. package/dist/patterns/AppShell.d.ts +28 -1
  345. package/dist/patterns/AppShell.js +158 -52
  346. package/dist/patterns/AppShell.js.map +1 -1
  347. package/dist/patterns/AuthLayout.d.ts +28 -0
  348. package/dist/patterns/AuthLayout.js +77 -0
  349. package/dist/patterns/AuthLayout.js.map +1 -0
  350. package/dist/patterns/CommentThread.js +9 -9
  351. package/dist/patterns/CommentThread.js.map +1 -1
  352. package/dist/patterns/DataImport.js +4 -4
  353. package/dist/patterns/DataImport.js.map +1 -1
  354. package/dist/patterns/DeadlineBadge.js +3 -3
  355. package/dist/patterns/DeadlineBadge.js.map +1 -1
  356. package/dist/patterns/FilterBar.d.ts +11 -1
  357. package/dist/patterns/FilterBar.js +39 -10
  358. package/dist/patterns/FilterBar.js.map +1 -1
  359. package/dist/patterns/FormDialog.d.ts +18 -0
  360. package/dist/patterns/FormDialog.js +46 -0
  361. package/dist/patterns/FormDialog.js.map +1 -0
  362. package/dist/patterns/KanbanBoard.js +8 -8
  363. package/dist/patterns/KanbanBoard.js.map +1 -1
  364. package/dist/patterns/LayoutSwitcher.d.ts +12 -0
  365. package/dist/patterns/LayoutSwitcher.js +79 -0
  366. package/dist/patterns/LayoutSwitcher.js.map +1 -0
  367. package/dist/patterns/NotificationCenter.js +8 -8
  368. package/dist/patterns/NotificationCenter.js.map +1 -1
  369. package/dist/patterns/PageTabs.d.ts +12 -7
  370. package/dist/patterns/PageTabs.js +41 -29
  371. package/dist/patterns/PageTabs.js.map +1 -1
  372. package/dist/patterns/QueryTable.d.ts +10 -1
  373. package/dist/patterns/QueryTable.js +128 -68
  374. package/dist/patterns/QueryTable.js.map +1 -1
  375. package/dist/patterns/SlideCaptcha.d.ts +80 -0
  376. package/dist/patterns/SlideCaptcha.js +354 -0
  377. package/dist/patterns/SlideCaptcha.js.map +1 -0
  378. package/dist/patterns/StepsForm.js +7 -7
  379. package/dist/patterns/StepsForm.js.map +1 -1
  380. package/dist/patterns/ThemeSwitcher.js +3 -3
  381. package/dist/patterns/ThemeSwitcher.js.map +1 -1
  382. package/dist/patterns/index.d.ts +7 -3
  383. package/dist/patterns/index.js +5 -1
  384. package/dist/patterns/messages.d.ts +39 -1
  385. package/dist/patterns/messages.js +40 -2
  386. package/dist/patterns/messages.js.map +1 -1
  387. package/dist/table/ColumnHeaderActions.js +3 -3
  388. package/dist/table/ColumnHeaderActions.js.map +1 -1
  389. package/dist/table/ColumnResizer.js +3 -3
  390. package/dist/table/ColumnResizer.js.map +1 -1
  391. package/dist/table/ColumnSettings.js +5 -5
  392. package/dist/table/ColumnSettings.js.map +1 -1
  393. package/dist/table/ColumnTable.js +8 -8
  394. package/dist/table/ColumnTable.js.map +1 -1
  395. package/dist/table/DataTable.js +8 -8
  396. package/dist/table/DataTable.js.map +1 -1
  397. package/dist/table/DataTableView.js +21 -21
  398. package/dist/table/DataTableView.js.map +1 -1
  399. package/dist/table/PivotTable.js +3 -3
  400. package/dist/table/PivotTable.js.map +1 -1
  401. package/dist/table/SelectionBar.js +4 -4
  402. package/dist/table/SelectionBar.js.map +1 -1
  403. package/dist/table/TreeDataTable.js +5 -5
  404. package/dist/table/TreeDataTable.js.map +1 -1
  405. package/dist/theme-customize/ThemeCustomizer.js +7 -6
  406. package/dist/theme-customize/ThemeCustomizer.js.map +1 -1
  407. package/dist/theme-customize/ThemeThumbnail.js +3 -3
  408. package/dist/theme-customize/ThemeThumbnail.js.map +1 -1
  409. package/dist/three/background/AuroraBackground.js +3 -3
  410. package/dist/three/background/AuroraBackground.js.map +1 -1
  411. package/dist/three/background/MeshGradient.js +3 -3
  412. package/dist/three/background/MeshGradient.js.map +1 -1
  413. package/dist/three/background/ShaderBackground.js +3 -3
  414. package/dist/three/background/ShaderBackground.js.map +1 -1
  415. package/dist/three/core/EffectSurface.js +3 -3
  416. package/dist/three/core/EffectSurface.js.map +1 -1
  417. package/dist/three/core/ThreeCanvas.js +4 -4
  418. package/dist/three/core/ThreeCanvas.js.map +1 -1
  419. package/dist/three/effects/Confetti.js +3 -3
  420. package/dist/three/effects/Confetti.js.map +1 -1
  421. package/dist/three/effects/ParticleField.js +3 -3
  422. package/dist/three/effects/ParticleField.js.map +1 -1
  423. package/dist/three/effects/WaveGrid.js +3 -3
  424. package/dist/three/effects/WaveGrid.js.map +1 -1
  425. package/dist/three/globe/Globe.js +3 -3
  426. package/dist/three/globe/Globe.js.map +1 -1
  427. package/dist/three/model/ModelViewer.js +3 -3
  428. package/dist/three/model/ModelViewer.js.map +1 -1
  429. package/dist/utils/data/clone.d.ts +8 -0
  430. package/dist/utils/data/clone.js +21 -0
  431. package/dist/utils/data/clone.js.map +1 -0
  432. package/dist/utils/data/date.d.ts +10 -0
  433. package/dist/utils/data/date.js +13 -1
  434. package/dist/utils/data/date.js.map +1 -1
  435. package/dist/utils/data/number.d.ts +5 -0
  436. package/dist/utils/data/number.js +8 -1
  437. package/dist/utils/data/number.js.map +1 -1
  438. package/dist/utils/data/numeric.d.ts +7 -0
  439. package/dist/utils/data/numeric.js +46 -1
  440. package/dist/utils/data/numeric.js.map +1 -1
  441. package/dist/utils/dom/download.d.ts +8 -1
  442. package/dist/utils/dom/download.js +19 -2
  443. package/dist/utils/dom/download.js.map +1 -1
  444. package/dist/utils/dom/element.d.ts +3 -1
  445. package/dist/utils/dom/element.js +8 -4
  446. package/dist/utils/dom/element.js.map +1 -1
  447. package/dist/utils/dom/fullscreen.d.ts +1 -1
  448. package/dist/utils/dom/fullscreen.js +12 -8
  449. package/dist/utils/dom/fullscreen.js.map +1 -1
  450. package/dist/utils/dom/mounted.d.ts +7 -0
  451. package/dist/utils/dom/mounted.js +16 -0
  452. package/dist/utils/dom/mounted.js.map +1 -0
  453. package/dist/utils/dom/overflow.js +2 -1
  454. package/dist/utils/dom/overflow.js.map +1 -1
  455. package/dist/utils/dom/pan-zoom.js +2 -1
  456. package/dist/utils/dom/pan-zoom.js.map +1 -1
  457. package/dist/utils/props.js +3 -13
  458. package/dist/utils/props.js.map +1 -1
  459. package/dist/utils/request/error-message.d.ts +17 -0
  460. package/dist/utils/request/error-message.js +50 -0
  461. package/dist/utils/request/error-message.js.map +1 -0
  462. package/dist/utils/request/http.d.ts +80 -4
  463. package/dist/utils/request/http.js +121 -24
  464. package/dist/utils/request/http.js.map +1 -1
  465. package/dist/utils/request/use-autosave.d.ts +35 -0
  466. package/dist/utils/request/use-autosave.js +69 -0
  467. package/dist/utils/request/use-autosave.js.map +1 -0
  468. package/dist/utils/request/use-request.js +4 -2
  469. package/dist/utils/request/use-request.js.map +1 -1
  470. package/package.json +57 -4
@@ -0,0 +1,57 @@
1
+ /**
2
+ * 分层自动排版:从根节点沿连线走,按最长步数从左往右分列,同一列从上往下排,每列在最高的那列里垂直居中。
3
+ * 绕回去的线(环)不算步数,否则会越排越远;不该影响排版的线(流程图的退回、提级)由调用方先去掉。
4
+ * 已经有位置的节点用它自己的 x、y(只给了一个时另一个照排),照样占一个格子。流程图、审批链、简单的依赖图都够用。
5
+ *
6
+ * const placed = layoutLayers(
7
+ * nodes.map((n) => ({ id: n.id, width: 140, height: 52 })),
8
+ * edges.filter((e) => e.kind !== 'return'),
9
+ * { roots: ['start'] },
10
+ * );
11
+ */
12
+ /** 要排的一个节点:大小,已有的位置 */
13
+ export interface LayerNode {
14
+ /** 节点的标识,连线按它连 */
15
+ readonly id: string;
16
+ /** 宽 */
17
+ readonly width: number;
18
+ /** 高 */
19
+ readonly height: number;
20
+ /** 已有的横坐标(左上角);没有时排出来 */
21
+ readonly x?: number | null;
22
+ /** 已有的纵坐标(左上角);没有时排出来 */
23
+ readonly y?: number | null;
24
+ }
25
+ /** 一条连线:从哪到哪 */
26
+ export interface LayerEdge {
27
+ /** 起点节点的标识 */
28
+ readonly from: string;
29
+ /** 终点节点的标识 */
30
+ readonly to: string;
31
+ }
32
+ /** 排好的一个节点(画布坐标) */
33
+ export interface PlacedLayerNode {
34
+ /** 节点的标识 */
35
+ readonly id: string;
36
+ /** 横坐标(左上角) */
37
+ readonly x: number;
38
+ /** 纵坐标(左上角) */
39
+ readonly y: number;
40
+ /** 宽 */
41
+ readonly width: number;
42
+ /** 高 */
43
+ readonly height: number;
44
+ }
45
+ /** layoutLayers 的选项 */
46
+ export interface LayerOptions {
47
+ /** 从这些节点开始走(流程的开始节点);没走到的节点之后各自起头 */
48
+ roots?: readonly string[];
49
+ /** 列距(相邻两列左边的距离),默认 190 */
50
+ columnGap?: number;
51
+ /** 行距(相邻两行上边的距离),默认 96 */
52
+ rowGap?: number;
53
+ /** 画布边距,默认 32 */
54
+ margin?: number;
55
+ }
56
+ /** 排好每个节点的位置,按传入的先后返回 */
57
+ export declare function layoutLayers(nodes: readonly LayerNode[], edges: readonly LayerEdge[], { roots, columnGap, rowGap, margin }?: LayerOptions): PlacedLayerNode[];
@@ -0,0 +1,50 @@
1
+ //#region src/diagram/layout.ts
2
+ /** 排好每个节点的位置,按传入的先后返回 */
3
+ function layoutLayers(nodes, edges, { roots = [], columnGap = 190, rowGap = 96, margin = 32 } = {}) {
4
+ const ids = nodes.map((n) => n.id);
5
+ const forward = new Map(ids.map((id) => [id, []]));
6
+ for (const edge of edges) forward.get(edge.from)?.push(edge.to);
7
+ const back = /* @__PURE__ */ new Set();
8
+ const state = /* @__PURE__ */ new Map();
9
+ const order = [];
10
+ const visit = (id) => {
11
+ state.set(id, "visiting");
12
+ for (const next of forward.get(id) ?? []) if (state.get(next) === "visiting") back.add(`${id}>${next}`);
13
+ else if (!state.has(next)) visit(next);
14
+ state.set(id, "done");
15
+ order.unshift(id);
16
+ };
17
+ for (const id of [...roots, ...ids]) if (forward.has(id) && !state.has(id)) visit(id);
18
+ const column = new Map(ids.map((id) => [id, 0]));
19
+ for (const id of order) for (const next of forward.get(id) ?? []) {
20
+ if (back.has(`${id}>${next}`)) continue;
21
+ column.set(next, Math.max(column.get(next) ?? 0, (column.get(id) ?? 0) + 1));
22
+ }
23
+ const cellWidth = Math.max(0, ...nodes.map((n) => n.width));
24
+ const cellHeight = Math.max(0, ...nodes.map((n) => n.height));
25
+ const rows = /* @__PURE__ */ new Map();
26
+ for (const id of order) {
27
+ const c = column.get(id) ?? 0;
28
+ rows.set(c, [...rows.get(c) ?? [], id]);
29
+ }
30
+ const tallest = Math.max(1, ...[...rows.values()].map((r) => r.length));
31
+ const byId = new Map(nodes.map((n) => [n.id, n]));
32
+ const placed = /* @__PURE__ */ new Map();
33
+ for (const [c, members] of rows) members.forEach((id, i) => {
34
+ const node = byId.get(id);
35
+ const x = node.x ?? margin + c * columnGap + (cellWidth - node.width) / 2;
36
+ const y = node.y ?? margin + (i + (tallest - members.length) / 2) * rowGap + (cellHeight - node.height) / 2;
37
+ placed.set(id, {
38
+ id,
39
+ x,
40
+ y,
41
+ width: node.width,
42
+ height: node.height
43
+ });
44
+ });
45
+ return nodes.map((n) => placed.get(n.id));
46
+ }
47
+ //#endregion
48
+ export { layoutLayers };
49
+
50
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.js","names":[],"sources":["../../src/diagram/layout.ts"],"sourcesContent":["/**\n * 分层自动排版:从根节点沿连线走,按最长步数从左往右分列,同一列从上往下排,每列在最高的那列里垂直居中。\n * 绕回去的线(环)不算步数,否则会越排越远;不该影响排版的线(流程图的退回、提级)由调用方先去掉。\n * 已经有位置的节点用它自己的 x、y(只给了一个时另一个照排),照样占一个格子。流程图、审批链、简单的依赖图都够用。\n *\n * const placed = layoutLayers(\n * nodes.map((n) => ({ id: n.id, width: 140, height: 52 })),\n * edges.filter((e) => e.kind !== 'return'),\n * { roots: ['start'] },\n * );\n */\n\n/** 要排的一个节点:大小,已有的位置 */\nexport interface LayerNode {\n /** 节点的标识,连线按它连 */\n readonly id: string;\n /** 宽 */\n readonly width: number;\n /** 高 */\n readonly height: number;\n /** 已有的横坐标(左上角);没有时排出来 */\n readonly x?: number | null;\n /** 已有的纵坐标(左上角);没有时排出来 */\n readonly y?: number | null;\n}\n\n/** 一条连线:从哪到哪 */\nexport interface LayerEdge {\n /** 起点节点的标识 */\n readonly from: string;\n /** 终点节点的标识 */\n readonly to: string;\n}\n\n/** 排好的一个节点(画布坐标) */\nexport interface PlacedLayerNode {\n /** 节点的标识 */\n readonly id: string;\n /** 横坐标(左上角) */\n readonly x: number;\n /** 纵坐标(左上角) */\n readonly y: number;\n /** 宽 */\n readonly width: number;\n /** 高 */\n readonly height: number;\n}\n\n/** layoutLayers 的选项 */\nexport interface LayerOptions {\n /** 从这些节点开始走(流程的开始节点);没走到的节点之后各自起头 */\n roots?: readonly string[];\n /** 列距(相邻两列左边的距离),默认 190 */\n columnGap?: number;\n /** 行距(相邻两行上边的距离),默认 96 */\n rowGap?: number;\n /** 画布边距,默认 32 */\n margin?: number;\n}\n\n/** 排好每个节点的位置,按传入的先后返回 */\nexport function layoutLayers(\n nodes: readonly LayerNode[],\n edges: readonly LayerEdge[],\n { roots = [], columnGap = 190, rowGap = 96, margin = 32 }: LayerOptions = {},\n): PlacedLayerNode[] {\n const ids = nodes.map((n) => n.id);\n const forward = new Map<string, string[]>(ids.map((id) => [id, []]));\n for (const edge of edges) forward.get(edge.from)?.push(edge.to);\n\n // 深度优先找出绕回去的线(指向还在路上的节点),去掉它们之后是无环的\n const back = new Set<string>();\n const state = new Map<string, 'visiting' | 'done'>();\n const order: string[] = [];\n const visit = (id: string) => {\n state.set(id, 'visiting');\n for (const next of forward.get(id) ?? []) {\n if (state.get(next) === 'visiting') back.add(`${id}>${next}`);\n else if (!state.has(next)) visit(next);\n }\n state.set(id, 'done');\n order.unshift(id);\n };\n for (const id of [...roots, ...ids]) if (forward.has(id) && !state.has(id)) visit(id);\n\n // 按拓扑序算最长步数:列号\n const column = new Map<string, number>(ids.map((id) => [id, 0]));\n for (const id of order) {\n for (const next of forward.get(id) ?? []) {\n if (back.has(`${id}>${next}`)) continue;\n column.set(next, Math.max(column.get(next) ?? 0, (column.get(id) ?? 0) + 1));\n }\n }\n\n // 每个格子按最大的节点算,节点在格子里居中\n const cellWidth = Math.max(0, ...nodes.map((n) => n.width));\n const cellHeight = Math.max(0, ...nodes.map((n) => n.height));\n const rows = new Map<number, string[]>();\n for (const id of order) {\n const c = column.get(id) ?? 0;\n rows.set(c, [...(rows.get(c) ?? []), id]);\n }\n const tallest = Math.max(1, ...[...rows.values()].map((r) => r.length));\n const byId = new Map(nodes.map((n) => [n.id, n]));\n const placed = new Map<string, PlacedLayerNode>();\n for (const [c, members] of rows) {\n members.forEach((id, i) => {\n const node = byId.get(id)!;\n const x = node.x ?? margin + c * columnGap + (cellWidth - node.width) / 2;\n const y =\n node.y ??\n margin + (i + (tallest - members.length) / 2) * rowGap + (cellHeight - node.height) / 2;\n placed.set(id, { id, x, y, width: node.width, height: node.height });\n });\n }\n return nodes.map((n) => placed.get(n.id)!);\n}\n"],"mappings":";;AA6DA,SAAgB,aACd,OACA,OACA,EAAE,QAAQ,CAAC,GAAG,YAAY,KAAK,SAAS,IAAI,SAAS,OAAqB,CAAC,GACxD;CACnB,MAAM,MAAM,MAAM,KAAK,MAAM,EAAE,EAAE;CACjC,MAAM,UAAU,IAAI,IAAsB,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;CACnE,KAAK,MAAM,QAAQ,OAAO,QAAQ,IAAI,KAAK,IAAI,CAAC,EAAE,KAAK,KAAK,EAAE;CAG9D,MAAM,uBAAO,IAAI,IAAY;CAC7B,MAAM,wBAAQ,IAAI,IAAiC;CACnD,MAAM,QAAkB,CAAC;CACzB,MAAM,SAAS,OAAe;EAC5B,MAAM,IAAI,IAAI,UAAU;EACxB,KAAK,MAAM,QAAQ,QAAQ,IAAI,EAAE,KAAK,CAAC,GACrC,IAAI,MAAM,IAAI,IAAI,MAAM,YAAY,KAAK,IAAI,GAAG,GAAG,GAAG,MAAM;OACvD,IAAI,CAAC,MAAM,IAAI,IAAI,GAAG,MAAM,IAAI;EAEvC,MAAM,IAAI,IAAI,MAAM;EACpB,MAAM,QAAQ,EAAE;CAClB;CACA,KAAK,MAAM,MAAM,CAAC,GAAG,OAAO,GAAG,GAAG,GAAG,IAAI,QAAQ,IAAI,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE,GAAG,MAAM,EAAE;CAGpF,MAAM,SAAS,IAAI,IAAoB,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;CAC/D,KAAK,MAAM,MAAM,OACf,KAAK,MAAM,QAAQ,QAAQ,IAAI,EAAE,KAAK,CAAC,GAAG;EACxC,IAAI,KAAK,IAAI,GAAG,GAAG,GAAG,MAAM,GAAG;EAC/B,OAAO,IAAI,MAAM,KAAK,IAAI,OAAO,IAAI,IAAI,KAAK,IAAI,OAAO,IAAI,EAAE,KAAK,KAAK,CAAC,CAAC;CAC7E;CAIF,MAAM,YAAY,KAAK,IAAI,GAAG,GAAG,MAAM,KAAK,MAAM,EAAE,KAAK,CAAC;CAC1D,MAAM,aAAa,KAAK,IAAI,GAAG,GAAG,MAAM,KAAK,MAAM,EAAE,MAAM,CAAC;CAC5D,MAAM,uBAAO,IAAI,IAAsB;CACvC,KAAK,MAAM,MAAM,OAAO;EACtB,MAAM,IAAI,OAAO,IAAI,EAAE,KAAK;EAC5B,KAAK,IAAI,GAAG,CAAC,GAAI,KAAK,IAAI,CAAC,KAAK,CAAC,GAAI,EAAE,CAAC;CAC1C;CACA,MAAM,UAAU,KAAK,IAAI,GAAG,GAAG,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,MAAM,CAAC;CACtE,MAAM,OAAO,IAAI,IAAI,MAAM,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;CAChD,MAAM,yBAAS,IAAI,IAA6B;CAChD,KAAK,MAAM,CAAC,GAAG,YAAY,MACzB,QAAQ,SAAS,IAAI,MAAM;EACzB,MAAM,OAAO,KAAK,IAAI,EAAE;EACxB,MAAM,IAAI,KAAK,KAAK,SAAS,IAAI,aAAa,YAAY,KAAK,SAAS;EACxE,MAAM,IACJ,KAAK,KACL,UAAU,KAAK,UAAU,QAAQ,UAAU,KAAK,UAAU,aAAa,KAAK,UAAU;EACxF,OAAO,IAAI,IAAI;GAAE;GAAI;GAAG;GAAG,OAAO,KAAK;GAAO,QAAQ,KAAK;EAAO,CAAC;CACrE,CAAC;CAEH,OAAO,MAAM,KAAK,MAAM,OAAO,IAAI,EAAE,EAAE,CAAE;AAC3C"}
@@ -5,8 +5,8 @@ import { disclosureStyles } from "../utils/style/transitions.js";
5
5
  import { ButtonBase } from "../base/ButtonBase.js";
6
6
  import { selectedValues, toggleSelection } from "../utils/data/selection.js";
7
7
  import { Collapse } from "./Collapse.js";
8
- import { computed, createVNode, h, isVNode, mergeProps, shallowRef, useId } from "vue";
9
- import { _component, bindable, childrenProp, createContext, forwardChildren, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
8
+ import { computed, createVNode, h, isVNode, shallowRef, useId } from "vue";
9
+ import { _component, bindable, childrenProp, createContext, forwardChildren, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
10
10
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
11
11
  import { ChevronDown } from "@lucide/icons";
12
12
  //#region src/display/Accordion.tsx
@@ -123,7 +123,7 @@ var Accordion = /*#__PURE__*/ _component((_props, _ctx) => {
123
123
  event.preventDefault();
124
124
  next.focus();
125
125
  }
126
- return () => createVNode("div", mergeProps(mergeAttrs({ sx: [accordionStyles.root, size.value && fontSizeStyles[size.value]] }, rest, {
126
+ return () => createVNode("div", mergeJsxProps(mergeAttrs({ sx: [accordionStyles.root, size.value && fontSizeStyles[size.value]] }, rest, {
127
127
  ref: root,
128
128
  onKeydown
129
129
  }), {
@@ -172,7 +172,7 @@ var AccordionItem = /*#__PURE__*/ _component((_props2, _ctx2) => {
172
172
  const open = model.open;
173
173
  const off = disabled.value || accordion.disabled;
174
174
  const state = open ? "open" : "closed";
175
- const trigger = createVNode(ButtonBase, mergeProps(mergePartProps({ sx: [accordionStyles.trigger, off && accordionStyles.triggerDisabled] }, propsTrigger.value, {
175
+ const trigger = createVNode(ButtonBase, mergeJsxProps(mergePartProps({ sx: [accordionStyles.trigger, off && accordionStyles.triggerDisabled] }, propsTrigger.value, {
176
176
  id: triggerId,
177
177
  disabled: off,
178
178
  "aria-expanded": open,
@@ -189,10 +189,10 @@ var AccordionItem = /*#__PURE__*/ _component((_props2, _ctx2) => {
189
189
  open && accordionStyles.chevronOpen
190
190
  ]
191
191
  }, propsChevron.value), null)] });
192
- return createVNode("div", mergeProps(mergeAttrs({ sx: accordionStyles.item }, rest), {
192
+ return createVNode("div", mergeJsxProps(mergeAttrs({ sx: accordionStyles.item }, rest), {
193
193
  "data-state": state,
194
194
  "data-disabled": off || void 0
195
- }), [h(`h${accordion.headingLevel}`, mergeAttrs({ sx: accordionStyles.heading }, propsHeading.value), [trigger]), createVNode(Collapse, mergeProps(mergePartProps({ propsContent: { sx: accordionStyles.content } }, propsContent.value, {
195
+ }), [h(`h${accordion.headingLevel}`, mergeAttrs({ sx: accordionStyles.heading }, propsHeading.value), [trigger]), createVNode(Collapse, mergeJsxProps(mergePartProps({ propsContent: { sx: accordionStyles.content } }, propsContent.value, {
196
196
  id: contentId,
197
197
  role: "region",
198
198
  "aria-labelledby": triggerId
@@ -1 +1 @@
1
- {"version":3,"file":"Accordion.js","names":["_isVNode","_vtp_readonlyProp","_vtp_bindable","_vtp_childrenProp","_vtp_restProps","_vue_shallowRef","_vue_computed","_createVNode","_mergeProps","_vtp_forwardChildren"],"sources":["../../src/display/Accordion.tsx"],"sourcesContent":["/**\n * 手风琴,复合组件:Accordion(div)> AccordionItem(标题按钮 + 展开收起的内容)。WAI-ARIA 的 Accordion 模式:\n * 每个标题是 heading 里的 button(aria-expanded、aria-controls),内容是 role=\"region\"、以标题为名称;\n * 标题都在 Tab 顺序里,另外 ↑ / ↓ 在标题之间移动(到头后循环),Home / End 到第一个、最后一个。参考 Radix Accordion。\n *\n * <Accordion _value={open} aria-label=\"常见问题\">\n * <AccordionItem value=\"ship\" title=\"多久发货?\">付款后 48 小时内。</AccordionItem>\n * <AccordionItem value=\"refund\" title=\"怎么退款?\">…</AccordionItem>\n * </Accordion>\n * <Accordion selectionMode=\"multiple\" _value={openList}>…</Accordion>\n *\n * 展开收起的动画同 Collapsible(Collapse 的 CSS 过渡)。部件见 AccordionItemProps。\n */\nimport { ChevronDown } from '@lucide/icons';\nimport { createContext, _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { h, useId, type VNodeChild } from 'vue';\nimport { ButtonBase, type ButtonBaseProps } from '../base/ButtonBase';\nimport { Icon, type IconProps } from '../base/Icon';\nimport { selectedValues, toggleSelection, type SelectionProps } from '../utils/data/selection';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { disclosureStyles } from '../utils/style/transitions';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\nimport { Collapse, type CollapseProps } from './Collapse';\n\n/** Accordion 交给 AccordionItem 的状态 */\nexport interface AccordionState {\n /** 展开着的项 */\n readonly expanded: readonly string[];\n /** 标题的层级(h2–h6) */\n readonly headingLevel: 2 | 3 | 4 | 5 | 6;\n /** 整组不可用 */\n readonly disabled: boolean;\n /** 展开或收起一项(单开 / 多开的规则由组决定) */\n toggle(value: string): void;\n}\n\n/** Accordion 的上下文:自定义的项可以 inject 它接入组 */\nexport const AccordionContext = createContext<AccordionState>('Accordion');\n\n/** 两种方式共有的属性;未声明的属性落到外层 div 上 */\ninterface AccordionBaseProps extends PartProps<'div'> {\n /** 单开时允许把唯一展开的那项也收起,默认 true */\n collapsible?: boolean;\n /** 标题的层级,按所在页面的大纲选,默认 3 */\n headingLevel?: 2 | 3 | 4 | 5 | 6;\n /** 整组不可用 */\n disabled?: boolean;\n /** 字号档位;不写时继承 */\n size?: TextSize;\n /** AccordionItem */\n children?: VNodeChild;\n}\n\n/** 单开(selectionMode=\"single\",value 是展开项的值)或多开(value 是数组) */\nexport type AccordionProps = AccordionBaseProps & SelectionProps;\n\n/** Accordion 的样式:root、item、heading、trigger、chevron、chevronOpen、content */\nexport const accordionStyles = css.create({\n root: { display: 'flex', flexDirection: 'column' },\n item: {\n borderBottomWidth: '_xs',\n borderBottomStyle: 'solid',\n borderBottomColor: '_borderMuted',\n },\n heading: { margin: 0, fontSize: 'inherit', fontWeight: 'inherit' },\n // 去掉按钮默认外观、焦点环、波纹、颜色过渡由 ButtonBase 给出\n trigger: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '_md',\n width: '_full',\n minHeight: '_minTarget',\n paddingBlock: '_md',\n paddingInline: '_sm',\n borderRadius: '_sm',\n backgroundColor: { default: 'transparent', ':hover': '_fill' },\n color: '_text',\n fontWeight: '_semibold',\n textAlign: 'start',\n },\n triggerDisabled: { opacity: '_disabled' },\n chevron: { flexShrink: 0, color: '_textMuted' },\n chevronOpen: { rotate: '180deg' },\n content: { paddingInline: '_sm', paddingBlockEnd: '_md', color: '_text' },\n});\n\n/** 手风琴:一组可展开收起的项,单开或多开 */\nexport const Accordion = _component(\n ({\n selectionMode = 'single',\n _value: value = _bindable<string | string[] | null>(null),\n collapsible = true,\n headingLevel = 3,\n disabled = false,\n size,\n children,\n ...rest\n }: AccordionProps) => {\n let root = _state.raw<HTMLElement | null>(null);\n const expanded = _derived(selectedValues(value));\n\n AccordionContext.provide({\n get expanded() {\n return expanded;\n },\n get headingLevel() {\n return headingLevel;\n },\n get disabled() {\n return disabled;\n },\n toggle(item) {\n const next = toggleSelection(expanded, item, {\n mode: selectionMode,\n required: !collapsible,\n });\n if (next === expanded) return;\n value = selectionMode === 'multiple' ? [...next] : (next[0] ?? null);\n },\n });\n\n // ↑ / ↓ 在标题之间移动(循环),Home / End 到两端;只在焦点在标题按钮上时处理\n function onKeydown(event: KeyboardEvent) {\n const target = event.target as HTMLElement;\n if (!root || !target.matches('[data-accordion-trigger]')) return;\n const triggers = [\n ...root.querySelectorAll<HTMLButtonElement>('[data-accordion-trigger]:not(:disabled)'),\n ].filter((trigger) => trigger.closest('[data-accordion]') === root);\n const index = triggers.indexOf(target as HTMLButtonElement);\n const next = {\n ArrowDown: triggers[(index + 1) % triggers.length],\n ArrowUp: triggers[(index - 1 + triggers.length) % triggers.length],\n Home: triggers[0],\n End: triggers.at(-1),\n }[event.key];\n if (!next) return;\n event.preventDefault();\n next.focus();\n }\n\n return () => (\n <div\n {...mergeAttrs<'div'>({ sx: [accordionStyles.root, size && fontSizeStyles[size]] }, rest, {\n ref: _toRef(root),\n onKeydown,\n })}\n data-accordion=\"\"\n data-disabled={disabled || undefined}\n >\n {children}\n </div>\n );\n },\n);\n\n/** 未声明的属性落到每一项的外层 div 上 */\nexport interface AccordionItemProps extends PartProps<'div', 'title'> {\n /** 这一项的值 */\n value: string;\n /** 标题 */\n title: VNodeChild;\n /** 不可用:标题按钮 disabled,不能展开收起 */\n disabled?: boolean;\n /** 标题(h2–h6)的部件属性 */\n propsHeading?: PartProps<'h3'>;\n /** 标题按钮的部件属性 */\n propsTrigger?: Omit<Partial<ButtonBaseProps>, 'aria-expanded' | 'aria-controls'>;\n /** 展开箭头的部件属性 */\n propsChevron?: Partial<IconProps>;\n /** 内容区(Collapse,role=\"region\")的部件属性 */\n propsContent?: Partial<CollapseProps>;\n /** 内容 */\n children?: VNodeChild;\n}\n\n/** 手风琴里的一项:标题按钮 + 展开收起的内容 */\nexport const AccordionItem = _component(\n ({\n value,\n title,\n disabled = false,\n propsHeading,\n propsTrigger,\n propsChevron,\n propsContent,\n children,\n ...rest\n }: AccordionItemProps) => {\n const accordion = AccordionContext.inject();\n const id = useId();\n const triggerId = `${id}-trigger`;\n const contentId = `${id}-content`;\n // Collapse 在页内搜索命中(beforematch)时会写回 open:经这个对象交给组切换\n const model = {\n get open() {\n return accordion.expanded.includes(value);\n },\n set open(next: boolean) {\n if (next !== model.open) accordion.toggle(value);\n },\n };\n\n return () => {\n const open = model.open;\n const off = disabled || accordion.disabled;\n const state = open ? 'open' : 'closed';\n const trigger = (\n <ButtonBase\n {...mergePartProps<ButtonBaseProps>(\n { sx: [accordionStyles.trigger, off && accordionStyles.triggerDisabled] },\n propsTrigger,\n {\n id: triggerId,\n disabled: off,\n 'aria-expanded': open,\n 'aria-controls': contentId,\n onClick: () => accordion.toggle(value),\n },\n )}\n data-accordion-trigger=\"\"\n data-state={state}\n >\n <span>{title}</span>\n <Icon\n {...mergePartProps<IconProps>(\n {\n icon: ChevronDown,\n sx: [\n accordionStyles.chevron,\n disclosureStyles.icon,\n open && accordionStyles.chevronOpen,\n ],\n },\n propsChevron,\n )}\n />\n </ButtonBase>\n );\n return (\n <div\n {...mergeAttrs<'div'>({ sx: accordionStyles.item }, rest)}\n data-state={state}\n data-disabled={off || undefined}\n >\n {/* 标签名随 headingLevel,用 h() 渲染 */}\n {h(\n `h${accordion.headingLevel}`,\n mergeAttrs<'h3'>({ sx: accordionStyles.heading }, propsHeading),\n [trigger],\n )}\n <Collapse\n {...mergePartProps<CollapseProps>(\n { propsContent: { sx: accordionStyles.content } },\n propsContent,\n { id: contentId, role: 'region', 'aria-labelledby': triggerId },\n )}\n _open={model.open}\n >\n {children}\n </Collapse>\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"Accordion.js","names":["_isVNode","_vtp_readonlyProp","_vtp_bindable","_vtp_childrenProp","_vtp_restProps","_vue_shallowRef","_vue_computed","_createVNode","_mergeProps","_vtp_forwardChildren"],"sources":["../../src/display/Accordion.tsx"],"sourcesContent":["/**\n * 手风琴,复合组件:Accordion(div)> AccordionItem(标题按钮 + 展开收起的内容)。WAI-ARIA 的 Accordion 模式:\n * 每个标题是 heading 里的 button(aria-expanded、aria-controls),内容是 role=\"region\"、以标题为名称;\n * 标题都在 Tab 顺序里,另外 ↑ / ↓ 在标题之间移动(到头后循环),Home / End 到第一个、最后一个。参考 Radix Accordion。\n *\n * <Accordion _value={open} aria-label=\"常见问题\">\n * <AccordionItem value=\"ship\" title=\"多久发货?\">付款后 48 小时内。</AccordionItem>\n * <AccordionItem value=\"refund\" title=\"怎么退款?\">…</AccordionItem>\n * </Accordion>\n * <Accordion selectionMode=\"multiple\" _value={openList}>…</Accordion>\n *\n * 展开收起的动画同 Collapsible(Collapse 的 CSS 过渡)。部件见 AccordionItemProps。\n */\nimport { ChevronDown } from '@lucide/icons';\nimport { createContext, _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { h, useId, type VNodeChild } from 'vue';\nimport { ButtonBase, type ButtonBaseProps } from '../base/ButtonBase';\nimport { Icon, type IconProps } from '../base/Icon';\nimport { selectedValues, toggleSelection, type SelectionProps } from '../utils/data/selection';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { disclosureStyles } from '../utils/style/transitions';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\nimport { Collapse, type CollapseProps } from './Collapse';\n\n/** Accordion 交给 AccordionItem 的状态 */\nexport interface AccordionState {\n /** 展开着的项 */\n readonly expanded: readonly string[];\n /** 标题的层级(h2–h6) */\n readonly headingLevel: 2 | 3 | 4 | 5 | 6;\n /** 整组不可用 */\n readonly disabled: boolean;\n /** 展开或收起一项(单开 / 多开的规则由组决定) */\n toggle(value: string): void;\n}\n\n/** Accordion 的上下文:自定义的项可以 inject 它接入组 */\nexport const AccordionContext = createContext<AccordionState>('Accordion');\n\n/** 两种方式共有的属性;未声明的属性落到外层 div 上 */\ninterface AccordionBaseProps extends PartProps<'div'> {\n /** 单开时允许把唯一展开的那项也收起,默认 true */\n collapsible?: boolean;\n /** 标题的层级,按所在页面的大纲选,默认 3 */\n headingLevel?: 2 | 3 | 4 | 5 | 6;\n /** 整组不可用 */\n disabled?: boolean;\n /** 字号档位;不写时继承 */\n size?: TextSize;\n /** AccordionItem */\n children?: VNodeChild;\n}\n\n/** 单开(selectionMode=\"single\",value 是展开项的值)或多开(value 是数组) */\nexport type AccordionProps = AccordionBaseProps & SelectionProps;\n\n/** Accordion 的样式:root、item、heading、trigger、chevron、chevronOpen、content */\nexport const accordionStyles = css.create({\n root: { display: 'flex', flexDirection: 'column' },\n item: {\n borderBottomWidth: '_xs',\n borderBottomStyle: 'solid',\n borderBottomColor: '_borderMuted',\n },\n heading: { margin: 0, fontSize: 'inherit', fontWeight: 'inherit' },\n // 去掉按钮默认外观、焦点环、波纹、颜色过渡由 ButtonBase 给出\n trigger: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '_md',\n width: '_full',\n minHeight: '_minTarget',\n paddingBlock: '_md',\n paddingInline: '_sm',\n borderRadius: '_sm',\n backgroundColor: { default: 'transparent', ':hover': '_fill' },\n color: '_text',\n fontWeight: '_semibold',\n textAlign: 'start',\n },\n triggerDisabled: { opacity: '_disabled' },\n chevron: { flexShrink: 0, color: '_textMuted' },\n chevronOpen: { rotate: '180deg' },\n content: { paddingInline: '_sm', paddingBlockEnd: '_md', color: '_text' },\n});\n\n/** 手风琴:一组可展开收起的项,单开或多开 */\nexport const Accordion = _component(\n ({\n selectionMode = 'single',\n _value: value = _bindable<string | string[] | null>(null),\n collapsible = true,\n headingLevel = 3,\n disabled = false,\n size,\n children,\n ...rest\n }: AccordionProps) => {\n let root = _state.raw<HTMLElement | null>(null);\n const expanded = _derived(selectedValues(value));\n\n AccordionContext.provide({\n get expanded() {\n return expanded;\n },\n get headingLevel() {\n return headingLevel;\n },\n get disabled() {\n return disabled;\n },\n toggle(item) {\n const next = toggleSelection(expanded, item, {\n mode: selectionMode,\n required: !collapsible,\n });\n if (next === expanded) return;\n value = selectionMode === 'multiple' ? [...next] : (next[0] ?? null);\n },\n });\n\n // ↑ / ↓ 在标题之间移动(循环),Home / End 到两端;只在焦点在标题按钮上时处理\n function onKeydown(event: KeyboardEvent) {\n const target = event.target as HTMLElement;\n if (!root || !target.matches('[data-accordion-trigger]')) return;\n const triggers = [\n ...root.querySelectorAll<HTMLButtonElement>('[data-accordion-trigger]:not(:disabled)'),\n ].filter((trigger) => trigger.closest('[data-accordion]') === root);\n const index = triggers.indexOf(target as HTMLButtonElement);\n const next = {\n ArrowDown: triggers[(index + 1) % triggers.length],\n ArrowUp: triggers[(index - 1 + triggers.length) % triggers.length],\n Home: triggers[0],\n End: triggers.at(-1),\n }[event.key];\n if (!next) return;\n event.preventDefault();\n next.focus();\n }\n\n return () => (\n <div\n {...mergeAttrs<'div'>({ sx: [accordionStyles.root, size && fontSizeStyles[size]] }, rest, {\n ref: _toRef(root),\n onKeydown,\n })}\n data-accordion=\"\"\n data-disabled={disabled || undefined}\n >\n {children}\n </div>\n );\n },\n);\n\n/** 未声明的属性落到每一项的外层 div 上 */\nexport interface AccordionItemProps extends PartProps<'div', 'title'> {\n /** 这一项的值 */\n value: string;\n /** 标题 */\n title: VNodeChild;\n /** 不可用:标题按钮 disabled,不能展开收起 */\n disabled?: boolean;\n /** 标题(h2–h6)的部件属性 */\n propsHeading?: PartProps<'h3'>;\n /** 标题按钮的部件属性 */\n propsTrigger?: Omit<Partial<ButtonBaseProps>, 'aria-expanded' | 'aria-controls'>;\n /** 展开箭头的部件属性 */\n propsChevron?: Partial<IconProps>;\n /** 内容区(Collapse,role=\"region\")的部件属性 */\n propsContent?: Partial<CollapseProps>;\n /** 内容 */\n children?: VNodeChild;\n}\n\n/** 手风琴里的一项:标题按钮 + 展开收起的内容 */\nexport const AccordionItem = _component(\n ({\n value,\n title,\n disabled = false,\n propsHeading,\n propsTrigger,\n propsChevron,\n propsContent,\n children,\n ...rest\n }: AccordionItemProps) => {\n const accordion = AccordionContext.inject();\n const id = useId();\n const triggerId = `${id}-trigger`;\n const contentId = `${id}-content`;\n // Collapse 在页内搜索命中(beforematch)时会写回 open:经这个对象交给组切换\n const model = {\n get open() {\n return accordion.expanded.includes(value);\n },\n set open(next: boolean) {\n if (next !== model.open) accordion.toggle(value);\n },\n };\n\n return () => {\n const open = model.open;\n const off = disabled || accordion.disabled;\n const state = open ? 'open' : 'closed';\n const trigger = (\n <ButtonBase\n {...mergePartProps<ButtonBaseProps>(\n { sx: [accordionStyles.trigger, off && accordionStyles.triggerDisabled] },\n propsTrigger,\n {\n id: triggerId,\n disabled: off,\n 'aria-expanded': open,\n 'aria-controls': contentId,\n onClick: () => accordion.toggle(value),\n },\n )}\n data-accordion-trigger=\"\"\n data-state={state}\n >\n <span>{title}</span>\n <Icon\n {...mergePartProps<IconProps>(\n {\n icon: ChevronDown,\n sx: [\n accordionStyles.chevron,\n disclosureStyles.icon,\n open && accordionStyles.chevronOpen,\n ],\n },\n propsChevron,\n )}\n />\n </ButtonBase>\n );\n return (\n <div\n {...mergeAttrs<'div'>({ sx: accordionStyles.item }, rest)}\n data-state={state}\n data-disabled={off || undefined}\n >\n {/* 标签名随 headingLevel,用 h() 渲染 */}\n {h(\n `h${accordion.headingLevel}`,\n mergeAttrs<'h3'>({ sx: accordionStyles.heading }, propsHeading),\n [trigger],\n )}\n <Collapse\n {...mergePartProps<CollapseProps>(\n { propsContent: { sx: accordionStyles.content } },\n propsContent,\n { id: contentId, role: 'region', 'aria-labelledby': triggerId },\n )}\n _open={model.open}\n >\n {children}\n </Collapse>\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -4,8 +4,8 @@ import { toneStyles } from "../utils/style/typography.js";
4
4
  import { VisuallyHidden } from "../base/VisuallyHidden.js";
5
5
  import { useFormat } from "../config/lang/format.js";
6
6
  import { useTween } from "../utils/motion/tween.js";
7
- import { createVNode, mergeProps, shallowRef } from "vue";
8
- import { _component, effect, readonlyProp, restProps, untrack } from "@zerodep-dev/vue-tsx-pro-tsx";
7
+ import { createVNode, shallowRef } from "vue";
8
+ import { _component, effect, mergeJsxProps, readonlyProp, restProps, untrack } from "@zerodep-dev/vue-tsx-pro-tsx";
9
9
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
10
10
  //#region src/display/AnimatedNumber.tsx
11
11
  /** 未声明的属性落到外层 span 上;原生的 prefix 属性(RDFa)让给前缀内容 */
@@ -61,13 +61,13 @@ var AnimatedNumber = /*#__PURE__*/ _component((_props, _ctx) => {
61
61
  down: "danger",
62
62
  flat: tone.value
63
63
  }[direction] : tone.value;
64
- return createVNode("span", mergeProps(mergeAttrs({ sx: [animatedNumberStyles.root, color && toneStyles[color]] }, rest, { ref: (element) => root = element }), { "data-trend": trend.value ? direction : void 0 }), [
64
+ return createVNode("span", mergeJsxProps(mergeAttrs({ sx: [animatedNumberStyles.root, color && toneStyles[color]] }, rest, { ref: (element) => root = element }), { "data-trend": trend.value ? direction : void 0 }), [
65
65
  hasContent(prefix.value) && createVNode("span", mergeAttrs({}, propsPrefix.value), [prefix.value]),
66
66
  createVNode("span", mergeAttrs({}, propsValue.value, {
67
67
  "aria-hidden": true,
68
68
  ref: valueElement
69
69
  }), [untrack(() => shownText())]),
70
- createVNode(VisuallyHidden, mergeProps(mergePartProps({}, propsLabel.value), { "key": "__site0" }), {
70
+ createVNode(VisuallyHidden, mergeJsxProps(mergePartProps({}, propsLabel.value), { "key": "__site0" }), {
71
71
  default: () => [text(value.value)],
72
72
  $stable: true
73
73
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"AnimatedNumber.js","names":["_vtp_readonlyProp","_vtp_restProps","_vtp_untrack","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../src/display/AnimatedNumber.tsx"],"sourcesContent":["/**\n * 会滚动的数字(span):值变化时从旧值过渡到新值(useTween),按当前语言格式化,等宽数字不抖动。\n * 统计卡片的数值、金额、百分比、计数器。\n *\n * <AnimatedNumber value={revenue} format={{ style: 'currency' }} />\n * <AnimatedNumber value={0.123} format={{ style: 'percent', maximumFractionDigits: 1 }} trend prefix=\"较上周 \" />\n *\n * 读屏只读终值:滚动中的数字对读屏隐藏,旁边有一份隐藏的终值文字。需要播报变化时在外层加 aria-live。\n * 值可以是 number、bigint 或 Decimal:过渡的中间帧按浮点数算,停下时与读屏的终值按原值格式化,不丢精度。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { VisuallyHidden, type VisuallyHiddenProps } from '../base/VisuallyHidden';\nimport { useFormat, type NumericFormat } from '../config/lang/format';\nimport { compareNumeric, numericText, toNumber, type NumericValue } from '../utils/data/numeric';\nimport { useTween, type TweenOptions } from '../utils/motion/tween';\nimport { hasContent, mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { toneStyles, type Tone } from '../utils/style/typography';\n\n/** 未声明的属性落到外层 span 上;原生的 prefix 属性(RDFa)让给前缀内容 */\nexport interface AnimatedNumberProps extends PartProps<'span', 'prefix'> {\n /** 数值:number、bigint 或 Decimal */\n value: NumericValue;\n /**\n * 格式:金额 `{ style: 'currency' }`(币种默认取语言包)、百分比 `{ style: 'percent' }`、\n * 以万为单位 `{ scale: 10_000, maximumFractionDigits: 2 }`\n */\n format?: NumericFormat;\n /** 过渡的时长档位,默认 lg */\n duration?: TweenOptions['duration'];\n /** 挂载时从这个值滚到 value;不给时直接显示 value */\n from?: NumericValue;\n /** 按正负着色:正数成功色、负数危险色(涨跌);data-trend 写 up / down / flat */\n trend?: boolean;\n /** 文字色调;给了 trend 时由正负决定 */\n tone?: Tone;\n /** 数字前的内容(如“¥”以外的说明文字、图标) */\n prefix?: VNodeChild;\n /** 数字后的内容(如单位“人”) */\n suffix?: VNodeChild;\n /** 前缀的部件属性 */\n propsPrefix?: PartProps<'span'>;\n /** 后缀的部件属性 */\n propsSuffix?: PartProps<'span'>;\n /** 滚动中的数字(对读屏隐藏)的部件属性 */\n propsValue?: PartProps<'span', 'aria-hidden'>;\n /** 给读屏的终值文字的部件属性 */\n propsLabel?: Partial<VisuallyHiddenProps>;\n}\n\n/** AnimatedNumber 的样式:root */\nexport const animatedNumberStyles = css.create({\n // 等宽数字:滚动时宽度不跳\n root: { fontVariantNumeric: 'tabular-nums', whiteSpace: 'nowrap' },\n});\n\n/** 终值的小数位数:滚动中的值按它取整,整数不会滚出一串小数 */\nfunction decimals(value: NumericValue) {\n return Math.min(20, numericText(value).split('.')[1]?.length ?? 0);\n}\n\n/** 会滚动的数字:值变化时过渡,读屏只读终值 */\nexport const AnimatedNumber = _component(\n ({\n value,\n format,\n duration = 'lg',\n from,\n trend = false,\n tone,\n prefix,\n suffix,\n propsPrefix,\n propsSuffix,\n propsValue,\n propsLabel,\n ...rest\n }: AnimatedNumberProps) => {\n const formatter = useFormat();\n let root: HTMLElement | null = null;\n // 时长按自己所在的主题范围读(子树里可能覆盖了主题)\n const start = _untrack(from);\n const tween = useTween(() => toNumber(value), {\n duration: _untrack(duration),\n from: start == null ? undefined : toNumber(start),\n scope: () => root,\n });\n\n const text = (number: NumericValue) => formatter.number(number, format);\n\n /** 过渡中当前显示的文字 */\n const shownText = () => {\n // 停在终值时按原值格式化:bigint、Decimal 不经过浮点数\n if (tween.current === toNumber(value)) return text(value);\n const places = 10 ** decimals(value);\n return text(Math.round(tween.current * places) / places);\n };\n // 过渡中每帧直接改文字,不为一个数字重新渲染整个组件;渲染里只取当前值、不追踪\n let valueElement = _state.raw<HTMLElement | null>(null);\n _effect(() => {\n const shown = shownText();\n if (valueElement) valueElement.textContent = shown;\n });\n\n return () => {\n const sign = compareNumeric(value, 0);\n const direction = sign > 0 ? 'up' : sign < 0 ? 'down' : 'flat';\n const color = trend\n ? ({ up: 'success', down: 'danger', flat: tone } as const)[direction]\n : tone;\n return (\n <span\n {...mergeAttrs<'span'>(\n { sx: [animatedNumberStyles.root, color && toneStyles[color]] },\n rest,\n { ref: (element: unknown) => (root = element as HTMLElement | null) },\n )}\n data-trend={trend ? direction : undefined}\n >\n {hasContent(prefix) && <span {...mergeAttrs<'span'>({}, propsPrefix)}>{prefix}</span>}\n <span\n {...mergeAttrs<'span'>({}, propsValue, {\n 'aria-hidden': true,\n ref: _toRef(valueElement),\n })}\n >\n {_untrack(shownText())}\n </span>\n <VisuallyHidden {...mergePartProps<VisuallyHiddenProps>({}, propsLabel)}>\n {text(value)}\n </VisuallyHidden>\n {hasContent(suffix) && <span {...mergeAttrs<'span'>({}, propsSuffix)}>{suffix}</span>}\n </span>\n );\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"AnimatedNumber.js","names":["_vtp_readonlyProp","_vtp_restProps","_vtp_untrack","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../src/display/AnimatedNumber.tsx"],"sourcesContent":["/**\n * 会滚动的数字(span):值变化时从旧值过渡到新值(useTween),按当前语言格式化,等宽数字不抖动。\n * 统计卡片的数值、金额、百分比、计数器。\n *\n * <AnimatedNumber value={revenue} format={{ style: 'currency' }} />\n * <AnimatedNumber value={0.123} format={{ style: 'percent', maximumFractionDigits: 1 }} trend prefix=\"较上周 \" />\n *\n * 读屏只读终值:滚动中的数字对读屏隐藏,旁边有一份隐藏的终值文字。需要播报变化时在外层加 aria-live。\n * 值可以是 number、bigint 或 Decimal:过渡的中间帧按浮点数算,停下时与读屏的终值按原值格式化,不丢精度。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { VisuallyHidden, type VisuallyHiddenProps } from '../base/VisuallyHidden';\nimport { useFormat, type NumericFormat } from '../config/lang/format';\nimport { compareNumeric, numericText, toNumber, type NumericValue } from '../utils/data/numeric';\nimport { useTween, type TweenOptions } from '../utils/motion/tween';\nimport { hasContent, mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { toneStyles, type Tone } from '../utils/style/typography';\n\n/** 未声明的属性落到外层 span 上;原生的 prefix 属性(RDFa)让给前缀内容 */\nexport interface AnimatedNumberProps extends PartProps<'span', 'prefix'> {\n /** 数值:number、bigint 或 Decimal */\n value: NumericValue;\n /**\n * 格式:金额 `{ style: 'currency' }`(币种默认取语言包)、百分比 `{ style: 'percent' }`、\n * 以万为单位 `{ scale: 10_000, maximumFractionDigits: 2 }`\n */\n format?: NumericFormat;\n /** 过渡的时长档位,默认 lg */\n duration?: TweenOptions['duration'];\n /** 挂载时从这个值滚到 value;不给时直接显示 value */\n from?: NumericValue;\n /** 按正负着色:正数成功色、负数危险色(涨跌);data-trend 写 up / down / flat */\n trend?: boolean;\n /** 文字色调;给了 trend 时由正负决定 */\n tone?: Tone;\n /** 数字前的内容(如“¥”以外的说明文字、图标) */\n prefix?: VNodeChild;\n /** 数字后的内容(如单位“人”) */\n suffix?: VNodeChild;\n /** 前缀的部件属性 */\n propsPrefix?: PartProps<'span'>;\n /** 后缀的部件属性 */\n propsSuffix?: PartProps<'span'>;\n /** 滚动中的数字(对读屏隐藏)的部件属性 */\n propsValue?: PartProps<'span', 'aria-hidden'>;\n /** 给读屏的终值文字的部件属性 */\n propsLabel?: Partial<VisuallyHiddenProps>;\n}\n\n/** AnimatedNumber 的样式:root */\nexport const animatedNumberStyles = css.create({\n // 等宽数字:滚动时宽度不跳\n root: { fontVariantNumeric: 'tabular-nums', whiteSpace: 'nowrap' },\n});\n\n/** 终值的小数位数:滚动中的值按它取整,整数不会滚出一串小数 */\nfunction decimals(value: NumericValue) {\n return Math.min(20, numericText(value).split('.')[1]?.length ?? 0);\n}\n\n/** 会滚动的数字:值变化时过渡,读屏只读终值 */\nexport const AnimatedNumber = _component(\n ({\n value,\n format,\n duration = 'lg',\n from,\n trend = false,\n tone,\n prefix,\n suffix,\n propsPrefix,\n propsSuffix,\n propsValue,\n propsLabel,\n ...rest\n }: AnimatedNumberProps) => {\n const formatter = useFormat();\n let root: HTMLElement | null = null;\n // 时长按自己所在的主题范围读(子树里可能覆盖了主题)\n const start = _untrack(from);\n const tween = useTween(() => toNumber(value), {\n duration: _untrack(duration),\n from: start == null ? undefined : toNumber(start),\n scope: () => root,\n });\n\n const text = (number: NumericValue) => formatter.number(number, format);\n\n /** 过渡中当前显示的文字 */\n const shownText = () => {\n // 停在终值时按原值格式化:bigint、Decimal 不经过浮点数\n if (tween.current === toNumber(value)) return text(value);\n const places = 10 ** decimals(value);\n return text(Math.round(tween.current * places) / places);\n };\n // 过渡中每帧直接改文字,不为一个数字重新渲染整个组件;渲染里只取当前值、不追踪\n let valueElement = _state.raw<HTMLElement | null>(null);\n _effect(() => {\n const shown = shownText();\n if (valueElement) valueElement.textContent = shown;\n });\n\n return () => {\n const sign = compareNumeric(value, 0);\n const direction = sign > 0 ? 'up' : sign < 0 ? 'down' : 'flat';\n const color = trend\n ? ({ up: 'success', down: 'danger', flat: tone } as const)[direction]\n : tone;\n return (\n <span\n {...mergeAttrs<'span'>(\n { sx: [animatedNumberStyles.root, color && toneStyles[color]] },\n rest,\n { ref: (element: unknown) => (root = element as HTMLElement | null) },\n )}\n data-trend={trend ? direction : undefined}\n >\n {hasContent(prefix) && <span {...mergeAttrs<'span'>({}, propsPrefix)}>{prefix}</span>}\n <span\n {...mergeAttrs<'span'>({}, propsValue, {\n 'aria-hidden': true,\n ref: _toRef(valueElement),\n })}\n >\n {_untrack(shownText())}\n </span>\n <VisuallyHidden {...mergePartProps<VisuallyHiddenProps>({}, propsLabel)}>\n {text(value)}\n </VisuallyHidden>\n {hasContent(suffix) && <span {...mergeAttrs<'span'>({}, propsSuffix)}>{suffix}</span>}\n </span>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -6,8 +6,8 @@ import { radiusStyles } from "../utils/style/styles.js";
6
6
  import { useRecipe } from "../config/styles.js";
7
7
  import { Icon } from "../base/Icon.js";
8
8
  import { statusToneStyles } from "../utils/style/tone-styles.js";
9
- import { createVNode, mergeProps, ref, watch } from "vue";
10
- import { _component, createContext, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
9
+ import { createVNode, ref, watch } from "vue";
10
+ import { _component, createContext, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
11
11
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
12
12
  import { User } from "@lucide/icons";
13
13
  //#region src/display/Avatar.tsx
@@ -118,7 +118,7 @@ var Avatar = /*#__PURE__*/ _component((_props, _ctx) => {
118
118
  grouped: !!group,
119
119
  loading: status.value === "loading"
120
120
  });
121
- return createVNode("span", mergeProps(mergeAttrs({
121
+ return createVNode("span", mergeJsxProps(mergeAttrs({
122
122
  ...s.root,
123
123
  sx: [
124
124
  statusToneStyles[fill][color],
@@ -129,7 +129,7 @@ var Avatar = /*#__PURE__*/ _component((_props, _ctx) => {
129
129
  }, rest, name.value ? {
130
130
  role: "img",
131
131
  "aria-label": name.value
132
- } : { "aria-hidden": true }), { "data-state": src.value ? status.value : "fallback" }), [src.value && status.value !== "error" && createVNode("img", mergeProps({
132
+ } : { "aria-hidden": true }), { "data-state": src.value ? status.value : "fallback" }), [src.value && status.value !== "error" && createVNode("img", mergeJsxProps({
133
133
  "key": src.value,
134
134
  "alt": ""
135
135
  }, mergeAttrs(s.image, propsImage.value, {
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.js","names":["_vtp_readonlyProp","_vtp_restProps","_vue_ref","_createVNode","_mergeProps"],"sources":["../../src/display/Avatar.tsx"],"sourcesContent":["/**\n * 头像(span,role=\"img\"):显示图片,图片还没加载好或加载失败时显示后备内容(默认是名字的首字母)。\n * 名称写在外层(aria-label),图片本身是装饰(alt=\"\"),读屏不会念两遍;没有 name 时整个头像是装饰性的(对读屏隐藏)。\n *\n * <Avatar src={user.avatar} name={user.name} />\n * <Avatar name=\"张三\" size=\"lg\" radius=\"md\" />\n * <Avatar name=\"李四\" variant=\"solid\" tone=\"success\" />\n */\nimport { User } from '@lucide/icons';\nimport { createContext, _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 { Icon } from '../base/Icon';\nimport { useDefaults } from '../config/defaults';\nimport { useRecipe } from '../config/styles';\nimport { mergeAttrs, type PartProps } from '../utils/props';\nimport { statusToneStyles, type StatusTone } from '../utils/style/tone-styles';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\nimport { radiusStyles, type Radius } from '../utils/style/styles';\nimport { t } from '../config/theme/tokens';\n\n/** 后备内容(首字母、图标)的底色样式 */\nexport interface AvatarVariants {\n /** 浅色底(默认) */\n soft: unknown;\n /** 实底 */\n solid: unknown;\n}\n\n/** 头像的外观选项;可以用 createUi / Provider 的 defaults.Avatar 统一改默认值 */\nexport interface AvatarOptions {\n /** 字号档位,头像边长是它的 2.5 倍;不写时继承 */\n size?: TextSize;\n /** 圆角,默认 full(圆形);团队、组织、应用的图标常用 md(圆角方形) */\n radius?: Radius;\n /** 后备内容的底色样式,默认 soft */\n variant?: keyof AvatarVariants;\n /** 后备内容的色调(与 Button、Badge 等同一套),默认 accent */\n tone?: StatusTone;\n}\n\n/** 角色与读屏可见性由组件按 name 决定 */\nexport type AvatarManaged = 'role' | 'aria-hidden';\n\n/** 未声明的属性落到外层 span 上 */\nexport interface AvatarProps extends PartProps<'span', AvatarManaged>, AvatarOptions {\n /** 图片地址;不写或加载失败时显示后备内容 */\n src?: string;\n /** 名字:无障碍名称,也用来生成首字母;不写时头像是装饰性的 */\n name?: string;\n /** 后备内容,默认是名字的首字母,没有名字时是人像图标 */\n fallback?: VNodeChild;\n /** 图片的部件属性 */\n propsImage?: PartProps<'img', 'src' | 'alt'>;\n /** 后备内容的部件属性 */\n propsFallback?: PartProps<'span'>;\n}\n\n/** 在 AvatarGroup 里:Avatar 据此叠放(AvatarGroup 提供) */\nexport const AvatarGroupContext = createContext<{ readonly grouped: true }>('AvatarGroup');\n\n/**\n * 头像的配方:部件 root(外层)、image(图片)、fallback(后备内容);在头像组里、图片加载中是档位。\n * 后备内容的底色来自共用的 statusToneStyles,排在配方之前,createUi / Provider 的 styles.Avatar 能盖过它\n */\nexport const avatarRecipe = css.recipe({\n name: 'Avatar',\n parts: ['root', 'image', 'fallback'],\n base: {\n root: {\n position: 'relative',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n width: '2.5em',\n height: '2.5em',\n overflow: 'hidden',\n verticalAlign: 'middle',\n userSelect: 'none',\n },\n image: { width: '_full', height: '_full', objectFit: 'cover' },\n fallback: { fontWeight: '_medium', lineHeight: 1, textTransform: 'uppercase' },\n },\n variants: {\n // 头像组里:往前叠 0.5em,一圈页面底色的描边把相邻的分开(AvatarGroup 的“+N”也用它)\n grouped: {\n true: {\n root: {\n boxShadow: `0 0 0 ${t.borderWidths.sm} ${t.colors.background}`,\n marginInlineStart: { default: '-0.5em', ':first-child': 0 },\n },\n },\n },\n // 图片加载完之前先藏起来(仍在 DOM 里加载),后备内容垫在下面\n loading: { true: { image: { position: 'absolute', opacity: 0 } } },\n },\n});\n\n/** 头像的部件(createUi / Provider 的 styles.Avatar 按它定制) */\nexport type AvatarPart = (typeof avatarRecipe.parts)[number];\n\n/** 名字的首字母:中文取最后一个字(通常是名),其他语言取前两个词的首字母 */\nexport function initials(name: string): string {\n const trimmed = name.trim();\n if (!trimmed) return '';\n if (/[㐀-鿿]/.test(trimmed)) return trimmed.at(-1)!;\n const words = trimmed.split(/\\s+/);\n return (words[0]![0]! + (words.length > 1 ? words.at(-1)![0]! : '')).toUpperCase();\n}\n\n/** 头像:图片 + 后备内容(首字母或图标) */\nexport const Avatar = _component(\n ({\n src,\n name,\n fallback,\n size,\n radius,\n variant,\n tone,\n propsImage,\n propsFallback,\n ...rest\n }: AvatarProps) => {\n const appearance = useDefaults('Avatar', () => ({ size, radius, variant, tone }), {\n radius: 'full',\n variant: 'soft',\n tone: 'accent',\n });\n const recipe = useRecipe(avatarRecipe);\n const group = AvatarGroupContext.inject(null);\n // 图片状态:loading 加载中、loaded 已显示、error 失败(显示后备内容)\n let status = _state<'loading' | 'loaded' | 'error'>('loading');\n watch(\n () => src,\n () => (status = 'loading'),\n );\n\n return () => {\n const showFallback = !src || status !== 'loaded';\n const { size: fontSize, radius: corner, variant: fill, tone: color } = appearance();\n const s = recipe({\n variant: fill,\n tone: color,\n grouped: !!group,\n loading: status === 'loading',\n });\n return (\n <span\n {...mergeAttrs<'span'>(\n {\n ...s.root,\n sx: [\n statusToneStyles[fill][color],\n s.root.sx,\n radiusStyles[corner],\n fontSize && fontSizeStyles[fontSize],\n ],\n },\n rest,\n name ? { role: 'img', 'aria-label': name } : { 'aria-hidden': true },\n )}\n data-state={src ? status : 'fallback'}\n >\n {src && status !== 'error' && (\n <img\n key={src}\n alt=\"\"\n {...mergeAttrs<'img'>(s.image, propsImage, {\n src,\n onLoad: () => (status = 'loaded'),\n onError: () => (status = 'error'),\n })}\n />\n )}\n {showFallback && (\n <span {...mergeAttrs<'span'>(s.fallback, propsFallback, { 'aria-hidden': true })}>\n {fallback ?? (name ? initials(name) : <Icon icon={User} />)}\n </span>\n )}\n </span>\n );\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"Avatar.js","names":["_vtp_readonlyProp","_vtp_restProps","_vue_ref","_createVNode","_mergeProps"],"sources":["../../src/display/Avatar.tsx"],"sourcesContent":["/**\n * 头像(span,role=\"img\"):显示图片,图片还没加载好或加载失败时显示后备内容(默认是名字的首字母)。\n * 名称写在外层(aria-label),图片本身是装饰(alt=\"\"),读屏不会念两遍;没有 name 时整个头像是装饰性的(对读屏隐藏)。\n *\n * <Avatar src={user.avatar} name={user.name} />\n * <Avatar name=\"张三\" size=\"lg\" radius=\"md\" />\n * <Avatar name=\"李四\" variant=\"solid\" tone=\"success\" />\n */\nimport { User } from '@lucide/icons';\nimport { createContext, _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 { Icon } from '../base/Icon';\nimport { useDefaults } from '../config/defaults';\nimport { useRecipe } from '../config/styles';\nimport { mergeAttrs, type PartProps } from '../utils/props';\nimport { statusToneStyles, type StatusTone } from '../utils/style/tone-styles';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\nimport { radiusStyles, type Radius } from '../utils/style/styles';\nimport { t } from '../config/theme/tokens';\n\n/** 后备内容(首字母、图标)的底色样式 */\nexport interface AvatarVariants {\n /** 浅色底(默认) */\n soft: unknown;\n /** 实底 */\n solid: unknown;\n}\n\n/** 头像的外观选项;可以用 createUi / Provider 的 defaults.Avatar 统一改默认值 */\nexport interface AvatarOptions {\n /** 字号档位,头像边长是它的 2.5 倍;不写时继承 */\n size?: TextSize;\n /** 圆角,默认 full(圆形);团队、组织、应用的图标常用 md(圆角方形) */\n radius?: Radius;\n /** 后备内容的底色样式,默认 soft */\n variant?: keyof AvatarVariants;\n /** 后备内容的色调(与 Button、Badge 等同一套),默认 accent */\n tone?: StatusTone;\n}\n\n/** 角色与读屏可见性由组件按 name 决定 */\nexport type AvatarManaged = 'role' | 'aria-hidden';\n\n/** 未声明的属性落到外层 span 上 */\nexport interface AvatarProps extends PartProps<'span', AvatarManaged>, AvatarOptions {\n /** 图片地址;不写或加载失败时显示后备内容 */\n src?: string;\n /** 名字:无障碍名称,也用来生成首字母;不写时头像是装饰性的 */\n name?: string;\n /** 后备内容,默认是名字的首字母,没有名字时是人像图标 */\n fallback?: VNodeChild;\n /** 图片的部件属性 */\n propsImage?: PartProps<'img', 'src' | 'alt'>;\n /** 后备内容的部件属性 */\n propsFallback?: PartProps<'span'>;\n}\n\n/** 在 AvatarGroup 里:Avatar 据此叠放(AvatarGroup 提供) */\nexport const AvatarGroupContext = createContext<{ readonly grouped: true }>('AvatarGroup');\n\n/**\n * 头像的配方:部件 root(外层)、image(图片)、fallback(后备内容);在头像组里、图片加载中是档位。\n * 后备内容的底色来自共用的 statusToneStyles,排在配方之前,createUi / Provider 的 styles.Avatar 能盖过它\n */\nexport const avatarRecipe = css.recipe({\n name: 'Avatar',\n parts: ['root', 'image', 'fallback'],\n base: {\n root: {\n position: 'relative',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n width: '2.5em',\n height: '2.5em',\n overflow: 'hidden',\n verticalAlign: 'middle',\n userSelect: 'none',\n },\n image: { width: '_full', height: '_full', objectFit: 'cover' },\n fallback: { fontWeight: '_medium', lineHeight: 1, textTransform: 'uppercase' },\n },\n variants: {\n // 头像组里:往前叠 0.5em,一圈页面底色的描边把相邻的分开(AvatarGroup 的“+N”也用它)\n grouped: {\n true: {\n root: {\n boxShadow: `0 0 0 ${t.borderWidths.sm} ${t.colors.background}`,\n marginInlineStart: { default: '-0.5em', ':first-child': 0 },\n },\n },\n },\n // 图片加载完之前先藏起来(仍在 DOM 里加载),后备内容垫在下面\n loading: { true: { image: { position: 'absolute', opacity: 0 } } },\n },\n});\n\n/** 头像的部件(createUi / Provider 的 styles.Avatar 按它定制) */\nexport type AvatarPart = (typeof avatarRecipe.parts)[number];\n\n/** 名字的首字母:中文取最后一个字(通常是名),其他语言取前两个词的首字母 */\nexport function initials(name: string): string {\n const trimmed = name.trim();\n if (!trimmed) return '';\n if (/[㐀-鿿]/.test(trimmed)) return trimmed.at(-1)!;\n const words = trimmed.split(/\\s+/);\n return (words[0]![0]! + (words.length > 1 ? words.at(-1)![0]! : '')).toUpperCase();\n}\n\n/** 头像:图片 + 后备内容(首字母或图标) */\nexport const Avatar = _component(\n ({\n src,\n name,\n fallback,\n size,\n radius,\n variant,\n tone,\n propsImage,\n propsFallback,\n ...rest\n }: AvatarProps) => {\n const appearance = useDefaults('Avatar', () => ({ size, radius, variant, tone }), {\n radius: 'full',\n variant: 'soft',\n tone: 'accent',\n });\n const recipe = useRecipe(avatarRecipe);\n const group = AvatarGroupContext.inject(null);\n // 图片状态:loading 加载中、loaded 已显示、error 失败(显示后备内容)\n let status = _state<'loading' | 'loaded' | 'error'>('loading');\n watch(\n () => src,\n () => (status = 'loading'),\n );\n\n return () => {\n const showFallback = !src || status !== 'loaded';\n const { size: fontSize, radius: corner, variant: fill, tone: color } = appearance();\n const s = recipe({\n variant: fill,\n tone: color,\n grouped: !!group,\n loading: status === 'loading',\n });\n return (\n <span\n {...mergeAttrs<'span'>(\n {\n ...s.root,\n sx: [\n statusToneStyles[fill][color],\n s.root.sx,\n radiusStyles[corner],\n fontSize && fontSizeStyles[fontSize],\n ],\n },\n rest,\n name ? { role: 'img', 'aria-label': name } : { 'aria-hidden': true },\n )}\n data-state={src ? status : 'fallback'}\n >\n {src && status !== 'error' && (\n <img\n key={src}\n alt=\"\"\n {...mergeAttrs<'img'>(s.image, propsImage, {\n src,\n onLoad: () => (status = 'loaded'),\n onError: () => (status = 'error'),\n })}\n />\n )}\n {showFallback && (\n <span {...mergeAttrs<'span'>(s.fallback, propsFallback, { 'aria-hidden': true })}>\n {fallback ?? (name ? initials(name) : <Icon icon={User} />)}\n </span>\n )}\n </span>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -5,8 +5,8 @@ import { focusRingStyles } from "../utils/style/styles.js";
5
5
  import { Icon } from "../base/Icon.js";
6
6
  import { VisuallyHidden } from "../base/VisuallyHidden.js";
7
7
  import { Progress } from "../feedback/Progress.js";
8
- import { createVNode, mergeProps, useId } from "vue";
9
- import { _component, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
8
+ import { createVNode, useId } from "vue";
9
+ import { _component, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
10
10
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
11
11
  import { Ban, CircleAlert, CircleCheck, CircleDashed, CircleMinus } from "@lucide/icons";
12
12
  //#region src/display/Checklist.tsx
@@ -177,7 +177,7 @@ var Checklist = /*#__PURE__*/ _component((_props, _ctx) => {
177
177
  const state = statusOf(item);
178
178
  if (!onCheckedChange.value) return createVNode("span", css.attrs(checklistStyles.status), [statusIcon(item), createVNode(VisuallyHidden, null, { default: () => [lang.checklistStatus[state]] })]);
179
179
  const done = state === "done";
180
- return createVNode("span", css.attrs(checklistStyles.status), [createVNode("button", mergeProps({
180
+ return createVNode("span", css.attrs(checklistStyles.status), [createVNode("button", mergeJsxProps({
181
181
  "type": "button",
182
182
  "role": "checkbox",
183
183
  "aria-checked": done,
@@ -206,9 +206,9 @@ var Checklist = /*#__PURE__*/ _component((_props, _ctx) => {
206
206
  }
207
207
  if (layout.value === "inline") return createVNode("ul", mergeAttrs({ sx: [checklistStyles.inline, size.value && fontSizeStyles[size.value]] }, rest), [items.value.map((item, index) => {
208
208
  const labelId = `${id}-${index}`;
209
- return createVNode("li", mergeProps({ "key": keyOf(item, index) }, css.attrs(checklistStyles.inlineItem)), [
209
+ return createVNode("li", mergeJsxProps({ "key": keyOf(item, index) }, css.attrs(checklistStyles.inlineItem)), [
210
210
  status(item, labelId),
211
- createVNode("span", mergeProps({ "id": labelId }, css.attrs(labelSx(item))), [item.label]),
211
+ createVNode("span", mergeJsxProps({ "id": labelId }, css.attrs(labelSx(item))), [item.label]),
212
212
  hasContent(item.date) && createVNode("span", css.attrs(checklistStyles.meta, statusOf(item) === "overdue" && checklistStyles.late), [item.date]),
213
213
  item.evidence
214
214
  ]);
@@ -228,10 +228,10 @@ var Checklist = /*#__PURE__*/ _component((_props, _ctx) => {
228
228
  item.date,
229
229
  item.evidence
230
230
  ].some(hasContent);
231
- return createVNode("li", mergeProps({ "key": keyOf(item, index) }, mergeAttrs({ sx: checklistStyles.item }, own), { "data-status": statusOf(item) }), [
231
+ return createVNode("li", mergeJsxProps({ "key": keyOf(item, index) }, mergeAttrs({ sx: checklistStyles.item }, own), { "data-status": statusOf(item) }), [
232
232
  status(item, labelId),
233
233
  createVNode("div", css.attrs(checklistStyles.body), [
234
- createVNode("span", mergeProps({ "id": labelId }, css.attrs(labelSx(item))), [item.label]),
234
+ createVNode("span", mergeJsxProps({ "id": labelId }, css.attrs(labelSx(item))), [item.label]),
235
235
  hasContent(item.description) && createVNode("span", css.attrs(checklistStyles.description), [item.description]),
236
236
  meta && createVNode("span", css.attrs(checklistStyles.meta), [
237
237
  hasContent(item.owner) && createVNode("span", null, [item.owner]),
@@ -1 +1 @@
1
- {"version":3,"file":"Checklist.js","names":["_vtp_readonlyProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../src/display/Checklist.tsx"],"sourcesContent":["/**\n * 完成清单:一组要做完的事,每项的状态(完成、待办、超时、不适用、受阻)与它的上下文——怎么做、谁负责、哪天、证据、去处理。\n * 里程碑与交付证据、结项材料、上线检查、新用户的引导任务。参考 Shopify Polaris 的 Setup guide、GitHub 的任务列表。\n *\n * <Checklist\n * title=\"结项材料\"\n * summary\n * items={[\n * { label: '验收报告', status: 'done', date: '10-12', evidence: <Link href={url}>验证报告.pdf</Link> },\n * { label: '财务复核意见', status: 'overdue', owner: '财务部', date: '计划 10-20', action: <Button>催办</Button> },\n * { label: '合同签订记录', description: '谈定价格与生效日期,采购经理签字', owner: '采购部' },\n * ]}\n * />\n * <Checklist layout=\"inline\" items={…} /> 一行排开、放不下换行(详情行、卡片的一角)\n * <Checklist layout=\"icons\" aria-label=\"里程碑\" items={…} /> 只有一排状态图标(表格的格子里),读屏念每一项\n * <Checklist items={tasks} onCheckedChange={(item, done) => save(item.key, done)} /> 可以勾选(上线检查、引导任务)\n *\n * summary 在上面显示“已完成 2 / 3”与进度条(不适用的不算)。没完成的名称是次要色,不适用的划掉;\n * 超时的日期用危险色。每项的状态写在给读屏的文字里。\n *\n * 部件:Root(div)、Summary(汇总行)、List(ul)、Item(li,可以按项计算)、Status(状态图标,可勾选时是按钮)、Label、Meta。\n */\nimport { Ban, CircleAlert, CircleCheck, CircleDashed, CircleMinus } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { useId, type VNodeChild } from 'vue';\nimport { Icon, type IconData } from '../base/Icon';\nimport { VisuallyHidden } from '../base/VisuallyHidden';\nimport { useLang } from '../config/context';\nimport { Progress } from '../feedback/Progress';\nimport { hasContent, mergeAttrs, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\n\n/** 一项的状态 */\nexport interface ChecklistStatuses {\n /** 完成 */\n done: unknown;\n /** 待办(默认) */\n todo: unknown;\n /** 超时:过了计划日期还没完成 */\n overdue: unknown;\n /** 受阻:等别人、缺前提 */\n blocked: unknown;\n /** 不适用:这一次不用做,不算进进度 */\n skipped: unknown;\n}\n\n/** 清单的一项 */\nexport interface ChecklistItem {\n /** 唯一的 key;不写时用 label(label 是文字时)或位置 */\n key?: string;\n /** 名称 */\n label: VNodeChild;\n /** 状态,默认 todo */\n status?: keyof ChecklistStatuses;\n /** 说明:怎么做、要什么材料、缺的由谁出具 */\n description?: VNodeChild;\n /** 负责人(谁处理、谁出具) */\n owner?: VNodeChild;\n /** 日期:完成的日期,或计划日期(超时时用危险色) */\n date?: VNodeChild;\n /** 证据:附件、报告的链接 */\n evidence?: VNodeChild;\n /** 操作:上传证据、去处理、催办(结束边) */\n action?: VNodeChild;\n}\n\n/** 清单的排法 */\nexport interface ChecklistLayouts {\n /** 一项一行(默认):状态、名称与说明、负责人 · 日期 · 证据,操作在结束边 */\n list: unknown;\n /** 一行排开、放不下换行:状态、名称、日期、证据 */\n inline: unknown;\n /** 只有一排状态图标:表格的格子里;悬停与读屏有每一项的说明 */\n icons: unknown;\n}\n\n/** 未声明的属性落到外层元素上(list 是 div,inline 是 ul,icons 是 span) */\nexport interface ChecklistProps extends PartProps<'div'> {\n /** 各项 */\n items: readonly ChecklistItem[];\n /**\n * 排法\n * @default 'list'\n */\n layout?: keyof ChecklistLayouts;\n /** 上面显示“已完成 2 / 3”与进度条(list 排法) */\n summary?: boolean;\n /** 字号档位;不写时继承 */\n size?: TextSize;\n /** 可以勾选:状态图标变成复选按钮,点了报告新的完成状态(不适用、受阻的不能勾) */\n onCheckedChange?: (item: ChecklistItem, done: boolean) => void;\n /** 每一项(li)的部件属性,可以按项计算 */\n propsItem?: PartProps<'li'> | ((item: ChecklistItem) => PartProps<'li'>);\n}\n\n/** Checklist 的样式 */\nexport const checklistStyles = css.create({\n root: { display: 'grid', gap: '_sm' },\n summary: {\n display: 'grid',\n gridTemplateColumns: 'auto 1fr',\n alignItems: 'center',\n gap: '_md',\n fontSize: '_sm',\n color: '_textMuted',\n },\n list: { display: 'grid', margin: 0, padding: 0, listStyle: 'none' },\n // 状态一列、内容一列、操作一列;状态贴着名称那一行\n item: {\n display: 'grid',\n gridTemplateColumns: 'auto minmax(0, 1fr) auto',\n columnGap: '_sm',\n alignItems: 'start',\n paddingBlock: '_xs',\n },\n status: {\n display: 'flex',\n alignItems: 'center',\n minHeight: '1lh',\n fontSize: '1.125em',\n },\n // 可以勾选时的按钮:只有图标,去掉按钮的外观\n toggle: {\n display: 'inline-flex',\n padding: 0,\n margin: 0,\n borderWidth: 0,\n backgroundColor: 'transparent',\n color: 'inherit',\n font: 'inherit',\n borderRadius: '_full',\n cursor: { default: 'pointer', ':disabled': 'default' },\n },\n body: { display: 'grid', gap: '2px', minWidth: 0 },\n label: { color: '_text', overflowWrap: 'anywhere' },\n labelPending: { color: '_textMuted' },\n labelSkipped: { color: '_textMuted', textDecorationLine: 'line-through' },\n description: { fontSize: '_sm', color: '_textMuted' },\n meta: {\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n columnGap: '_sm',\n rowGap: '2px',\n fontSize: '_sm',\n color: '_textMuted',\n },\n late: { color: '_dangerText' },\n action: { display: 'flex', alignItems: 'center', gap: '_xs' },\n inline: {\n display: 'flex',\n flexWrap: 'wrap',\n columnGap: '_lg',\n rowGap: '_xs',\n margin: 0,\n padding: 0,\n listStyle: 'none',\n },\n inlineItem: { display: 'inline-flex', alignItems: 'center', gap: '_xs', whiteSpace: 'nowrap' },\n icons: { display: 'inline-flex', alignItems: 'center', gap: '2px' },\n});\n\n/** 各状态的图标与颜色 */\nexport const checklistStatusStyles = css.create({\n done: { color: '_successText' },\n todo: { color: '_textMuted' },\n overdue: { color: '_dangerText' },\n blocked: { color: '_warningText' },\n skipped: { color: '_textMuted' },\n});\n\nconst statusIcons: Record<keyof ChecklistStatuses, IconData> = {\n done: CircleCheck,\n todo: CircleDashed,\n overdue: CircleAlert,\n blocked: Ban,\n skipped: CircleMinus,\n};\n\nconst keyOf = (item: ChecklistItem, index: number) =>\n item.key ?? (typeof item.label === 'string' ? item.label : String(index));\n\nconst statusOf = (item: ChecklistItem): keyof ChecklistStatuses => item.status ?? 'todo';\n\n/** 完成清单 */\nexport const Checklist = _component(\n ({\n items,\n layout = 'list',\n summary = false,\n size,\n onCheckedChange,\n propsItem,\n ...rest\n }: ChecklistProps) => {\n const lang = useLang();\n const id = useId();\n\n const statusIcon = (item: ChecklistItem) => {\n const status = statusOf(item);\n return <Icon icon={statusIcons[status]} sx={checklistStatusStyles[status]} />;\n };\n\n /** 状态:可以勾选时是复选按钮(名称是这一项的名称),否则是图标加给读屏的状态文字 */\n const status = (item: ChecklistItem, labelId: string) => {\n const state = statusOf(item);\n if (!onCheckedChange)\n return (\n <span {...css.attrs(checklistStyles.status)}>\n {statusIcon(item)}\n <VisuallyHidden>{lang.checklistStatus[state]}</VisuallyHidden>\n </span>\n );\n const done = state === 'done';\n return (\n <span {...css.attrs(checklistStyles.status)}>\n <button\n type=\"button\"\n role=\"checkbox\"\n aria-checked={done}\n aria-labelledby={labelId}\n aria-describedby={`${labelId}-status`}\n disabled={state === 'skipped' || state === 'blocked'}\n onClick={() => onCheckedChange(item, !done)}\n {...css.attrs(checklistStyles.toggle, focusRingStyles.visible)}\n >\n {statusIcon(item)}\n </button>\n <VisuallyHidden id={`${labelId}-status`}>{lang.checklistStatus[state]}</VisuallyHidden>\n </span>\n );\n };\n\n const labelSx = (item: ChecklistItem) => {\n const state = statusOf(item);\n return [\n checklistStyles.label,\n state === 'skipped'\n ? checklistStyles.labelSkipped\n : state !== 'done' && checklistStyles.labelPending,\n ];\n };\n\n /** 读屏念的整组:名称与状态(icons 排法) */\n const iconsLabel = () =>\n lang.checklistIconsLabel(\n items.map((item) =>\n lang.checklistItemState(\n typeof item.label === 'string' ? item.label : '',\n lang.checklistStatus[statusOf(item)],\n ),\n ),\n );\n\n const counted = () => items.filter((item) => statusOf(item) !== 'skipped');\n const doneCount = () => counted().filter((item) => statusOf(item) === 'done').length;\n\n return () => {\n if (layout === 'icons') {\n const label = iconsLabel();\n return (\n <span\n {...mergeAttrs<'span'>(\n { sx: [checklistStyles.icons, size && fontSizeStyles[size]] },\n rest as PartProps<'span'>,\n { role: 'img', 'aria-label': label, title: label },\n )}\n >\n {items.map((item, index) => (\n <span key={keyOf(item, index)}>{statusIcon(item)}</span>\n ))}\n </span>\n );\n }\n\n if (layout === 'inline')\n return (\n <ul\n {...mergeAttrs<'ul'>(\n { sx: [checklistStyles.inline, size && fontSizeStyles[size]] },\n rest as PartProps<'ul'>,\n )}\n >\n {items.map((item, index) => {\n const labelId = `${id}-${index}`;\n return (\n <li key={keyOf(item, index)} {...css.attrs(checklistStyles.inlineItem)}>\n {status(item, labelId)}\n <span id={labelId} {...css.attrs(labelSx(item))}>\n {item.label}\n </span>\n {hasContent(item.date) && (\n <span\n {...css.attrs(\n checklistStyles.meta,\n statusOf(item) === 'overdue' && checklistStyles.late,\n )}\n >\n {item.date}\n </span>\n )}\n {item.evidence}\n </li>\n );\n })}\n </ul>\n );\n\n const total = counted().length;\n return (\n <div\n {...mergeAttrs<'div'>({ sx: [checklistStyles.root, size && fontSizeStyles[size]] }, rest)}\n >\n {summary && total > 0 && (\n <div {...css.attrs(checklistStyles.summary)}>\n <span>{lang.checklistSummary(doneCount(), total)}</span>\n <Progress\n value={doneCount()}\n max={total}\n size=\"xs\"\n tone={doneCount() === total ? 'success' : 'accent'}\n aria-label={lang.checklistSummary(doneCount(), total)}\n />\n </div>\n )}\n <ul {...css.attrs(checklistStyles.list)}>\n {items.map((item, index) => {\n const own = typeof propsItem === 'function' ? propsItem(item) : propsItem;\n const labelId = `${id}-${index}`;\n const meta = [item.owner, item.date, item.evidence].some(hasContent);\n return (\n <li\n key={keyOf(item, index)}\n {...mergeAttrs<'li'>({ sx: checklistStyles.item }, own)}\n data-status={statusOf(item)}\n >\n {status(item, labelId)}\n <div {...css.attrs(checklistStyles.body)}>\n <span id={labelId} {...css.attrs(labelSx(item))}>\n {item.label}\n </span>\n {hasContent(item.description) && (\n <span {...css.attrs(checklistStyles.description)}>{item.description}</span>\n )}\n {meta && (\n <span {...css.attrs(checklistStyles.meta)}>\n {hasContent(item.owner) && <span>{item.owner}</span>}\n {hasContent(item.date) && (\n <span\n {...css.attrs(statusOf(item) === 'overdue' && checklistStyles.late)}\n >\n {item.date}\n </span>\n )}\n {item.evidence}\n </span>\n )}\n </div>\n {hasContent(item.action) ? (\n <div {...css.attrs(checklistStyles.action)}>{item.action}</div>\n ) : (\n <span />\n )}\n </li>\n );\n })}\n </ul>\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"Checklist.js","names":["_vtp_readonlyProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../src/display/Checklist.tsx"],"sourcesContent":["/**\n * 完成清单:一组要做完的事,每项的状态(完成、待办、超时、不适用、受阻)与它的上下文——怎么做、谁负责、哪天、证据、去处理。\n * 里程碑与交付证据、结项材料、上线检查、新用户的引导任务。参考 Shopify Polaris 的 Setup guide、GitHub 的任务列表。\n *\n * <Checklist\n * title=\"结项材料\"\n * summary\n * items={[\n * { label: '验收报告', status: 'done', date: '10-12', evidence: <Link href={url}>验证报告.pdf</Link> },\n * { label: '财务复核意见', status: 'overdue', owner: '财务部', date: '计划 10-20', action: <Button>催办</Button> },\n * { label: '合同签订记录', description: '谈定价格与生效日期,采购经理签字', owner: '采购部' },\n * ]}\n * />\n * <Checklist layout=\"inline\" items={…} /> 一行排开、放不下换行(详情行、卡片的一角)\n * <Checklist layout=\"icons\" aria-label=\"里程碑\" items={…} /> 只有一排状态图标(表格的格子里),读屏念每一项\n * <Checklist items={tasks} onCheckedChange={(item, done) => save(item.key, done)} /> 可以勾选(上线检查、引导任务)\n *\n * summary 在上面显示“已完成 2 / 3”与进度条(不适用的不算)。没完成的名称是次要色,不适用的划掉;\n * 超时的日期用危险色。每项的状态写在给读屏的文字里。\n *\n * 部件:Root(div)、Summary(汇总行)、List(ul)、Item(li,可以按项计算)、Status(状态图标,可勾选时是按钮)、Label、Meta。\n */\nimport { Ban, CircleAlert, CircleCheck, CircleDashed, CircleMinus } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { useId, type VNodeChild } from 'vue';\nimport { Icon, type IconData } from '../base/Icon';\nimport { VisuallyHidden } from '../base/VisuallyHidden';\nimport { useLang } from '../config/context';\nimport { Progress } from '../feedback/Progress';\nimport { hasContent, mergeAttrs, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\n\n/** 一项的状态 */\nexport interface ChecklistStatuses {\n /** 完成 */\n done: unknown;\n /** 待办(默认) */\n todo: unknown;\n /** 超时:过了计划日期还没完成 */\n overdue: unknown;\n /** 受阻:等别人、缺前提 */\n blocked: unknown;\n /** 不适用:这一次不用做,不算进进度 */\n skipped: unknown;\n}\n\n/** 清单的一项 */\nexport interface ChecklistItem {\n /** 唯一的 key;不写时用 label(label 是文字时)或位置 */\n key?: string;\n /** 名称 */\n label: VNodeChild;\n /** 状态,默认 todo */\n status?: keyof ChecklistStatuses;\n /** 说明:怎么做、要什么材料、缺的由谁出具 */\n description?: VNodeChild;\n /** 负责人(谁处理、谁出具) */\n owner?: VNodeChild;\n /** 日期:完成的日期,或计划日期(超时时用危险色) */\n date?: VNodeChild;\n /** 证据:附件、报告的链接 */\n evidence?: VNodeChild;\n /** 操作:上传证据、去处理、催办(结束边) */\n action?: VNodeChild;\n}\n\n/** 清单的排法 */\nexport interface ChecklistLayouts {\n /** 一项一行(默认):状态、名称与说明、负责人 · 日期 · 证据,操作在结束边 */\n list: unknown;\n /** 一行排开、放不下换行:状态、名称、日期、证据 */\n inline: unknown;\n /** 只有一排状态图标:表格的格子里;悬停与读屏有每一项的说明 */\n icons: unknown;\n}\n\n/** 未声明的属性落到外层元素上(list 是 div,inline 是 ul,icons 是 span) */\nexport interface ChecklistProps extends PartProps<'div'> {\n /** 各项 */\n items: readonly ChecklistItem[];\n /**\n * 排法\n * @default 'list'\n */\n layout?: keyof ChecklistLayouts;\n /** 上面显示“已完成 2 / 3”与进度条(list 排法) */\n summary?: boolean;\n /** 字号档位;不写时继承 */\n size?: TextSize;\n /** 可以勾选:状态图标变成复选按钮,点了报告新的完成状态(不适用、受阻的不能勾) */\n onCheckedChange?: (item: ChecklistItem, done: boolean) => void;\n /** 每一项(li)的部件属性,可以按项计算 */\n propsItem?: PartProps<'li'> | ((item: ChecklistItem) => PartProps<'li'>);\n}\n\n/** Checklist 的样式 */\nexport const checklistStyles = css.create({\n root: { display: 'grid', gap: '_sm' },\n summary: {\n display: 'grid',\n gridTemplateColumns: 'auto 1fr',\n alignItems: 'center',\n gap: '_md',\n fontSize: '_sm',\n color: '_textMuted',\n },\n list: { display: 'grid', margin: 0, padding: 0, listStyle: 'none' },\n // 状态一列、内容一列、操作一列;状态贴着名称那一行\n item: {\n display: 'grid',\n gridTemplateColumns: 'auto minmax(0, 1fr) auto',\n columnGap: '_sm',\n alignItems: 'start',\n paddingBlock: '_xs',\n },\n status: {\n display: 'flex',\n alignItems: 'center',\n minHeight: '1lh',\n fontSize: '1.125em',\n },\n // 可以勾选时的按钮:只有图标,去掉按钮的外观\n toggle: {\n display: 'inline-flex',\n padding: 0,\n margin: 0,\n borderWidth: 0,\n backgroundColor: 'transparent',\n color: 'inherit',\n font: 'inherit',\n borderRadius: '_full',\n cursor: { default: 'pointer', ':disabled': 'default' },\n },\n body: { display: 'grid', gap: '2px', minWidth: 0 },\n label: { color: '_text', overflowWrap: 'anywhere' },\n labelPending: { color: '_textMuted' },\n labelSkipped: { color: '_textMuted', textDecorationLine: 'line-through' },\n description: { fontSize: '_sm', color: '_textMuted' },\n meta: {\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n columnGap: '_sm',\n rowGap: '2px',\n fontSize: '_sm',\n color: '_textMuted',\n },\n late: { color: '_dangerText' },\n action: { display: 'flex', alignItems: 'center', gap: '_xs' },\n inline: {\n display: 'flex',\n flexWrap: 'wrap',\n columnGap: '_lg',\n rowGap: '_xs',\n margin: 0,\n padding: 0,\n listStyle: 'none',\n },\n inlineItem: { display: 'inline-flex', alignItems: 'center', gap: '_xs', whiteSpace: 'nowrap' },\n icons: { display: 'inline-flex', alignItems: 'center', gap: '2px' },\n});\n\n/** 各状态的图标与颜色 */\nexport const checklistStatusStyles = css.create({\n done: { color: '_successText' },\n todo: { color: '_textMuted' },\n overdue: { color: '_dangerText' },\n blocked: { color: '_warningText' },\n skipped: { color: '_textMuted' },\n});\n\nconst statusIcons: Record<keyof ChecklistStatuses, IconData> = {\n done: CircleCheck,\n todo: CircleDashed,\n overdue: CircleAlert,\n blocked: Ban,\n skipped: CircleMinus,\n};\n\nconst keyOf = (item: ChecklistItem, index: number) =>\n item.key ?? (typeof item.label === 'string' ? item.label : String(index));\n\nconst statusOf = (item: ChecklistItem): keyof ChecklistStatuses => item.status ?? 'todo';\n\n/** 完成清单 */\nexport const Checklist = _component(\n ({\n items,\n layout = 'list',\n summary = false,\n size,\n onCheckedChange,\n propsItem,\n ...rest\n }: ChecklistProps) => {\n const lang = useLang();\n const id = useId();\n\n const statusIcon = (item: ChecklistItem) => {\n const status = statusOf(item);\n return <Icon icon={statusIcons[status]} sx={checklistStatusStyles[status]} />;\n };\n\n /** 状态:可以勾选时是复选按钮(名称是这一项的名称),否则是图标加给读屏的状态文字 */\n const status = (item: ChecklistItem, labelId: string) => {\n const state = statusOf(item);\n if (!onCheckedChange)\n return (\n <span {...css.attrs(checklistStyles.status)}>\n {statusIcon(item)}\n <VisuallyHidden>{lang.checklistStatus[state]}</VisuallyHidden>\n </span>\n );\n const done = state === 'done';\n return (\n <span {...css.attrs(checklistStyles.status)}>\n <button\n type=\"button\"\n role=\"checkbox\"\n aria-checked={done}\n aria-labelledby={labelId}\n aria-describedby={`${labelId}-status`}\n disabled={state === 'skipped' || state === 'blocked'}\n onClick={() => onCheckedChange(item, !done)}\n {...css.attrs(checklistStyles.toggle, focusRingStyles.visible)}\n >\n {statusIcon(item)}\n </button>\n <VisuallyHidden id={`${labelId}-status`}>{lang.checklistStatus[state]}</VisuallyHidden>\n </span>\n );\n };\n\n const labelSx = (item: ChecklistItem) => {\n const state = statusOf(item);\n return [\n checklistStyles.label,\n state === 'skipped'\n ? checklistStyles.labelSkipped\n : state !== 'done' && checklistStyles.labelPending,\n ];\n };\n\n /** 读屏念的整组:名称与状态(icons 排法) */\n const iconsLabel = () =>\n lang.checklistIconsLabel(\n items.map((item) =>\n lang.checklistItemState(\n typeof item.label === 'string' ? item.label : '',\n lang.checklistStatus[statusOf(item)],\n ),\n ),\n );\n\n const counted = () => items.filter((item) => statusOf(item) !== 'skipped');\n const doneCount = () => counted().filter((item) => statusOf(item) === 'done').length;\n\n return () => {\n if (layout === 'icons') {\n const label = iconsLabel();\n return (\n <span\n {...mergeAttrs<'span'>(\n { sx: [checklistStyles.icons, size && fontSizeStyles[size]] },\n rest as PartProps<'span'>,\n { role: 'img', 'aria-label': label, title: label },\n )}\n >\n {items.map((item, index) => (\n <span key={keyOf(item, index)}>{statusIcon(item)}</span>\n ))}\n </span>\n );\n }\n\n if (layout === 'inline')\n return (\n <ul\n {...mergeAttrs<'ul'>(\n { sx: [checklistStyles.inline, size && fontSizeStyles[size]] },\n rest as PartProps<'ul'>,\n )}\n >\n {items.map((item, index) => {\n const labelId = `${id}-${index}`;\n return (\n <li key={keyOf(item, index)} {...css.attrs(checklistStyles.inlineItem)}>\n {status(item, labelId)}\n <span id={labelId} {...css.attrs(labelSx(item))}>\n {item.label}\n </span>\n {hasContent(item.date) && (\n <span\n {...css.attrs(\n checklistStyles.meta,\n statusOf(item) === 'overdue' && checklistStyles.late,\n )}\n >\n {item.date}\n </span>\n )}\n {item.evidence}\n </li>\n );\n })}\n </ul>\n );\n\n const total = counted().length;\n return (\n <div\n {...mergeAttrs<'div'>({ sx: [checklistStyles.root, size && fontSizeStyles[size]] }, rest)}\n >\n {summary && total > 0 && (\n <div {...css.attrs(checklistStyles.summary)}>\n <span>{lang.checklistSummary(doneCount(), total)}</span>\n <Progress\n value={doneCount()}\n max={total}\n size=\"xs\"\n tone={doneCount() === total ? 'success' : 'accent'}\n aria-label={lang.checklistSummary(doneCount(), total)}\n />\n </div>\n )}\n <ul {...css.attrs(checklistStyles.list)}>\n {items.map((item, index) => {\n const own = typeof propsItem === 'function' ? propsItem(item) : propsItem;\n const labelId = `${id}-${index}`;\n const meta = [item.owner, item.date, item.evidence].some(hasContent);\n return (\n <li\n key={keyOf(item, index)}\n {...mergeAttrs<'li'>({ sx: checklistStyles.item }, own)}\n data-status={statusOf(item)}\n >\n {status(item, labelId)}\n <div {...css.attrs(checklistStyles.body)}>\n <span id={labelId} {...css.attrs(labelSx(item))}>\n {item.label}\n </span>\n {hasContent(item.description) && (\n <span {...css.attrs(checklistStyles.description)}>{item.description}</span>\n )}\n {meta && (\n <span {...css.attrs(checklistStyles.meta)}>\n {hasContent(item.owner) && <span>{item.owner}</span>}\n {hasContent(item.date) && (\n <span\n {...css.attrs(statusOf(item) === 'overdue' && checklistStyles.late)}\n >\n {item.date}\n </span>\n )}\n {item.evidence}\n </span>\n )}\n </div>\n {hasContent(item.action) ? (\n <div {...css.attrs(checklistStyles.action)}>{item.action}</div>\n ) : (\n <span />\n )}\n </li>\n );\n })}\n </ul>\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -1,9 +1,10 @@
1
1
  import { t } from "../config/theme/tokens.js";
2
2
  import { mergeAttrs } from "../utils/props.js";
3
3
  import { afterTransitions } from "../utils/style/transitions.js";
4
+ import { useMounted } from "../utils/dom/mounted.js";
4
5
  import { useLazyContent } from "../utils/motion/presence.js";
5
- import { createVNode, mergeProps, ref, shallowRef } from "vue";
6
- import { _component, bindable, childrenProp, effect, readonlyProp, restProps, untrack } from "@zerodep-dev/vue-tsx-pro-tsx";
6
+ import { createVNode, ref, shallowRef } from "vue";
7
+ import { _component, bindable, childrenProp, effect, mergeJsxProps, readonlyProp, restProps, untrack } from "@zerodep-dev/vue-tsx-pro-tsx";
7
8
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
8
9
  //#region src/display/Collapse.tsx
9
10
  /** 未声明的属性落到外层的 div 上;要分区语义时在外面包 section */
@@ -31,6 +32,8 @@ var Collapse = /*#__PURE__*/ _component((_props, _ctx) => {
31
32
  let root = shallowRef(null);
32
33
  let collapsed = ref(untrack(() => !open.value));
33
34
  const showContent = useLazyContent(() => open.value, () => lazy.value);
35
+ const mounted = useMounted();
36
+ const untilFound = () => supportsUntilFound && mounted.value;
34
37
  effect(() => {
35
38
  if (open.value) {
36
39
  collapsed.value = false;
@@ -43,11 +46,11 @@ var Collapse = /*#__PURE__*/ _component((_props, _ctx) => {
43
46
  });
44
47
  return () => cancelled = true;
45
48
  });
46
- return () => createVNode("div", mergeProps(mergeAttrs({ sx: collapseStyles.root }, rest, {
49
+ return () => createVNode("div", mergeJsxProps(mergeAttrs({ sx: collapseStyles.root }, rest, {
47
50
  sx: open.value && collapseStyles.open,
48
51
  ref: root,
49
- hidden: collapsed.value && supportsUntilFound ? "until-found" : void 0,
50
- inert: collapsed.value && !supportsUntilFound ? true : void 0,
52
+ hidden: collapsed.value && untilFound() ? "until-found" : void 0,
53
+ inert: collapsed.value && !untilFound() ? true : void 0,
51
54
  onBeforematch: () => open.value = true
52
55
  }), { "data-state": open.value ? "open" : "closed" }), [createVNode("div", mergeAttrs({ sx: collapseStyles.content }, propsContent.value), [showContent() && children.value])]);
53
56
  }, {