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

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 (616) hide show
  1. package/dist/base/Blockquote.d.ts +1 -1
  2. package/dist/base/Blockquote.js +1 -1
  3. package/dist/base/Blockquote.js.map +1 -1
  4. package/dist/base/ButtonGroup.d.ts +1 -1
  5. package/dist/base/ButtonGroup.js +1 -1
  6. package/dist/base/ButtonGroup.js.map +1 -1
  7. package/dist/base/Code.d.ts +1 -1
  8. package/dist/base/Code.js +1 -1
  9. package/dist/base/Code.js.map +1 -1
  10. package/dist/base/CodeBlock.d.ts +1 -1
  11. package/dist/base/CodeBlock.js +1 -1
  12. package/dist/base/CodeBlock.js.map +1 -1
  13. package/dist/base/CopyButton.d.ts +1 -1
  14. package/dist/base/CopyButton.js +1 -1
  15. package/dist/base/CopyButton.js.map +1 -1
  16. package/dist/base/Heading.d.ts +1 -1
  17. package/dist/base/Heading.js +1 -1
  18. package/dist/base/Heading.js.map +1 -1
  19. package/dist/base/Icon.d.ts +1 -1
  20. package/dist/base/Icon.js +1 -1
  21. package/dist/base/Icon.js.map +1 -1
  22. package/dist/base/Indicator.d.ts +1 -1
  23. package/dist/base/Indicator.js +1 -1
  24. package/dist/base/Indicator.js.map +1 -1
  25. package/dist/base/Kbd.d.ts +1 -1
  26. package/dist/base/Kbd.js +1 -1
  27. package/dist/base/Kbd.js.map +1 -1
  28. package/dist/base/Link.d.ts +1 -1
  29. package/dist/base/Link.js +1 -1
  30. package/dist/base/Link.js.map +1 -1
  31. package/dist/base/List.d.ts +1 -1
  32. package/dist/base/List.js +1 -1
  33. package/dist/base/List.js.map +1 -1
  34. package/dist/base/Mark.d.ts +1 -1
  35. package/dist/base/Mark.js +1 -1
  36. package/dist/base/Mark.js.map +1 -1
  37. package/dist/base/Spinner.d.ts +1 -1
  38. package/dist/base/Spinner.js +1 -1
  39. package/dist/base/Spinner.js.map +1 -1
  40. package/dist/base/StatusDot.d.ts +1 -1
  41. package/dist/base/StatusDot.js +1 -1
  42. package/dist/base/StatusDot.js.map +1 -1
  43. package/dist/base/Tag.d.ts +1 -1
  44. package/dist/base/Tag.js +1 -1
  45. package/dist/base/Tag.js.map +1 -1
  46. package/dist/base/Text.d.ts +1 -1
  47. package/dist/base/Text.js +1 -1
  48. package/dist/base/Text.js.map +1 -1
  49. package/dist/base/VisuallyHidden.d.ts +1 -1
  50. package/dist/base/VisuallyHidden.js +1 -1
  51. package/dist/base/VisuallyHidden.js.map +1 -1
  52. package/dist/base/badge-styles.d.ts +1 -1
  53. package/dist/base/badge-styles.js +1 -1
  54. package/dist/base/badge-styles.js.map +1 -1
  55. package/dist/base/button-core.d.ts +1 -1
  56. package/dist/base/button-core.js +1 -1
  57. package/dist/base/button-core.js.map +1 -1
  58. package/dist/charts/ChordChart.d.ts +1 -1
  59. package/dist/charts/ChordChart.js +1 -1
  60. package/dist/charts/ChordChart.js.map +1 -1
  61. package/dist/charts/DonutChart.d.ts +1 -1
  62. package/dist/charts/DonutChart.js +1 -1
  63. package/dist/charts/DonutChart.js.map +1 -1
  64. package/dist/charts/FunnelChart.d.ts +1 -1
  65. package/dist/charts/FunnelChart.js +1 -1
  66. package/dist/charts/FunnelChart.js.map +1 -1
  67. package/dist/charts/GraphChart.d.ts +1 -1
  68. package/dist/charts/GraphChart.js +1 -1
  69. package/dist/charts/GraphChart.js.map +1 -1
  70. package/dist/charts/MapChart.d.ts +1 -1
  71. package/dist/charts/MapChart.js +1 -1
  72. package/dist/charts/MapChart.js.map +1 -1
  73. package/dist/charts/RadarChart.d.ts +1 -1
  74. package/dist/charts/RadarChart.js +1 -1
  75. package/dist/charts/RadarChart.js.map +1 -1
  76. package/dist/charts/SankeyChart.d.ts +1 -1
  77. package/dist/charts/SankeyChart.js +1 -1
  78. package/dist/charts/SankeyChart.js.map +1 -1
  79. package/dist/charts/TreemapChart.d.ts +1 -1
  80. package/dist/charts/TreemapChart.js +1 -1
  81. package/dist/charts/TreemapChart.js.map +1 -1
  82. package/dist/charts/XYChart.d.ts +1 -1
  83. package/dist/charts/XYChart.js +1 -1
  84. package/dist/charts/XYChart.js.map +1 -1
  85. package/dist/charts/frame.d.ts +1 -1
  86. package/dist/charts/frame.js +1 -1
  87. package/dist/charts/frame.js.map +1 -1
  88. package/dist/code-editor/CodeEditor.js +1 -1
  89. package/dist/code-editor/CodeEditor.js.map +1 -1
  90. package/dist/config/Provider.d.ts +1 -1
  91. package/dist/config/Provider.js +1 -1
  92. package/dist/config/Provider.js.map +1 -1
  93. package/dist/config/createUi.d.ts +1 -1
  94. package/dist/config/createUi.js +1 -1
  95. package/dist/config/createUi.js.map +1 -1
  96. package/dist/config/theme/coffee.d.ts +1 -1
  97. package/dist/config/theme/coffee.js +1 -1
  98. package/dist/config/theme/coffee.js.map +1 -1
  99. package/dist/config/theme/cyberpunk.d.ts +1 -1
  100. package/dist/config/theme/cyberpunk.js +1 -1
  101. package/dist/config/theme/cyberpunk.js.map +1 -1
  102. package/dist/config/theme/dark.d.ts +1 -1
  103. package/dist/config/theme/dark.js +1 -1
  104. package/dist/config/theme/dark.js.map +1 -1
  105. package/dist/config/theme/festive.d.ts +1 -1
  106. package/dist/config/theme/festive.js +1 -1
  107. package/dist/config/theme/festive.js.map +1 -1
  108. package/dist/config/theme/forest.d.ts +1 -1
  109. package/dist/config/theme/forest.js +1 -1
  110. package/dist/config/theme/forest.js.map +1 -1
  111. package/dist/config/theme/high-contrast.d.ts +1 -1
  112. package/dist/config/theme/high-contrast.js +1 -1
  113. package/dist/config/theme/high-contrast.js.map +1 -1
  114. package/dist/config/theme/lemon.d.ts +1 -1
  115. package/dist/config/theme/lemon.js +1 -1
  116. package/dist/config/theme/lemon.js.map +1 -1
  117. package/dist/config/theme/light.d.ts +1 -1
  118. package/dist/config/theme/light.js +1 -1
  119. package/dist/config/theme/light.js.map +1 -1
  120. package/dist/config/theme/midnight.d.ts +1 -1
  121. package/dist/config/theme/midnight.js +1 -1
  122. package/dist/config/theme/midnight.js.map +1 -1
  123. package/dist/config/theme/ocean.d.ts +1 -1
  124. package/dist/config/theme/ocean.js +1 -1
  125. package/dist/config/theme/ocean.js.map +1 -1
  126. package/dist/config/theme/paper.d.ts +1 -1
  127. package/dist/config/theme/paper.js +1 -1
  128. package/dist/config/theme/paper.js.map +1 -1
  129. package/dist/config/theme/sakura.d.ts +1 -1
  130. package/dist/config/theme/sakura.js +1 -1
  131. package/dist/config/theme/sakura.js.map +1 -1
  132. package/dist/config/theme/theme.js +1 -1
  133. package/dist/config/theme/theme.js.map +1 -1
  134. package/dist/config/theme/tokens.d.ts +1 -1
  135. package/dist/config/theme/tokens.js +1 -1
  136. package/dist/config/theme/tokens.js.map +1 -1
  137. package/dist/date/CalendarBoard.d.ts +1 -1
  138. package/dist/date/CalendarBoard.js +1 -1
  139. package/dist/date/CalendarBoard.js.map +1 -1
  140. package/dist/date/CalendarView.d.ts +1 -1
  141. package/dist/date/CalendarView.js +1 -1
  142. package/dist/date/CalendarView.js.map +1 -1
  143. package/dist/date/Countdown.d.ts +1 -1
  144. package/dist/date/Countdown.js +1 -1
  145. package/dist/date/Countdown.js.map +1 -1
  146. package/dist/date/DatePicker.d.ts +1 -1
  147. package/dist/date/DatePicker.js +1 -1
  148. package/dist/date/DatePicker.js.map +1 -1
  149. package/dist/date/DateRangePicker.d.ts +1 -1
  150. package/dist/date/DateRangePicker.js +1 -1
  151. package/dist/date/DateRangePicker.js.map +1 -1
  152. package/dist/date/DateSegmentGroup.d.ts +1 -1
  153. package/dist/date/DateSegmentGroup.js +1 -1
  154. package/dist/date/DateSegmentGroup.js.map +1 -1
  155. package/dist/date/QuarterCalendar.js +1 -1
  156. package/dist/date/QuarterCalendar.js.map +1 -1
  157. package/dist/date/SegmentedField.d.ts +1 -1
  158. package/dist/date/SegmentedField.js +1 -1
  159. package/dist/date/SegmentedField.js.map +1 -1
  160. package/dist/date/TimePicker.d.ts +1 -1
  161. package/dist/date/TimePicker.js +1 -1
  162. package/dist/date/TimePicker.js.map +1 -1
  163. package/dist/date/picker-popover.d.ts +1 -1
  164. package/dist/date/picker-popover.js +1 -1
  165. package/dist/date/picker-popover.js.map +1 -1
  166. package/dist/diagram/Diagram.d.ts +1 -1
  167. package/dist/diagram/Diagram.js +1 -1
  168. package/dist/diagram/Diagram.js.map +1 -1
  169. package/dist/diagram/DiagramControls.d.ts +1 -1
  170. package/dist/diagram/DiagramControls.js +1 -1
  171. package/dist/diagram/DiagramControls.js.map +1 -1
  172. package/dist/diagram/DiagramLanes.d.ts +1 -1
  173. package/dist/diagram/DiagramLanes.js +1 -1
  174. package/dist/diagram/DiagramLanes.js.map +1 -1
  175. package/dist/diagram/DiagramMinimap.d.ts +1 -1
  176. package/dist/diagram/DiagramMinimap.js +1 -1
  177. package/dist/diagram/DiagramMinimap.js.map +1 -1
  178. package/dist/diagram/DiagramNode.d.ts +1 -1
  179. package/dist/diagram/DiagramNode.js +1 -1
  180. package/dist/diagram/DiagramNode.js.map +1 -1
  181. package/dist/display/Accordion.d.ts +1 -1
  182. package/dist/display/Accordion.js +1 -1
  183. package/dist/display/Accordion.js.map +1 -1
  184. package/dist/display/AnimatedNumber.d.ts +1 -1
  185. package/dist/display/AnimatedNumber.js +1 -1
  186. package/dist/display/AnimatedNumber.js.map +1 -1
  187. package/dist/display/Avatar.d.ts +1 -1
  188. package/dist/display/Avatar.js +1 -1
  189. package/dist/display/Avatar.js.map +1 -1
  190. package/dist/display/AvatarGroup.d.ts +1 -1
  191. package/dist/display/AvatarGroup.js +1 -1
  192. package/dist/display/AvatarGroup.js.map +1 -1
  193. package/dist/display/Card.d.ts +1 -1
  194. package/dist/display/Card.js +1 -1
  195. package/dist/display/Card.js.map +1 -1
  196. package/dist/display/Checklist.d.ts +1 -1
  197. package/dist/display/Checklist.js +1 -1
  198. package/dist/display/Checklist.js.map +1 -1
  199. package/dist/display/Collapse.d.ts +1 -1
  200. package/dist/display/Collapse.js +1 -1
  201. package/dist/display/Collapse.js.map +1 -1
  202. package/dist/display/Descriptions.d.ts +1 -1
  203. package/dist/display/Descriptions.js +1 -1
  204. package/dist/display/Descriptions.js.map +1 -1
  205. package/dist/display/Ellipsis.d.ts +1 -1
  206. package/dist/display/Ellipsis.js +1 -1
  207. package/dist/display/Ellipsis.js.map +1 -1
  208. package/dist/display/FieldCompare.d.ts +1 -1
  209. package/dist/display/FieldCompare.js +1 -1
  210. package/dist/display/FieldCompare.js.map +1 -1
  211. package/dist/display/Gauge.d.ts +1 -1
  212. package/dist/display/Gauge.js +1 -1
  213. package/dist/display/Gauge.js.map +1 -1
  214. package/dist/display/Image.d.ts +1 -1
  215. package/dist/display/Image.js +1 -1
  216. package/dist/display/Image.js.map +1 -1
  217. package/dist/display/ItemList.d.ts +1 -1
  218. package/dist/display/ItemList.js +1 -1
  219. package/dist/display/ItemList.js.map +1 -1
  220. package/dist/display/Marquee.d.ts +1 -1
  221. package/dist/display/Marquee.js +1 -1
  222. package/dist/display/Marquee.js.map +1 -1
  223. package/dist/display/ProportionBar.d.ts +1 -1
  224. package/dist/display/ProportionBar.js +1 -1
  225. package/dist/display/ProportionBar.js.map +1 -1
  226. package/dist/display/Sortable.d.ts +1 -1
  227. package/dist/display/Sortable.js +1 -1
  228. package/dist/display/Sortable.js.map +1 -1
  229. package/dist/display/Sparkline.d.ts +1 -1
  230. package/dist/display/Sparkline.js +1 -1
  231. package/dist/display/Sparkline.js.map +1 -1
  232. package/dist/display/Stat.d.ts +1 -1
  233. package/dist/display/Stat.js +1 -1
  234. package/dist/display/Stat.js.map +1 -1
  235. package/dist/display/Timeline.d.ts +1 -1
  236. package/dist/display/Timeline.js +1 -1
  237. package/dist/display/Timeline.js.map +1 -1
  238. package/dist/display/Tree.d.ts +1 -1
  239. package/dist/display/Tree.js +1 -1
  240. package/dist/display/Tree.js.map +1 -1
  241. package/dist/display/VirtualList.d.ts +1 -1
  242. package/dist/display/VirtualList.js +1 -1
  243. package/dist/display/VirtualList.js.map +1 -1
  244. package/dist/display/Watermark.d.ts +1 -1
  245. package/dist/display/Watermark.js +1 -1
  246. package/dist/display/Watermark.js.map +1 -1
  247. package/dist/docs-kit/CodeGroup.d.ts +1 -1
  248. package/dist/docs-kit/CodeGroup.js +1 -1
  249. package/dist/docs-kit/CodeGroup.js.map +1 -1
  250. package/dist/docs-kit/CodePreview.d.ts +1 -1
  251. package/dist/docs-kit/CodePreview.js +1 -1
  252. package/dist/docs-kit/CodePreview.js.map +1 -1
  253. package/dist/docs-kit/ColorSwatch.d.ts +1 -1
  254. package/dist/docs-kit/ColorSwatch.js +1 -1
  255. package/dist/docs-kit/ColorSwatch.js.map +1 -1
  256. package/dist/docs-kit/PropsTable.d.ts +1 -1
  257. package/dist/docs-kit/PropsTable.js +1 -1
  258. package/dist/docs-kit/PropsTable.js.map +1 -1
  259. package/dist/feedback/Alert.d.ts +1 -1
  260. package/dist/feedback/Alert.js +1 -1
  261. package/dist/feedback/Alert.js.map +1 -1
  262. package/dist/feedback/Banner.d.ts +1 -1
  263. package/dist/feedback/Banner.js +1 -1
  264. package/dist/feedback/Banner.js.map +1 -1
  265. package/dist/feedback/Empty.d.ts +1 -1
  266. package/dist/feedback/Empty.js +1 -1
  267. package/dist/feedback/Empty.js.map +1 -1
  268. package/dist/feedback/LoadingBar.d.ts +1 -1
  269. package/dist/feedback/LoadingBar.js +1 -1
  270. package/dist/feedback/LoadingBar.js.map +1 -1
  271. package/dist/feedback/LoadingOverlay.d.ts +1 -1
  272. package/dist/feedback/LoadingOverlay.js +1 -1
  273. package/dist/feedback/LoadingOverlay.js.map +1 -1
  274. package/dist/feedback/Progress.d.ts +1 -1
  275. package/dist/feedback/Progress.js +1 -1
  276. package/dist/feedback/Progress.js.map +1 -1
  277. package/dist/feedback/Result.d.ts +1 -1
  278. package/dist/feedback/Result.js +1 -1
  279. package/dist/feedback/Result.js.map +1 -1
  280. package/dist/feedback/Skeleton.d.ts +1 -1
  281. package/dist/feedback/Skeleton.js +1 -1
  282. package/dist/feedback/Skeleton.js.map +1 -1
  283. package/dist/feedback/SkeletonText.d.ts +1 -1
  284. package/dist/feedback/SkeletonText.js +1 -1
  285. package/dist/feedback/SkeletonText.js.map +1 -1
  286. package/dist/feedback/Toast.d.ts +1 -1
  287. package/dist/feedback/Toast.js +1 -1
  288. package/dist/feedback/Toast.js.map +1 -1
  289. package/dist/form/Field.d.ts +1 -1
  290. package/dist/form/Field.js +1 -1
  291. package/dist/form/Field.js.map +1 -1
  292. package/dist/form/FormErrorSummary.d.ts +1 -1
  293. package/dist/form/FormErrorSummary.js +1 -1
  294. package/dist/form/FormErrorSummary.js.map +1 -1
  295. package/dist/form/FormSection.d.ts +1 -1
  296. package/dist/form/FormSection.js +1 -1
  297. package/dist/form/FormSection.js.map +1 -1
  298. package/dist/form/schemas.d.ts +1 -1
  299. package/dist/form/schemas.js +1 -1
  300. package/dist/form/schemas.js.map +1 -1
  301. package/dist/input/Cascader.d.ts +1 -1
  302. package/dist/input/Cascader.js +1 -1
  303. package/dist/input/Cascader.js.map +1 -1
  304. package/dist/input/CharacterCount.d.ts +1 -1
  305. package/dist/input/CharacterCount.js +1 -1
  306. package/dist/input/CharacterCount.js.map +1 -1
  307. package/dist/input/Checkbox.d.ts +1 -1
  308. package/dist/input/Checkbox.js +1 -1
  309. package/dist/input/Checkbox.js.map +1 -1
  310. package/dist/input/ColorField.d.ts +1 -1
  311. package/dist/input/ColorField.js +1 -1
  312. package/dist/input/ColorField.js.map +1 -1
  313. package/dist/input/Combobox.d.ts +1 -1
  314. package/dist/input/Combobox.js +1 -1
  315. package/dist/input/Combobox.js.map +1 -1
  316. package/dist/input/ConditionBuilder.d.ts +1 -1
  317. package/dist/input/ConditionBuilder.js +1 -1
  318. package/dist/input/ConditionBuilder.js.map +1 -1
  319. package/dist/input/ControlGroup.d.ts +1 -1
  320. package/dist/input/ControlGroup.js +1 -1
  321. package/dist/input/ControlGroup.js.map +1 -1
  322. package/dist/input/FileDrop.d.ts +1 -1
  323. package/dist/input/FileDrop.js +1 -1
  324. package/dist/input/FileDrop.js.map +1 -1
  325. package/dist/input/ListPopover.d.ts +1 -1
  326. package/dist/input/ListPopover.js +1 -1
  327. package/dist/input/ListPopover.js.map +1 -1
  328. package/dist/input/Listbox.d.ts +1 -1
  329. package/dist/input/Listbox.js +1 -1
  330. package/dist/input/Listbox.js.map +1 -1
  331. package/dist/input/Mentions.d.ts +1 -1
  332. package/dist/input/Mentions.js +1 -1
  333. package/dist/input/Mentions.js.map +1 -1
  334. package/dist/input/NumberRangeField.d.ts +1 -1
  335. package/dist/input/NumberRangeField.js +1 -1
  336. package/dist/input/NumberRangeField.js.map +1 -1
  337. package/dist/input/OtpField.d.ts +1 -1
  338. package/dist/input/OtpField.js +1 -1
  339. package/dist/input/OtpField.js.map +1 -1
  340. package/dist/input/PeoplePicker.js +1 -1
  341. package/dist/input/PeoplePicker.js.map +1 -1
  342. package/dist/input/PeoplePickerPanel.d.ts +1 -1
  343. package/dist/input/PeoplePickerPanel.js +1 -1
  344. package/dist/input/PeoplePickerPanel.js.map +1 -1
  345. package/dist/input/Radio.d.ts +1 -1
  346. package/dist/input/Radio.js +1 -1
  347. package/dist/input/Radio.js.map +1 -1
  348. package/dist/input/Rating.d.ts +1 -1
  349. package/dist/input/Rating.js +1 -1
  350. package/dist/input/Rating.js.map +1 -1
  351. package/dist/input/Select.d.ts +1 -1
  352. package/dist/input/Select.js +1 -1
  353. package/dist/input/Select.js.map +1 -1
  354. package/dist/input/SelectedTags.d.ts +1 -1
  355. package/dist/input/SelectedTags.js +1 -1
  356. package/dist/input/SelectedTags.js.map +1 -1
  357. package/dist/input/Slider.d.ts +1 -1
  358. package/dist/input/Slider.js +1 -1
  359. package/dist/input/Slider.js.map +1 -1
  360. package/dist/input/Switch.d.ts +1 -1
  361. package/dist/input/Switch.js +1 -1
  362. package/dist/input/Switch.js.map +1 -1
  363. package/dist/input/TagsInput.d.ts +1 -1
  364. package/dist/input/TagsInput.js +1 -1
  365. package/dist/input/TagsInput.js.map +1 -1
  366. package/dist/input/Textarea.d.ts +1 -1
  367. package/dist/input/Textarea.js +1 -1
  368. package/dist/input/Textarea.js.map +1 -1
  369. package/dist/input/ToggleGroup.d.ts +1 -1
  370. package/dist/input/ToggleGroup.js +1 -1
  371. package/dist/input/ToggleGroup.js.map +1 -1
  372. package/dist/input/Transfer.d.ts +1 -1
  373. package/dist/input/Transfer.js +1 -1
  374. package/dist/input/Transfer.js.map +1 -1
  375. package/dist/input/TreeSelect.d.ts +1 -1
  376. package/dist/input/TreeSelect.js +1 -1
  377. package/dist/input/TreeSelect.js.map +1 -1
  378. package/dist/input/Upload.d.ts +1 -1
  379. package/dist/input/Upload.js +1 -1
  380. package/dist/input/Upload.js.map +1 -1
  381. package/dist/input/choice-styles.d.ts +1 -1
  382. package/dist/input/choice-styles.js +1 -1
  383. package/dist/input/choice-styles.js.map +1 -1
  384. package/dist/input/control.d.ts +1 -1
  385. package/dist/input/control.js +1 -1
  386. package/dist/input/control.js.map +1 -1
  387. package/dist/layout/Affix.d.ts +1 -1
  388. package/dist/layout/Affix.js +1 -1
  389. package/dist/layout/Affix.js.map +1 -1
  390. package/dist/layout/AsideLayout.d.ts +1 -1
  391. package/dist/layout/AsideLayout.js +1 -1
  392. package/dist/layout/AsideLayout.js.map +1 -1
  393. package/dist/layout/BackTop.d.ts +1 -1
  394. package/dist/layout/BackTop.js +1 -1
  395. package/dist/layout/BackTop.js.map +1 -1
  396. package/dist/layout/Container.d.ts +1 -1
  397. package/dist/layout/Container.js +1 -1
  398. package/dist/layout/Container.js.map +1 -1
  399. package/dist/layout/Flex.d.ts +1 -1
  400. package/dist/layout/Flex.js +1 -1
  401. package/dist/layout/Flex.js.map +1 -1
  402. package/dist/layout/Grid.d.ts +1 -1
  403. package/dist/layout/Grid.js +1 -1
  404. package/dist/layout/Grid.js.map +1 -1
  405. package/dist/layout/PageScrollbar.d.ts +1 -1
  406. package/dist/layout/PageScrollbar.js +1 -1
  407. package/dist/layout/PageScrollbar.js.map +1 -1
  408. package/dist/layout/Prose.d.ts +1 -1
  409. package/dist/layout/Prose.js +1 -1
  410. package/dist/layout/Prose.js.map +1 -1
  411. package/dist/layout/ResizeHandle.d.ts +1 -1
  412. package/dist/layout/ResizeHandle.js +1 -1
  413. package/dist/layout/ResizeHandle.js.map +1 -1
  414. package/dist/layout/ScrollArea.d.ts +1 -1
  415. package/dist/layout/ScrollArea.js +1 -1
  416. package/dist/layout/ScrollArea.js.map +1 -1
  417. package/dist/layout/Separator.d.ts +1 -1
  418. package/dist/layout/Separator.js +1 -1
  419. package/dist/layout/Separator.js.map +1 -1
  420. package/dist/layout/Splitter.d.ts +1 -1
  421. package/dist/layout/Splitter.js +1 -1
  422. package/dist/layout/Splitter.js.map +1 -1
  423. package/dist/layout/ViewportFill.d.ts +1 -1
  424. package/dist/layout/ViewportFill.js +1 -1
  425. package/dist/layout/ViewportFill.js.map +1 -1
  426. package/dist/navigation/Breadcrumbs.d.ts +1 -1
  427. package/dist/navigation/Breadcrumbs.js +1 -1
  428. package/dist/navigation/Breadcrumbs.js.map +1 -1
  429. package/dist/navigation/NavBar.d.ts +1 -1
  430. package/dist/navigation/NavBar.js +1 -1
  431. package/dist/navigation/NavBar.js.map +1 -1
  432. package/dist/navigation/NavList.d.ts +1 -1
  433. package/dist/navigation/NavList.js +1 -1
  434. package/dist/navigation/NavList.js.map +1 -1
  435. package/dist/navigation/PageJump.d.ts +1 -1
  436. package/dist/navigation/PageJump.js +1 -1
  437. package/dist/navigation/PageJump.js.map +1 -1
  438. package/dist/navigation/PageSizeSelect.d.ts +1 -1
  439. package/dist/navigation/PageSizeSelect.js +1 -1
  440. package/dist/navigation/PageSizeSelect.js.map +1 -1
  441. package/dist/navigation/Pager.d.ts +1 -1
  442. package/dist/navigation/Pager.js +1 -1
  443. package/dist/navigation/Pager.js.map +1 -1
  444. package/dist/navigation/Pagination.d.ts +1 -1
  445. package/dist/navigation/Pagination.js +1 -1
  446. package/dist/navigation/Pagination.js.map +1 -1
  447. package/dist/navigation/PaginationBar.d.ts +1 -1
  448. package/dist/navigation/PaginationBar.js +1 -1
  449. package/dist/navigation/PaginationBar.js.map +1 -1
  450. package/dist/navigation/SkipLink.d.ts +1 -1
  451. package/dist/navigation/SkipLink.js +1 -1
  452. package/dist/navigation/SkipLink.js.map +1 -1
  453. package/dist/navigation/Steps.d.ts +1 -1
  454. package/dist/navigation/Steps.js +1 -1
  455. package/dist/navigation/Steps.js.map +1 -1
  456. package/dist/navigation/TableOfContents.d.ts +1 -1
  457. package/dist/navigation/TableOfContents.js +1 -1
  458. package/dist/navigation/TableOfContents.js.map +1 -1
  459. package/dist/navigation/Tabs.d.ts +1 -1
  460. package/dist/navigation/Tabs.js +1 -1
  461. package/dist/navigation/Tabs.js.map +1 -1
  462. package/dist/navigation/Toolbar.d.ts +1 -1
  463. package/dist/navigation/Toolbar.js +1 -1
  464. package/dist/navigation/Toolbar.js.map +1 -1
  465. package/dist/overlay/CommandPalette.d.ts +1 -1
  466. package/dist/overlay/CommandPalette.js +1 -1
  467. package/dist/overlay/CommandPalette.js.map +1 -1
  468. package/dist/overlay/Dialog.d.ts +1 -1
  469. package/dist/overlay/Dialog.js +1 -1
  470. package/dist/overlay/Dialog.js.map +1 -1
  471. package/dist/overlay/Drawer.d.ts +1 -1
  472. package/dist/overlay/Drawer.js +1 -1
  473. package/dist/overlay/Drawer.js.map +1 -1
  474. package/dist/overlay/HoverCard.d.ts +1 -1
  475. package/dist/overlay/HoverCard.js +1 -1
  476. package/dist/overlay/HoverCard.js.map +1 -1
  477. package/dist/overlay/Lightbox.d.ts +1 -1
  478. package/dist/overlay/Lightbox.js +1 -1
  479. package/dist/overlay/Lightbox.js.map +1 -1
  480. package/dist/overlay/Menu.d.ts +1 -1
  481. package/dist/overlay/Menu.js +1 -1
  482. package/dist/overlay/Menu.js.map +1 -1
  483. package/dist/overlay/Popconfirm.d.ts +1 -1
  484. package/dist/overlay/Popconfirm.js +1 -1
  485. package/dist/overlay/Popconfirm.js.map +1 -1
  486. package/dist/overlay/Popover.d.ts +1 -1
  487. package/dist/overlay/Popover.js +1 -1
  488. package/dist/overlay/Popover.js.map +1 -1
  489. package/dist/overlay/Tooltip.d.ts +1 -1
  490. package/dist/overlay/Tooltip.js +1 -1
  491. package/dist/overlay/Tooltip.js.map +1 -1
  492. package/dist/overlay/Tour.d.ts +1 -1
  493. package/dist/overlay/Tour.js +1 -1
  494. package/dist/overlay/Tour.js.map +1 -1
  495. package/dist/patterns/ActionBar.d.ts +1 -1
  496. package/dist/patterns/ActionBar.js +1 -1
  497. package/dist/patterns/ActionBar.js.map +1 -1
  498. package/dist/patterns/AppShell.d.ts +1 -1
  499. package/dist/patterns/AppShell.js +1 -1
  500. package/dist/patterns/AppShell.js.map +1 -1
  501. package/dist/patterns/AuthLayout.d.ts +2 -2
  502. package/dist/patterns/AuthLayout.js +2 -2
  503. package/dist/patterns/AuthLayout.js.map +1 -1
  504. package/dist/patterns/CommentThread.d.ts +1 -1
  505. package/dist/patterns/CommentThread.js +1 -1
  506. package/dist/patterns/CommentThread.js.map +1 -1
  507. package/dist/patterns/DataImport.d.ts +1 -1
  508. package/dist/patterns/DataImport.js +1 -1
  509. package/dist/patterns/DataImport.js.map +1 -1
  510. package/dist/patterns/FilterBar.d.ts +1 -1
  511. package/dist/patterns/FilterBar.js +1 -1
  512. package/dist/patterns/FilterBar.js.map +1 -1
  513. package/dist/patterns/KanbanBoard.d.ts +1 -1
  514. package/dist/patterns/KanbanBoard.js +1 -1
  515. package/dist/patterns/KanbanBoard.js.map +1 -1
  516. package/dist/patterns/NotificationCenter.d.ts +1 -1
  517. package/dist/patterns/NotificationCenter.js +1 -1
  518. package/dist/patterns/NotificationCenter.js.map +1 -1
  519. package/dist/patterns/QueryTable.d.ts +1 -1
  520. package/dist/patterns/QueryTable.js +1 -1
  521. package/dist/patterns/QueryTable.js.map +1 -1
  522. package/dist/patterns/SlideCaptcha.d.ts +1 -1
  523. package/dist/patterns/SlideCaptcha.js +1 -1
  524. package/dist/patterns/SlideCaptcha.js.map +1 -1
  525. package/dist/patterns/StepsForm.d.ts +1 -1
  526. package/dist/patterns/StepsForm.js +1 -1
  527. package/dist/patterns/StepsForm.js.map +1 -1
  528. package/dist/table/ColumnHeaderActions.d.ts +1 -1
  529. package/dist/table/ColumnHeaderActions.js +1 -1
  530. package/dist/table/ColumnHeaderActions.js.map +1 -1
  531. package/dist/table/ColumnSettings.d.ts +1 -1
  532. package/dist/table/ColumnSettings.js +1 -1
  533. package/dist/table/ColumnSettings.js.map +1 -1
  534. package/dist/table/ColumnTable.d.ts +1 -1
  535. package/dist/table/ColumnTable.js +1 -1
  536. package/dist/table/ColumnTable.js.map +1 -1
  537. package/dist/table/DataTableView.d.ts +1 -1
  538. package/dist/table/DataTableView.js +1 -1
  539. package/dist/table/DataTableView.js.map +1 -1
  540. package/dist/table/PivotTable.d.ts +1 -1
  541. package/dist/table/PivotTable.js +1 -1
  542. package/dist/table/PivotTable.js.map +1 -1
  543. package/dist/table/SelectionBar.d.ts +1 -1
  544. package/dist/table/SelectionBar.js +1 -1
  545. package/dist/table/SelectionBar.js.map +1 -1
  546. package/dist/table/Table.d.ts +1 -1
  547. package/dist/table/Table.js +1 -1
  548. package/dist/table/Table.js.map +1 -1
  549. package/dist/table/TreeDataTable.d.ts +1 -1
  550. package/dist/table/TreeDataTable.js +1 -1
  551. package/dist/table/TreeDataTable.js.map +1 -1
  552. package/dist/table/table-styles.d.ts +1 -1
  553. package/dist/table/table-styles.js +1 -1
  554. package/dist/table/table-styles.js.map +1 -1
  555. package/dist/theme-customize/ThemeCustomizer.d.ts +1 -1
  556. package/dist/theme-customize/ThemeCustomizer.js +1 -1
  557. package/dist/theme-customize/ThemeCustomizer.js.map +1 -1
  558. package/dist/theme-customize/ThemeThumbnail.d.ts +1 -1
  559. package/dist/theme-customize/ThemeThumbnail.js +1 -1
  560. package/dist/theme-customize/ThemeThumbnail.js.map +1 -1
  561. package/dist/theme-customize/design-tokens.js +1 -1
  562. package/dist/theme-customize/design-tokens.js.map +1 -1
  563. package/dist/three/core/EffectSurface.d.ts +1 -1
  564. package/dist/three/core/EffectSurface.js +1 -1
  565. package/dist/three/core/EffectSurface.js.map +1 -1
  566. package/dist/three/core/ThreeCanvas.d.ts +1 -1
  567. package/dist/three/core/ThreeCanvas.js +1 -1
  568. package/dist/three/core/ThreeCanvas.js.map +1 -1
  569. package/dist/three/effects/Confetti.d.ts +1 -1
  570. package/dist/three/effects/Confetti.js +1 -1
  571. package/dist/three/effects/Confetti.js.map +1 -1
  572. package/dist/three/globe/Globe.d.ts +1 -1
  573. package/dist/three/globe/Globe.js +1 -1
  574. package/dist/three/globe/Globe.js.map +1 -1
  575. package/dist/three/model/ModelViewer.d.ts +1 -1
  576. package/dist/three/model/ModelViewer.js +1 -1
  577. package/dist/three/model/ModelViewer.js.map +1 -1
  578. package/dist/utils/dom/floating.d.ts +1 -1
  579. package/dist/utils/dom/floating.js +1 -1
  580. package/dist/utils/dom/floating.js.map +1 -1
  581. package/dist/utils/dom/ripple.d.ts +1 -1
  582. package/dist/utils/dom/ripple.js +1 -1
  583. package/dist/utils/dom/ripple.js.map +1 -1
  584. package/dist/utils/props.js +1 -1
  585. package/dist/utils/props.js.map +1 -1
  586. package/dist/utils/style/attached.d.ts +1 -1
  587. package/dist/utils/style/attached.js +1 -1
  588. package/dist/utils/style/attached.js.map +1 -1
  589. package/dist/utils/style/item-styles.d.ts +1 -1
  590. package/dist/utils/style/item-styles.js +1 -1
  591. package/dist/utils/style/item-styles.js.map +1 -1
  592. package/dist/utils/style/markers.d.ts +1 -1
  593. package/dist/utils/style/markers.js +1 -1
  594. package/dist/utils/style/markers.js.map +1 -1
  595. package/dist/utils/style/shimmer.d.ts +1 -1
  596. package/dist/utils/style/shimmer.js +1 -1
  597. package/dist/utils/style/shimmer.js.map +1 -1
  598. package/dist/utils/style/styles.d.ts +1 -1
  599. package/dist/utils/style/styles.js +1 -1
  600. package/dist/utils/style/styles.js.map +1 -1
  601. package/dist/utils/style/swatch-styles.d.ts +1 -1
  602. package/dist/utils/style/swatch-styles.js +1 -1
  603. package/dist/utils/style/swatch-styles.js.map +1 -1
  604. package/dist/utils/style/tone-styles.d.ts +1 -1
  605. package/dist/utils/style/tone-styles.js +1 -1
  606. package/dist/utils/style/tone-styles.js.map +1 -1
  607. package/dist/utils/style/transitions.d.ts +1 -1
  608. package/dist/utils/style/transitions.js +1 -1
  609. package/dist/utils/style/transitions.js.map +1 -1
  610. package/dist/utils/style/typography.d.ts +1 -1
  611. package/dist/utils/style/typography.js +1 -1
  612. package/dist/utils/style/typography.js.map +1 -1
  613. package/dist/utils/style/vars.d.ts +1 -1
  614. package/dist/utils/style/vars.js +1 -1
  615. package/dist/utils/style/vars.js.map +1 -1
  616. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"QueryTable.js","names":["_isVNode","_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vtp_untrack","_vue_shallowRef","_createVNode","Menu","_mergeProps"],"sources":["../../src/patterns/QueryTable.tsx"],"sourcesContent":["/**\n * 查询表格(列表页的整块):查询栏(FilterBar)+ 工具栏(标题、自己的按钮、刷新、行高、列设置、全屏)+ 批量操作栏 + 数据表格 + 分页栏。\n * 有查询栏时工具栏并进查询栏那一行,压成一行:标题 条件 查询 重置 展开 … 自己的按钮 刷新 行高 列设置 全屏;\n * 条件多时把不常用的放进 moreFilters,点“展开”后更多条件排在这一行下面。没有查询栏、或全屏(全屏的只有表格那一块)时,\n * 工具栏是表格上方单独的一行。fill 时整块占满到窗口底边(ViewportFill),行多了在表格里滚动,分页留在一屏里。\n * 状态都在 useTableQuery 里(服务端分页、排序、条件)。同 Ant Design ProComponents 的 ProTable。\n *\n * const tasks = useTableQuery(fetchTasks, { filters: { keyword: '', status: '' }, pageSize: 20 });\n * <QueryTable\n * query={tasks} columns={columns} getKey={(task) => task.id} title=\"任务台账\" persistKey=\"tasks\"\n * filters={(draft) => <Field label=\"关键字\"><TextField _value={draft.keyword} /></Field>}\n * toolbar={<Button icon={Plus}>新建</Button>}\n * />\n *\n * - 查询栏的条件改的是草稿(draft),点“查询”(或回车)才交给 query.search;“重置”回到 blankFilters(不写时是一开始的条件)并查询。\n * - 表头排序交给服务端(manualSort,写回 query.sort;multiSort 时按住 Shift 追加一列,写回 query.sorts),\n * 表头筛选也交给服务端(manualFilter,写回 query.columnFilters;列的 filter 要写 options,否则只列出当前这页出现过的值),\n * 分页栏绑定 query.page / pageSize / total。fetcher 用 tableParams(query, columns) 把这些写成接口的参数。\n * - persistKey:列设置(显示、顺序、固定、列宽)与行高记在浏览器里,下次打开还是这样。\n * - selectionMode 时勾选行,表格上方出现批量操作栏,batchActions 拿到已选的 key 给出按钮。\n *\n * 部件:Root(div)、FilterBar、Panel(工具栏与表格所在的区域,全屏的就是它)、Toolbar(div)、Title(div)、\n * Table(DataTable)、SelectionBar、Pagination(PaginationBar)。\n */\nimport { Maximize, Minimize, RefreshCw, Rows3 } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { reactive, shallowRef, type Ref, type VNodeChild } from 'vue';\nimport { Button } from '../base/Button';\nimport { IconButton, type IconButtonProps } from '../base/IconButton';\nimport { useLang } from '../config/context';\nimport { useMessages } from '../config/lang/messages';\nimport { Alert, type AlertProps } from '../feedback/Alert';\nimport { PaginationBar, type PaginationBarProps } from '../navigation/PaginationBar';\nimport { Menu, MenuRadioGroup, MenuRadioItem } from '../overlay/Menu';\nimport { ColumnSettings } from '../table/ColumnSettings';\nimport type { ColumnStickies, DataTableColumn } from '../table/columns';\nimport { ViewportFill } from '../layout/ViewportFill';\nimport { DataTable, type DataTableProps } from '../table/DataTable';\nimport { SelectionBar, type SelectionBarProps } from '../table/SelectionBar';\nimport type { DataTableDensities } from '../table/table-styles';\nimport type { TablePage, TableQueryState } from '../table/use-table-query';\nimport { cloneValue } from '../utils/data/clone';\nimport { useFullscreen } from '../utils/dom/fullscreen';\nimport { usePersistentState } from '../utils/dom/storage';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { errorMessage } from '../utils/request/error-message';\nimport { FilterBar, type FilterBarProps } from './FilterBar';\nimport { patternsMessages } from './messages';\n\n/** 未声明的属性落到外层 div 上 */\nexport interface QueryTableProps<T, Filters extends object> extends PartProps<'div'> {\n /** 列表状态:useTableQuery 的返回值 */\n query: TableQueryState<TablePage<T>, Filters>;\n /** 列定义 */\n columns: readonly DataTableColumn<T>[];\n /** 行的 key */\n getKey: (row: T, index: number) => string;\n /** 表格的名称(工具栏起始边的标题,也是表格的 aria-label) */\n title: string;\n /** 查询栏的条件:拿到草稿,控件绑定它的字段(`_value={draft.keyword}`);不写时没有查询栏 */\n filters?: (draft: Filters) => VNodeChild;\n /** 收起的条件(不常用的),点“展开”才显示 */\n moreFilters?: (draft: Filters) => VNodeChild;\n /** “重置”回到的条件;不写时是 query 一开始的条件 */\n blankFilters?: Filters;\n /** 占满到窗口底边(列表页的整页):行多了在表格里滚动,分页一直在一屏里 */\n fill?: boolean;\n /** 工具栏上自己的按钮(新建、导出),在标题之后、内置按钮之前 */\n toolbar?: VNodeChild;\n /** 列设置与行高记在浏览器里的键(localStorage,自动加前缀);不写时只在这次打开里有效 */\n persistKey?: string;\n /** 多列排序:按住 Shift 点列标题追加一列(同 DataTable 的 multiSort),排序写在 query.sorts */\n multiSort?: boolean;\n /** 勾选行:多选时表格上方出现批量操作栏 */\n selectionMode?: DataTableProps<T>['selectionMode'];\n /** 已选行的 key:父级写 _selected={keys} */\n _selected?: string[];\n /** 批量操作栏里的按钮:拿到已选的 key */\n batchActions?: (keys: readonly string[]) => VNodeChild;\n /** 查询栏(FilterBar)的部件属性 */\n propsFilterBar?: Partial<FilterBarProps>;\n /** 工具栏与表格所在区域的部件属性(全屏的就是它) */\n propsPanel?: PartProps<'div'>;\n /** 工具栏的部件属性 */\n propsToolbar?: PartProps<'div'>;\n /** 表格(DataTable)的部件属性:列宽、详情行、行的色调等直接写在这里 */\n propsTable?: Partial<DataTableProps<T>>;\n /** 批量操作栏的部件属性 */\n propsSelectionBar?: Partial<SelectionBarProps>;\n /** 分页栏的部件属性 */\n propsPagination?: Partial<PaginationBarProps>;\n /** 加载失败时表格上方的提示条(Alert)的部件属性 */\n propsError?: Partial<AlertProps>;\n /** 工具栏内置按钮(刷新、行高、全屏)的部件属性 */\n propsToolbarButton?: Partial<IconButtonProps>;\n}\n\n/** QueryTable 的样式:root、rootFill、panel、panelFullscreen、panelFill、toolbar、title、tools、titleInline、toolbarInline */\nexport const queryTableStyles = css.create({\n root: { display: 'flex', flexDirection: 'column', gap: '_md', minWidth: 0 },\n panel: {\n display: 'flex',\n flexDirection: 'column',\n gap: '_sm',\n minWidth: 0,\n backgroundColor: '_surface',\n },\n // 全屏时铺满屏幕、四周留白,表格占满剩下的高度\n panelFullscreen: { padding: '_lg', overflow: 'auto' },\n // fill 时外面的高度定了,整块与区域可以压矮,压不下的在表格里滚动\n rootFill: { flexGrow: 1, minHeight: 0 },\n panelFill: { minHeight: 0 },\n toolbar: { display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: '_sm' },\n title: { flexGrow: 1, minWidth: 0, fontWeight: '_semibold', fontSize: '_lg' },\n tools: { display: 'flex', alignItems: 'center', gap: '_xs' },\n // 并进查询栏那一行时:标题不撑开,按钮靠在一起\n titleInline: { flexShrink: 0, fontWeight: '_semibold', fontSize: '_lg' },\n toolbarInline: { display: 'flex', alignItems: 'center', gap: '_sm' },\n});\n\n/** 存在浏览器里(给了 persistKey)或只在这次打开里有效的状态 */\nfunction settingRef<V>(key: string | undefined, name: string, initial: V): Ref<V> {\n return key ? usePersistentState(`${key}:${name}`, initial) : shallowRef(initial);\n}\n\n/** 查询表格:查询栏 + 工具栏 + 表格 + 分页,状态来自 useTableQuery */\nexport const QueryTable = _component(\n <T, Filters extends object>({\n query,\n columns,\n getKey,\n title,\n filters,\n moreFilters,\n blankFilters,\n fill = false,\n toolbar,\n persistKey,\n multiSort = false,\n selectionMode,\n _selected: selected = _bindable<string[]>([]),\n batchActions,\n propsFilterBar,\n propsPanel,\n propsToolbar,\n propsTable,\n propsSelectionBar,\n propsPagination,\n propsError,\n propsToolbarButton,\n ...rest\n }: QueryTableProps<T, Filters>) => {\n const messages = useMessages('patterns', patternsMessages);\n const lang = useLang();\n // 查询栏改的是草稿:点“查询”才交给 query\n // 用 cloneValue 不用 structuredClone:条件里的日期(CalendarDate)、Decimal 要保持原样\n const initial = cloneValue(_untrack(query.filters));\n const draft = reactive({ ...initial }) as Filters;\n const key = _untrack(persistKey);\n let hidden = _fromRef(settingRef<string[]>(key, 'hidden', []));\n let order = _fromRef(settingRef<string[]>(key, 'order', []));\n let pins = _fromRef(settingRef<Record<string, keyof ColumnStickies | null>>(key, 'pins', {}));\n let widths = _fromRef(settingRef<Record<string, number>>(key, 'widths', {}));\n let density = _fromRef(settingRef<keyof DataTableDensities>(key, 'density', 'standard'));\n let panel = _state.raw<HTMLElement | null>(null);\n const fullscreen = useFullscreen(() => panel);\n\n function search() {\n query.search(cloneValue(draft) as Filters);\n }\n\n function reset() {\n Object.assign(draft, cloneValue(blankFilters ?? initial));\n search();\n }\n\n const toolButton = (props: Partial<IconButtonProps>) =>\n mergePartProps<IconButtonProps>(\n { icon: RefreshCw, variant: 'ghost', tone: 'neutral', 'aria-label': '' },\n propsToolbarButton,\n props,\n );\n\n function renderTools() {\n return (\n <div {...css.attrs(queryTableStyles.tools)}>\n <IconButton\n {...toolButton({\n icon: RefreshCw,\n 'aria-label': messages.queryTableRefresh,\n loading: query.loading,\n onClick: () => void query.refresh(),\n })}\n />\n <Menu\n placement=\"bottom-end\"\n trigger={(props) => (\n <IconButton\n {...toolButton({ icon: Rows3, 'aria-label': messages.queryTableDensity })}\n {...props}\n />\n )}\n >\n <MenuRadioGroup\n _value={density}\n onUpdate:_value={(value: string) => (density = value as keyof DataTableDensities)}\n >\n <MenuRadioItem value=\"compact\">{messages.queryTableDensityCompact}</MenuRadioItem>\n <MenuRadioItem value=\"standard\">{messages.queryTableDensityStandard}</MenuRadioItem>\n <MenuRadioItem value=\"comfortable\">\n {messages.queryTableDensityComfortable}\n </MenuRadioItem>\n </MenuRadioGroup>\n </Menu>\n <ColumnSettings\n columns={columns}\n _hidden={hidden}\n _order={order}\n onReset={() => {\n pins = {};\n widths = {};\n }}\n propsTrigger={propsToolbarButton}\n />\n {fullscreen.supported && (\n <IconButton\n {...toolButton({\n icon: fullscreen.active ? Minimize : Maximize,\n 'aria-label': fullscreen.active\n ? messages.queryTableExitFullscreen\n : messages.queryTableFullscreen,\n 'aria-pressed': fullscreen.active,\n onClick: () => void fullscreen.toggle(),\n })}\n />\n )}\n </div>\n );\n }\n\n return () => {\n const root = renderRoot();\n return fill ? <ViewportFill>{root}</ViewportFill> : root;\n };\n\n function renderRoot() {\n return (\n <div\n {...mergeAttrs<'div'>(\n { sx: [queryTableStyles.root, fill && queryTableStyles.rootFill] },\n rest,\n )}\n >\n {filters && (\n <FilterBar\n {...mergePartProps<Partial<FilterBarProps>>(\n // 一页上可能有几个查询栏:各有名称,search 地标才分得清\n { 'aria-label': messages.queryTableSearch(title) },\n propsFilterBar,\n {\n onSearch: search,\n onReset: reset,\n loading: query.loading,\n more: moreFilters?.(draft),\n // 全屏时只有表格那一块(查询栏不在里面),工具栏要留在表格上方,所以不并进来\n start: fullscreen.active ? undefined : (\n <div {...css.attrs(queryTableStyles.titleInline)}>{title}</div>\n ),\n end: fullscreen.active ? undefined : (\n <div\n {...mergeAttrs<'div'>({ sx: queryTableStyles.toolbarInline }, propsToolbar)}\n >\n {toolbar}\n {renderTools()}\n </div>\n ),\n },\n )}\n >\n {filters(draft)}\n </FilterBar>\n )}\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n queryTableStyles.panel,\n fill && queryTableStyles.panelFill,\n fullscreen.active && queryTableStyles.panelFullscreen,\n ],\n },\n propsPanel,\n { ref: _toRef(panel) },\n )}\n >\n {(!filters || fullscreen.active) && (\n <div {...mergeAttrs<'div'>({ sx: queryTableStyles.toolbar }, propsToolbar)}>\n <div {...css.attrs(queryTableStyles.title)}>{title}</div>\n {toolbar}\n {renderTools()}\n </div>\n )}\n {selectionMode === 'multiple' && (\n <SelectionBar\n {...mergePartProps<SelectionBarProps>(\n { count: selected.length },\n propsSelectionBar,\n {\n count: selected.length,\n onClear: () => (selected = []),\n },\n )}\n >\n {batchActions?.(selected)}\n </SelectionBar>\n )}\n {/* 加载失败:按错误码说明原因(网络、权限、条件写错),保留上一次的行,给一个重试 */}\n {query.error !== undefined && (\n <Alert\n {...mergePartProps<Partial<AlertProps>>(\n {\n tone: 'danger',\n live: 'assertive',\n action: (\n <Button\n size=\"sm\"\n variant=\"outline\"\n tone=\"danger\"\n onClick={() => void query.refresh()}\n >\n {messages.queryTableRetry}\n </Button>\n ),\n },\n propsError,\n )}\n >\n {errorMessage(query.error, lang)}\n </Alert>\n )}\n <DataTable\n {...mergePartProps<Partial<DataTableProps<T>>>(\n { 'aria-label': title, flexible: fill || fullscreen.active },\n propsTable,\n )}\n rows={query.rows as T[]}\n columns={columns}\n getKey={getKey}\n manualSort\n multiSort={multiSort}\n _sort={query.sort}\n _sorts={query.sorts}\n manualFilter\n _filters={query.columnFilters}\n loading={query.loading}\n density={density}\n selectionMode={selectionMode}\n _selected={selected}\n _hiddenColumns={hidden}\n _columnOrder={order}\n _columnPins={pins}\n _columnWidths={widths}\n resizable\n columnMenu\n />\n <PaginationBar\n {...mergePartProps<Partial<PaginationBarProps>>(\n { propsPagination: { 'aria-label': messages.queryTablePagination(title) } },\n propsPagination,\n )}\n _page={query.page}\n _pageSize={query.pageSize}\n total={query.total}\n />\n </div>\n </div>\n );\n }\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"QueryTable.js","names":["_isVNode","_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vtp_untrack","_vue_shallowRef","_createVNode","Menu","_mergeProps"],"sources":["../../src/patterns/QueryTable.tsx"],"sourcesContent":["/**\n * 查询表格(列表页的整块):查询栏(FilterBar)+ 工具栏(标题、自己的按钮、刷新、行高、列设置、全屏)+ 批量操作栏 + 数据表格 + 分页栏。\n * 有查询栏时工具栏并进查询栏那一行,压成一行:标题 条件 查询 重置 展开 … 自己的按钮 刷新 行高 列设置 全屏;\n * 条件多时把不常用的放进 moreFilters,点“展开”后更多条件排在这一行下面。没有查询栏、或全屏(全屏的只有表格那一块)时,\n * 工具栏是表格上方单独的一行。fill 时整块占满到窗口底边(ViewportFill),行多了在表格里滚动,分页留在一屏里。\n * 状态都在 useTableQuery 里(服务端分页、排序、条件)。同 Ant Design ProComponents 的 ProTable。\n *\n * const tasks = useTableQuery(fetchTasks, { filters: { keyword: '', status: '' }, pageSize: 20 });\n * <QueryTable\n * query={tasks} columns={columns} getKey={(task) => task.id} title=\"任务台账\" persistKey=\"tasks\"\n * filters={(draft) => <Field label=\"关键字\"><TextField _value={draft.keyword} /></Field>}\n * toolbar={<Button icon={Plus}>新建</Button>}\n * />\n *\n * - 查询栏的条件改的是草稿(draft),点“查询”(或回车)才交给 query.search;“重置”回到 blankFilters(不写时是一开始的条件)并查询。\n * - 表头排序交给服务端(manualSort,写回 query.sort;multiSort 时按住 Shift 追加一列,写回 query.sorts),\n * 表头筛选也交给服务端(manualFilter,写回 query.columnFilters;列的 filter 要写 options,否则只列出当前这页出现过的值),\n * 分页栏绑定 query.page / pageSize / total。fetcher 用 tableParams(query, columns) 把这些写成接口的参数。\n * - persistKey:列设置(显示、顺序、固定、列宽)与行高记在浏览器里,下次打开还是这样。\n * - selectionMode 时勾选行,表格上方出现批量操作栏,batchActions 拿到已选的 key 给出按钮。\n *\n * 部件:Root(div)、FilterBar、Panel(工具栏与表格所在的区域,全屏的就是它)、Toolbar(div)、Title(div)、\n * Table(DataTable)、SelectionBar、Pagination(PaginationBar)。\n */\nimport { Maximize, Minimize, RefreshCw, Rows3 } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { reactive, shallowRef, type Ref, type VNodeChild } from 'vue';\nimport { Button } from '../base/Button';\nimport { IconButton, type IconButtonProps } from '../base/IconButton';\nimport { useLang } from '../config/context';\nimport { useMessages } from '../config/lang/messages';\nimport { Alert, type AlertProps } from '../feedback/Alert';\nimport { PaginationBar, type PaginationBarProps } from '../navigation/PaginationBar';\nimport { Menu, MenuRadioGroup, MenuRadioItem } from '../overlay/Menu';\nimport { ColumnSettings } from '../table/ColumnSettings';\nimport type { ColumnStickies, DataTableColumn } from '../table/columns';\nimport { ViewportFill } from '../layout/ViewportFill';\nimport { DataTable, type DataTableProps } from '../table/DataTable';\nimport { SelectionBar, type SelectionBarProps } from '../table/SelectionBar';\nimport type { DataTableDensities } from '../table/table-styles';\nimport type { TablePage, TableQueryState } from '../table/use-table-query';\nimport { cloneValue } from '../utils/data/clone';\nimport { useFullscreen } from '../utils/dom/fullscreen';\nimport { usePersistentState } from '../utils/dom/storage';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { errorMessage } from '../utils/request/error-message';\nimport { FilterBar, type FilterBarProps } from './FilterBar';\nimport { patternsMessages } from './messages';\n\n/** 未声明的属性落到外层 div 上 */\nexport interface QueryTableProps<T, Filters extends object> extends PartProps<'div'> {\n /** 列表状态:useTableQuery 的返回值 */\n query: TableQueryState<TablePage<T>, Filters>;\n /** 列定义 */\n columns: readonly DataTableColumn<T>[];\n /** 行的 key */\n getKey: (row: T, index: number) => string;\n /** 表格的名称(工具栏起始边的标题,也是表格的 aria-label) */\n title: string;\n /** 查询栏的条件:拿到草稿,控件绑定它的字段(`_value={draft.keyword}`);不写时没有查询栏 */\n filters?: (draft: Filters) => VNodeChild;\n /** 收起的条件(不常用的),点“展开”才显示 */\n moreFilters?: (draft: Filters) => VNodeChild;\n /** “重置”回到的条件;不写时是 query 一开始的条件 */\n blankFilters?: Filters;\n /** 占满到窗口底边(列表页的整页):行多了在表格里滚动,分页一直在一屏里 */\n fill?: boolean;\n /** 工具栏上自己的按钮(新建、导出),在标题之后、内置按钮之前 */\n toolbar?: VNodeChild;\n /** 列设置与行高记在浏览器里的键(localStorage,自动加前缀);不写时只在这次打开里有效 */\n persistKey?: string;\n /** 多列排序:按住 Shift 点列标题追加一列(同 DataTable 的 multiSort),排序写在 query.sorts */\n multiSort?: boolean;\n /** 勾选行:多选时表格上方出现批量操作栏 */\n selectionMode?: DataTableProps<T>['selectionMode'];\n /** 已选行的 key:父级写 _selected={keys} */\n _selected?: string[];\n /** 批量操作栏里的按钮:拿到已选的 key */\n batchActions?: (keys: readonly string[]) => VNodeChild;\n /** 查询栏(FilterBar)的部件属性 */\n propsFilterBar?: Partial<FilterBarProps>;\n /** 工具栏与表格所在区域的部件属性(全屏的就是它) */\n propsPanel?: PartProps<'div'>;\n /** 工具栏的部件属性 */\n propsToolbar?: PartProps<'div'>;\n /** 表格(DataTable)的部件属性:列宽、详情行、行的色调等直接写在这里 */\n propsTable?: Partial<DataTableProps<T>>;\n /** 批量操作栏的部件属性 */\n propsSelectionBar?: Partial<SelectionBarProps>;\n /** 分页栏的部件属性 */\n propsPagination?: Partial<PaginationBarProps>;\n /** 加载失败时表格上方的提示条(Alert)的部件属性 */\n propsError?: Partial<AlertProps>;\n /** 工具栏内置按钮(刷新、行高、全屏)的部件属性 */\n propsToolbarButton?: Partial<IconButtonProps>;\n}\n\n/** QueryTable 的样式:root、rootFill、panel、panelFullscreen、panelFill、toolbar、title、tools、titleInline、toolbarInline */\nexport const queryTableStyles = css.create({\n root: { display: 'flex', flexDirection: 'column', gap: '_md', minWidth: 0 },\n panel: {\n display: 'flex',\n flexDirection: 'column',\n gap: '_sm',\n minWidth: 0,\n backgroundColor: '_surface',\n },\n // 全屏时铺满屏幕、四周留白,表格占满剩下的高度\n panelFullscreen: { padding: '_lg', overflow: 'auto' },\n // fill 时外面的高度定了,整块与区域可以压矮,压不下的在表格里滚动\n rootFill: { flexGrow: 1, minHeight: 0 },\n panelFill: { minHeight: 0 },\n toolbar: { display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: '_sm' },\n title: { flexGrow: 1, minWidth: 0, fontWeight: '_semibold', fontSize: '_lg' },\n tools: { display: 'flex', alignItems: 'center', gap: '_xs' },\n // 并进查询栏那一行时:标题不撑开,按钮靠在一起\n titleInline: { flexShrink: 0, fontWeight: '_semibold', fontSize: '_lg' },\n toolbarInline: { display: 'flex', alignItems: 'center', gap: '_sm' },\n});\n\n/** 存在浏览器里(给了 persistKey)或只在这次打开里有效的状态 */\nfunction settingRef<V>(key: string | undefined, name: string, initial: V): Ref<V> {\n return key ? usePersistentState(`${key}:${name}`, initial) : shallowRef(initial);\n}\n\n/** 查询表格:查询栏 + 工具栏 + 表格 + 分页,状态来自 useTableQuery */\nexport const QueryTable = _component(\n <T, Filters extends object>({\n query,\n columns,\n getKey,\n title,\n filters,\n moreFilters,\n blankFilters,\n fill = false,\n toolbar,\n persistKey,\n multiSort = false,\n selectionMode,\n _selected: selected = _bindable<string[]>([]),\n batchActions,\n propsFilterBar,\n propsPanel,\n propsToolbar,\n propsTable,\n propsSelectionBar,\n propsPagination,\n propsError,\n propsToolbarButton,\n ...rest\n }: QueryTableProps<T, Filters>) => {\n const messages = useMessages('patterns', patternsMessages);\n const lang = useLang();\n // 查询栏改的是草稿:点“查询”才交给 query\n // 用 cloneValue 不用 structuredClone:条件里的日期(CalendarDate)、Decimal 要保持原样\n const initial = cloneValue(_untrack(query.filters));\n const draft = reactive({ ...initial }) as Filters;\n const key = _untrack(persistKey);\n let hidden = _fromRef(settingRef<string[]>(key, 'hidden', []));\n let order = _fromRef(settingRef<string[]>(key, 'order', []));\n let pins = _fromRef(settingRef<Record<string, keyof ColumnStickies | null>>(key, 'pins', {}));\n let widths = _fromRef(settingRef<Record<string, number>>(key, 'widths', {}));\n let density = _fromRef(settingRef<keyof DataTableDensities>(key, 'density', 'standard'));\n let panel = _state.raw<HTMLElement | null>(null);\n const fullscreen = useFullscreen(() => panel);\n\n function search() {\n query.search(cloneValue(draft) as Filters);\n }\n\n function reset() {\n Object.assign(draft, cloneValue(blankFilters ?? initial));\n search();\n }\n\n const toolButton = (props: Partial<IconButtonProps>) =>\n mergePartProps<IconButtonProps>(\n { icon: RefreshCw, variant: 'ghost', tone: 'neutral', 'aria-label': '' },\n propsToolbarButton,\n props,\n );\n\n function renderTools() {\n return (\n <div {...css.attrs(queryTableStyles.tools)}>\n <IconButton\n {...toolButton({\n icon: RefreshCw,\n 'aria-label': messages.queryTableRefresh,\n loading: query.loading,\n onClick: () => void query.refresh(),\n })}\n />\n <Menu\n placement=\"bottom-end\"\n trigger={(props) => (\n <IconButton\n {...toolButton({ icon: Rows3, 'aria-label': messages.queryTableDensity })}\n {...props}\n />\n )}\n >\n <MenuRadioGroup\n _value={density}\n onUpdate:_value={(value: string) => (density = value as keyof DataTableDensities)}\n >\n <MenuRadioItem value=\"compact\">{messages.queryTableDensityCompact}</MenuRadioItem>\n <MenuRadioItem value=\"standard\">{messages.queryTableDensityStandard}</MenuRadioItem>\n <MenuRadioItem value=\"comfortable\">\n {messages.queryTableDensityComfortable}\n </MenuRadioItem>\n </MenuRadioGroup>\n </Menu>\n <ColumnSettings\n columns={columns}\n _hidden={hidden}\n _order={order}\n onReset={() => {\n pins = {};\n widths = {};\n }}\n propsTrigger={propsToolbarButton}\n />\n {fullscreen.supported && (\n <IconButton\n {...toolButton({\n icon: fullscreen.active ? Minimize : Maximize,\n 'aria-label': fullscreen.active\n ? messages.queryTableExitFullscreen\n : messages.queryTableFullscreen,\n 'aria-pressed': fullscreen.active,\n onClick: () => void fullscreen.toggle(),\n })}\n />\n )}\n </div>\n );\n }\n\n return () => {\n const root = renderRoot();\n return fill ? <ViewportFill>{root}</ViewportFill> : root;\n };\n\n function renderRoot() {\n return (\n <div\n {...mergeAttrs<'div'>(\n { sx: [queryTableStyles.root, fill && queryTableStyles.rootFill] },\n rest,\n )}\n >\n {filters && (\n <FilterBar\n {...mergePartProps<Partial<FilterBarProps>>(\n // 一页上可能有几个查询栏:各有名称,search 地标才分得清\n { 'aria-label': messages.queryTableSearch(title) },\n propsFilterBar,\n {\n onSearch: search,\n onReset: reset,\n loading: query.loading,\n more: moreFilters?.(draft),\n // 全屏时只有表格那一块(查询栏不在里面),工具栏要留在表格上方,所以不并进来\n start: fullscreen.active ? undefined : (\n <div {...css.attrs(queryTableStyles.titleInline)}>{title}</div>\n ),\n end: fullscreen.active ? undefined : (\n <div\n {...mergeAttrs<'div'>({ sx: queryTableStyles.toolbarInline }, propsToolbar)}\n >\n {toolbar}\n {renderTools()}\n </div>\n ),\n },\n )}\n >\n {filters(draft)}\n </FilterBar>\n )}\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n queryTableStyles.panel,\n fill && queryTableStyles.panelFill,\n fullscreen.active && queryTableStyles.panelFullscreen,\n ],\n },\n propsPanel,\n { ref: _toRef(panel) },\n )}\n >\n {(!filters || fullscreen.active) && (\n <div {...mergeAttrs<'div'>({ sx: queryTableStyles.toolbar }, propsToolbar)}>\n <div {...css.attrs(queryTableStyles.title)}>{title}</div>\n {toolbar}\n {renderTools()}\n </div>\n )}\n {selectionMode === 'multiple' && (\n <SelectionBar\n {...mergePartProps<SelectionBarProps>(\n { count: selected.length },\n propsSelectionBar,\n {\n count: selected.length,\n onClear: () => (selected = []),\n },\n )}\n >\n {batchActions?.(selected)}\n </SelectionBar>\n )}\n {/* 加载失败:按错误码说明原因(网络、权限、条件写错),保留上一次的行,给一个重试 */}\n {query.error !== undefined && (\n <Alert\n {...mergePartProps<Partial<AlertProps>>(\n {\n tone: 'danger',\n live: 'assertive',\n action: (\n <Button\n size=\"sm\"\n variant=\"outline\"\n tone=\"danger\"\n onClick={() => void query.refresh()}\n >\n {messages.queryTableRetry}\n </Button>\n ),\n },\n propsError,\n )}\n >\n {errorMessage(query.error, lang)}\n </Alert>\n )}\n <DataTable\n {...mergePartProps<Partial<DataTableProps<T>>>(\n { 'aria-label': title, flexible: fill || fullscreen.active },\n propsTable,\n )}\n rows={query.rows as T[]}\n columns={columns}\n getKey={getKey}\n manualSort\n multiSort={multiSort}\n _sort={query.sort}\n _sorts={query.sorts}\n manualFilter\n _filters={query.columnFilters}\n loading={query.loading}\n density={density}\n selectionMode={selectionMode}\n _selected={selected}\n _hiddenColumns={hidden}\n _columnOrder={order}\n _columnPins={pins}\n _columnWidths={widths}\n resizable\n columnMenu\n />\n <PaginationBar\n {...mergePartProps<Partial<PaginationBarProps>>(\n { propsPagination: { 'aria-label': messages.queryTablePagination(title) } },\n propsPagination,\n )}\n _page={query.page}\n _pageSize={query.pageSize}\n total={query.total}\n />\n </div>\n </div>\n );\n }\n },\n);\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';
1
+ import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
2
2
  import { type PartProps } from '../utils/props';
3
3
  /** 服务端给的一张拼图 */
4
4
  export interface SlideChallenge {
@@ -7,7 +7,7 @@ import { useMessages } from "../config/lang/messages.js";
7
7
  import { patternsMessages } from "./messages.js";
8
8
  import { Fragment, createVNode, ref, shallowRef, watch } from "vue";
9
9
  import { _component, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
10
- import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
10
+ import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
11
11
  import { Check, ChevronsRight, RefreshCw, X } from "@lucide/icons";
12
12
  //#region src/patterns/SlideCaptcha.tsx
13
13
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"SlideCaptcha.js","names":["_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_vue_ref","_createVNode","_mergeProps","_Fragment"],"sources":["../../src/patterns/SlideCaptcha.tsx"],"sourcesContent":["/**\n * 拼图滑块验证:画面是服务端生成的背景图(有一个缺口)和一块拼图,拖动下面的滑块让拼图对准缺口,松手后把位置和拖动轨迹\n * 交给服务端判定。组件只负责交互,不判对错:答案在服务端,每次给一张新图。\n *\n * <SlideCaptcha\n * challenge={challenge} // 服务端给的图;还没拿到时为 null\n * status={status} // idle / verifying / success / error,由父级按判定结果设置\n * onRelease={(result) => verify(challenge.id, result)}\n * onRefresh={loadChallenge}\n * />\n *\n * - `challenge`:background、piece 是图片地址(data URL 或普通地址),width、height 是背景图的像素尺寸,pieceWidth 是拼图图片的宽度;\n * 拼图图片和背景一样高,左边缘就是缺口的左边缘,所以位置换算成像素直接就是答案。\n * - `onRelease` 交出 { x, track, duration }:x 是拼图左边缘在背景图里的像素位置,track 是(毫秒,位置)序列,\n * 真人拖动有加减速和抖动,服务端据此区分脚本。\n * - `status` 由父级控制:verifying 时不能拖,success 时锁定,error 时滑块晃一下;父级换了新的 challenge 或设回 idle 时滑块回到起点。\n * - 键盘:聚焦滑块后 ←/→ 微调、Home/End、Enter 或空格松手。这类验证对读屏和运动障碍的用户不友好,应用应当另外提供别的方式。\n */\nimport { Check, ChevronsRight, RefreshCw, X } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { watch } from 'vue';\nimport { Icon } from '../base/Icon';\nimport { IconButton } from '../base/IconButton';\nimport { Spinner } from '../base/Spinner';\nimport { VisuallyHidden } from '../base/VisuallyHidden';\nimport { useMessages } from '../config/lang/messages';\nimport { mergeAttrs, type PartProps } from '../utils/props';\nimport { patternsMessages } from './messages';\n\n/** 服务端给的一张拼图 */\nexport interface SlideChallenge {\n /** 这一张的标识,换图时变;松手后连同结果一起交给服务端 */\n id: string;\n /** 背景图(带缺口) */\n background: string;\n /** 拼图图片:和背景一样高,左边缘对着缺口的左边缘 */\n piece: string;\n /** 背景图的宽(px) */\n width: number;\n /** 背景图的高(px) */\n height: number;\n /** 拼图图片的宽度(px) */\n pieceWidth: number;\n}\n\n/** 松手时交给服务端的内容 */\nexport interface SlideResult {\n /** 拼图左边缘在背景图里的位置(px,整数) */\n x: number;\n /** 拖动轨迹:距按下的毫秒数,和当时的位置(px) */\n track: { t: number; x: number }[];\n /** 从按下到松手的毫秒数 */\n duration: number;\n}\n\n/** 验证码的状态:idle 可以拖,verifying 等服务端判定,success 通过,error 没对准 */\nexport type SlideStatus = 'idle' | 'verifying' | 'success' | 'error';\n\n/** 未声明的属性落到外层 div 上 */\nexport interface SlideCaptchaProps extends PartProps<'div'> {\n /** 当前的拼图;还没拿到时为 null,显示加载中 */\n challenge: SlideChallenge | null;\n /** 状态,默认 idle */\n status?: SlideStatus;\n /** 滑块条上的提示,默认“向右拖动滑块,让拼图对准缺口” */\n hint?: string;\n /** 没对准时的提示(图片底部和滑块条上),默认“没对准,请再试一次”;服务端给了具体原因时用它 */\n errorText?: string;\n /** 松手:把结果发给服务端判定 */\n onRelease?: (result: SlideResult) => void;\n /** 点了“换一张” */\n onRefresh?: () => void;\n}\n\n/** 键盘每次移动的距离(px) */\nconst KEY_STEP = 2;\n/** 轨迹最多记多少个点,太长的拖动只留一部分 */\nconst MAX_POINTS = 240;\n/** 滑块的宽度,也是滑块条的高度 */\nconst HANDLE = '2.75rem';\n/** 松手回到起点时的过渡:带一点回弹 */\nconst SETTLE = '0.28s cubic-bezier(0.34, 1.4, 0.64, 1)';\n\n/** SlideCaptcha 的样式:root、picture、image、piece、banner、track、fill、handle 等 */\nexport const slideCaptchaStyles = css.create({\n root: {\n display: 'flex',\n flexDirection: 'column',\n gap: '_sm',\n width: '_full',\n userSelect: 'none',\n },\n picture: {\n position: 'relative',\n boxSizing: 'border-box',\n width: '_full',\n overflow: 'hidden',\n borderRadius: '_md',\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_border',\n backgroundColor: '_fill',\n },\n image: {\n display: 'block',\n width: '_full',\n height: '_full',\n objectFit: 'cover',\n pointerEvents: 'none',\n userSelect: 'none',\n },\n piece: {\n position: 'absolute',\n top: 0,\n height: '_full',\n pointerEvents: 'none',\n filter: 'drop-shadow(0 2px 6px rgb(0 0 0 / 0.45))',\n },\n pieceSettle: { transition: `left ${SETTLE}` },\n refresh: { position: 'absolute', top: '_xs', insetInlineEnd: '_xs' },\n // 盖在图上的结果条:底色固定为深色半透明,白字在任何背景图上都读得清\n banner: {\n position: 'absolute',\n insetInline: 0,\n bottom: 0,\n paddingBlock: '_xs',\n paddingInline: '_md',\n fontSize: '_sm',\n textAlign: 'center',\n color: 'white',\n },\n bannerSuccess: { backgroundColor: 'rgb(22 163 74 / 0.88)' },\n bannerError: { backgroundColor: 'rgb(220 38 38 / 0.88)' },\n loading: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '_sm',\n height: '_full',\n color: '_textMuted',\n fontSize: '_sm',\n },\n track: {\n position: 'relative',\n boxSizing: 'border-box',\n height: HANDLE,\n overflow: 'hidden',\n borderRadius: '_md',\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_border',\n backgroundColor: '_fill',\n },\n fill: {\n position: 'absolute',\n insetBlock: 0,\n insetInlineStart: 0,\n backgroundColor: '_accentSoft',\n },\n fillSuccess: { backgroundColor: '_successSoft' },\n fillError: { backgroundColor: '_dangerSoft' },\n hint: {\n position: 'absolute',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n paddingInline: HANDLE,\n color: '_textMuted',\n fontSize: '_sm',\n pointerEvents: 'none',\n },\n handle: {\n position: 'absolute',\n insetBlock: 0,\n boxSizing: 'border-box',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: HANDLE,\n borderRadius: '_md',\n backgroundColor: '_surface',\n boxShadow: '_sm',\n color: '_accentText',\n cursor: 'grab',\n touchAction: 'none',\n outlineOffset: '-2px',\n },\n handleActive: { cursor: 'grabbing', boxShadow: '_md' },\n handleSuccess: { color: '_successText' },\n handleError: { color: '_dangerText' },\n locked: { cursor: 'default' },\n // 松手后回到起点、或键盘微调时有过渡;拖动中跟手,不加过渡\n settle: { transition: `left ${SETTLE}, width ${SETTLE}` },\n});\n\n/** SlideCaptcha 的动态样式:位置用百分比,画面和滑块条按容器宽度缩放 */\nexport const slideCaptchaDynamicStyles = css.create({\n at: (percent: number) => ({ left: `${percent}%` }),\n pieceWidth: (percent: number) => ({ width: `${percent}%` }),\n ratio: (aspect: number) => ({ aspectRatio: String(aspect) }),\n // 滑块在条里的位置:条宽减去滑块宽的部分按比例走\n handleAt: (position: number) => ({ left: `calc(${position} * (100% - ${HANDLE}))` }),\n fillTo: (position: number) => ({ width: `calc(${position} * (100% - ${HANDLE}) + ${HANDLE})` }),\n});\n\nconst clamp01 = (value: number) => Math.min(1, Math.max(0, value));\n\n/** 拼图滑块验证:拖动滑块让拼图对准缺口,松手把位置与轨迹交给服务端判定 */\nexport const SlideCaptcha = _component(\n ({\n challenge,\n status = 'idle',\n hint,\n errorText,\n onRelease,\n onRefresh,\n ...rest\n }: SlideCaptchaProps) => {\n const messages = useMessages('patterns', patternsMessages);\n let trackElement = _state.raw<HTMLElement | null>(null);\n let handleElement = _state.raw<HTMLElement | null>(null);\n // 拼图左边缘的位置占“可移动距离”的比例(0 到 1)\n let position = _state(0);\n let dragging = _state(false);\n let track: SlideResult['track'] = [];\n let startedAt = 0;\n\n const travel = () => (challenge ? challenge.width - challenge.pieceWidth : 0);\n const pixels = () => Math.round(position * travel());\n const interactive = () => challenge !== null && status === 'idle';\n\n function record() {\n if (!track.length) startedAt = performance.now();\n if (track.length < MAX_POINTS) {\n track.push({ t: Math.round(performance.now() - startedAt), x: pixels() });\n }\n }\n\n function release() {\n if (!track.length) return;\n const result: SlideResult = {\n x: pixels(),\n track,\n duration: Math.round(performance.now() - startedAt),\n };\n track = [];\n onRelease?.(result);\n }\n\n function grab(event: PointerEvent) {\n if (!interactive() || !trackElement || !handleElement) return;\n event.preventDefault();\n handleElement.focus();\n handleElement.setPointerCapture(event.pointerId);\n const room = trackElement.clientWidth - handleElement.offsetWidth;\n const startX = event.clientX;\n const startPosition = position;\n track = [];\n record();\n dragging = true;\n const move = (next: PointerEvent) => {\n position = clamp01(startPosition + (next.clientX - startX) / Math.max(room, 1));\n record();\n };\n const end = (next: PointerEvent) => {\n handleElement?.removeEventListener('pointermove', move);\n handleElement?.removeEventListener('pointerup', end);\n handleElement?.removeEventListener('pointercancel', end);\n handleElement?.releasePointerCapture(next.pointerId);\n dragging = false;\n if (next.type === 'pointercancel') {\n position = 0;\n track = [];\n } else {\n release();\n }\n };\n handleElement.addEventListener('pointermove', move);\n handleElement.addEventListener('pointerup', end);\n handleElement.addEventListener('pointercancel', end);\n }\n\n function onKeydown(event: KeyboardEvent) {\n if (!interactive()) return;\n const step = KEY_STEP / Math.max(travel(), 1);\n const isRtl = !!trackElement && getComputedStyle(trackElement).direction === 'rtl';\n const forward = isRtl ? 'ArrowLeft' : 'ArrowRight';\n const backward = isRtl ? 'ArrowRight' : 'ArrowLeft';\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n release();\n return;\n }\n const next =\n event.key === forward\n ? clamp01(position + step)\n : event.key === backward\n ? clamp01(position - step)\n : event.key === 'Home'\n ? 0\n : event.key === 'End'\n ? 1\n : null;\n if (next === null) return;\n event.preventDefault();\n position = next;\n record();\n }\n\n // 换了新图、或父级设回 idle(重试):滑块回到起点;没对准时滑块晃一下\n watch(\n () => challenge?.id,\n () => {\n position = 0;\n track = [];\n },\n );\n watch(\n () => status,\n (next, previous) => {\n if (next === 'idle' && previous !== 'idle') {\n position = 0;\n track = [];\n }\n if (\n next === 'error' &&\n handleElement &&\n !matchMedia('(prefers-reduced-motion: reduce)').matches\n ) {\n handleElement.animate(\n [\n { translate: '0' },\n { translate: '-6px' },\n { translate: '6px' },\n { translate: '-4px' },\n { translate: '4px' },\n { translate: '0' },\n ],\n { duration: 360 },\n );\n }\n },\n );\n\n return () => {\n const locked = !interactive();\n const settling = !dragging;\n const text =\n status === 'verifying'\n ? messages.slideVerifying\n : status === 'success'\n ? messages.slideSuccess\n : status === 'error'\n ? (errorText ?? messages.slideError)\n : (hint ?? messages.slideHint);\n const icon = status === 'success' ? Check : status === 'error' ? X : ChevronsRight;\n const piecePercent = challenge ? ((position * travel()) / challenge.width) * 100 : 0;\n const pieceWidthPercent = challenge ? (challenge.pieceWidth / challenge.width) * 100 : 0;\n const aspect = challenge ? challenge.width / challenge.height : 2;\n return (\n <div\n {...mergeAttrs<'div'>({ sx: slideCaptchaStyles.root }, rest)}\n aria-busy={status === 'verifying' || undefined}\n >\n <div\n {...mergeAttrs<'div'>({\n sx: [slideCaptchaStyles.picture, slideCaptchaDynamicStyles.ratio(aspect)],\n })}\n >\n {challenge ? (\n <>\n <img\n {...mergeAttrs<'img'>({ sx: slideCaptchaStyles.image })}\n src={challenge.background}\n alt=\"\"\n draggable={false}\n />\n <img\n {...mergeAttrs<'img'>({\n sx: [\n slideCaptchaStyles.piece,\n slideCaptchaDynamicStyles.pieceWidth(pieceWidthPercent),\n slideCaptchaDynamicStyles.at(piecePercent),\n settling && slideCaptchaStyles.pieceSettle,\n ],\n })}\n src={challenge.piece}\n alt=\"\"\n draggable={false}\n />\n </>\n ) : (\n <div {...mergeAttrs<'div'>({ sx: slideCaptchaStyles.loading })}>\n <Spinner />\n {messages.slideLoading}\n </div>\n )}\n <IconButton\n sx={slideCaptchaStyles.refresh}\n icon={RefreshCw}\n size=\"sm\"\n variant=\"ghost\"\n tone=\"neutral\"\n aria-label={messages.slideRefresh}\n disabled={status === 'verifying'}\n onClick={() => onRefresh?.()}\n />\n {(status === 'success' || status === 'error') && (\n <div\n {...mergeAttrs<'div'>({\n sx: [\n slideCaptchaStyles.banner,\n status === 'success'\n ? slideCaptchaStyles.bannerSuccess\n : slideCaptchaStyles.bannerError,\n ],\n })}\n >\n {text}\n </div>\n )}\n </div>\n <div\n {...mergeAttrs<'div'>({ sx: slideCaptchaStyles.track }, undefined, {\n ref: _toRef(trackElement),\n })}\n >\n <div\n {...mergeAttrs<'div'>({\n sx: [\n slideCaptchaStyles.fill,\n status === 'success' && slideCaptchaStyles.fillSuccess,\n status === 'error' && slideCaptchaStyles.fillError,\n settling && slideCaptchaStyles.settle,\n slideCaptchaDynamicStyles.fillTo(position),\n ],\n })}\n />\n <span {...mergeAttrs<'span'>({ sx: slideCaptchaStyles.hint })} aria-hidden=\"true\">\n {position === 0 || status !== 'idle' ? text : null}\n </span>\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n slideCaptchaStyles.handle,\n dragging && slideCaptchaStyles.handleActive,\n status === 'success' && slideCaptchaStyles.handleSuccess,\n status === 'error' && slideCaptchaStyles.handleError,\n locked && slideCaptchaStyles.locked,\n settling && slideCaptchaStyles.settle,\n slideCaptchaDynamicStyles.handleAt(position),\n ],\n },\n undefined,\n { ref: _toRef(handleElement) },\n )}\n role=\"slider\"\n aria-label={messages.slideLabel}\n aria-valuemin={0}\n aria-valuemax={travel()}\n aria-valuenow={pixels()}\n aria-valuetext={messages.slidePosition(pixels())}\n aria-disabled={locked || undefined}\n tabindex={locked ? -1 : 0}\n onPointerdown={grab}\n onKeydown={onKeydown}\n >\n <Icon icon={icon} />\n </div>\n </div>\n <VisuallyHidden aria-live=\"polite\">{status === 'idle' ? '' : text}</VisuallyHidden>\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"SlideCaptcha.js","names":["_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_vue_ref","_createVNode","_mergeProps","_Fragment"],"sources":["../../src/patterns/SlideCaptcha.tsx"],"sourcesContent":["/**\n * 拼图滑块验证:画面是服务端生成的背景图(有一个缺口)和一块拼图,拖动下面的滑块让拼图对准缺口,松手后把位置和拖动轨迹\n * 交给服务端判定。组件只负责交互,不判对错:答案在服务端,每次给一张新图。\n *\n * <SlideCaptcha\n * challenge={challenge} // 服务端给的图;还没拿到时为 null\n * status={status} // idle / verifying / success / error,由父级按判定结果设置\n * onRelease={(result) => verify(challenge.id, result)}\n * onRefresh={loadChallenge}\n * />\n *\n * - `challenge`:background、piece 是图片地址(data URL 或普通地址),width、height 是背景图的像素尺寸,pieceWidth 是拼图图片的宽度;\n * 拼图图片和背景一样高,左边缘就是缺口的左边缘,所以位置换算成像素直接就是答案。\n * - `onRelease` 交出 { x, track, duration }:x 是拼图左边缘在背景图里的像素位置,track 是(毫秒,位置)序列,\n * 真人拖动有加减速和抖动,服务端据此区分脚本。\n * - `status` 由父级控制:verifying 时不能拖,success 时锁定,error 时滑块晃一下;父级换了新的 challenge 或设回 idle 时滑块回到起点。\n * - 键盘:聚焦滑块后 ←/→ 微调、Home/End、Enter 或空格松手。这类验证对读屏和运动障碍的用户不友好,应用应当另外提供别的方式。\n */\nimport { Check, ChevronsRight, RefreshCw, X } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { watch } from 'vue';\nimport { Icon } from '../base/Icon';\nimport { IconButton } from '../base/IconButton';\nimport { Spinner } from '../base/Spinner';\nimport { VisuallyHidden } from '../base/VisuallyHidden';\nimport { useMessages } from '../config/lang/messages';\nimport { mergeAttrs, type PartProps } from '../utils/props';\nimport { patternsMessages } from './messages';\n\n/** 服务端给的一张拼图 */\nexport interface SlideChallenge {\n /** 这一张的标识,换图时变;松手后连同结果一起交给服务端 */\n id: string;\n /** 背景图(带缺口) */\n background: string;\n /** 拼图图片:和背景一样高,左边缘对着缺口的左边缘 */\n piece: string;\n /** 背景图的宽(px) */\n width: number;\n /** 背景图的高(px) */\n height: number;\n /** 拼图图片的宽度(px) */\n pieceWidth: number;\n}\n\n/** 松手时交给服务端的内容 */\nexport interface SlideResult {\n /** 拼图左边缘在背景图里的位置(px,整数) */\n x: number;\n /** 拖动轨迹:距按下的毫秒数,和当时的位置(px) */\n track: { t: number; x: number }[];\n /** 从按下到松手的毫秒数 */\n duration: number;\n}\n\n/** 验证码的状态:idle 可以拖,verifying 等服务端判定,success 通过,error 没对准 */\nexport type SlideStatus = 'idle' | 'verifying' | 'success' | 'error';\n\n/** 未声明的属性落到外层 div 上 */\nexport interface SlideCaptchaProps extends PartProps<'div'> {\n /** 当前的拼图;还没拿到时为 null,显示加载中 */\n challenge: SlideChallenge | null;\n /** 状态,默认 idle */\n status?: SlideStatus;\n /** 滑块条上的提示,默认“向右拖动滑块,让拼图对准缺口” */\n hint?: string;\n /** 没对准时的提示(图片底部和滑块条上),默认“没对准,请再试一次”;服务端给了具体原因时用它 */\n errorText?: string;\n /** 松手:把结果发给服务端判定 */\n onRelease?: (result: SlideResult) => void;\n /** 点了“换一张” */\n onRefresh?: () => void;\n}\n\n/** 键盘每次移动的距离(px) */\nconst KEY_STEP = 2;\n/** 轨迹最多记多少个点,太长的拖动只留一部分 */\nconst MAX_POINTS = 240;\n/** 滑块的宽度,也是滑块条的高度 */\nconst HANDLE = '2.75rem';\n/** 松手回到起点时的过渡:带一点回弹 */\nconst SETTLE = '0.28s cubic-bezier(0.34, 1.4, 0.64, 1)';\n\n/** SlideCaptcha 的样式:root、picture、image、piece、banner、track、fill、handle 等 */\nexport const slideCaptchaStyles = css.create({\n root: {\n display: 'flex',\n flexDirection: 'column',\n gap: '_sm',\n width: '_full',\n userSelect: 'none',\n },\n picture: {\n position: 'relative',\n boxSizing: 'border-box',\n width: '_full',\n overflow: 'hidden',\n borderRadius: '_md',\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_border',\n backgroundColor: '_fill',\n },\n image: {\n display: 'block',\n width: '_full',\n height: '_full',\n objectFit: 'cover',\n pointerEvents: 'none',\n userSelect: 'none',\n },\n piece: {\n position: 'absolute',\n top: 0,\n height: '_full',\n pointerEvents: 'none',\n filter: 'drop-shadow(0 2px 6px rgb(0 0 0 / 0.45))',\n },\n pieceSettle: { transition: `left ${SETTLE}` },\n refresh: { position: 'absolute', top: '_xs', insetInlineEnd: '_xs' },\n // 盖在图上的结果条:底色固定为深色半透明,白字在任何背景图上都读得清\n banner: {\n position: 'absolute',\n insetInline: 0,\n bottom: 0,\n paddingBlock: '_xs',\n paddingInline: '_md',\n fontSize: '_sm',\n textAlign: 'center',\n color: 'white',\n },\n bannerSuccess: { backgroundColor: 'rgb(22 163 74 / 0.88)' },\n bannerError: { backgroundColor: 'rgb(220 38 38 / 0.88)' },\n loading: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '_sm',\n height: '_full',\n color: '_textMuted',\n fontSize: '_sm',\n },\n track: {\n position: 'relative',\n boxSizing: 'border-box',\n height: HANDLE,\n overflow: 'hidden',\n borderRadius: '_md',\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_border',\n backgroundColor: '_fill',\n },\n fill: {\n position: 'absolute',\n insetBlock: 0,\n insetInlineStart: 0,\n backgroundColor: '_accentSoft',\n },\n fillSuccess: { backgroundColor: '_successSoft' },\n fillError: { backgroundColor: '_dangerSoft' },\n hint: {\n position: 'absolute',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n paddingInline: HANDLE,\n color: '_textMuted',\n fontSize: '_sm',\n pointerEvents: 'none',\n },\n handle: {\n position: 'absolute',\n insetBlock: 0,\n boxSizing: 'border-box',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: HANDLE,\n borderRadius: '_md',\n backgroundColor: '_surface',\n boxShadow: '_sm',\n color: '_accentText',\n cursor: 'grab',\n touchAction: 'none',\n outlineOffset: '-2px',\n },\n handleActive: { cursor: 'grabbing', boxShadow: '_md' },\n handleSuccess: { color: '_successText' },\n handleError: { color: '_dangerText' },\n locked: { cursor: 'default' },\n // 松手后回到起点、或键盘微调时有过渡;拖动中跟手,不加过渡\n settle: { transition: `left ${SETTLE}, width ${SETTLE}` },\n});\n\n/** SlideCaptcha 的动态样式:位置用百分比,画面和滑块条按容器宽度缩放 */\nexport const slideCaptchaDynamicStyles = css.create({\n at: (percent: number) => ({ left: `${percent}%` }),\n pieceWidth: (percent: number) => ({ width: `${percent}%` }),\n ratio: (aspect: number) => ({ aspectRatio: String(aspect) }),\n // 滑块在条里的位置:条宽减去滑块宽的部分按比例走\n handleAt: (position: number) => ({ left: `calc(${position} * (100% - ${HANDLE}))` }),\n fillTo: (position: number) => ({ width: `calc(${position} * (100% - ${HANDLE}) + ${HANDLE})` }),\n});\n\nconst clamp01 = (value: number) => Math.min(1, Math.max(0, value));\n\n/** 拼图滑块验证:拖动滑块让拼图对准缺口,松手把位置与轨迹交给服务端判定 */\nexport const SlideCaptcha = _component(\n ({\n challenge,\n status = 'idle',\n hint,\n errorText,\n onRelease,\n onRefresh,\n ...rest\n }: SlideCaptchaProps) => {\n const messages = useMessages('patterns', patternsMessages);\n let trackElement = _state.raw<HTMLElement | null>(null);\n let handleElement = _state.raw<HTMLElement | null>(null);\n // 拼图左边缘的位置占“可移动距离”的比例(0 到 1)\n let position = _state(0);\n let dragging = _state(false);\n let track: SlideResult['track'] = [];\n let startedAt = 0;\n\n const travel = () => (challenge ? challenge.width - challenge.pieceWidth : 0);\n const pixels = () => Math.round(position * travel());\n const interactive = () => challenge !== null && status === 'idle';\n\n function record() {\n if (!track.length) startedAt = performance.now();\n if (track.length < MAX_POINTS) {\n track.push({ t: Math.round(performance.now() - startedAt), x: pixels() });\n }\n }\n\n function release() {\n if (!track.length) return;\n const result: SlideResult = {\n x: pixels(),\n track,\n duration: Math.round(performance.now() - startedAt),\n };\n track = [];\n onRelease?.(result);\n }\n\n function grab(event: PointerEvent) {\n if (!interactive() || !trackElement || !handleElement) return;\n event.preventDefault();\n handleElement.focus();\n handleElement.setPointerCapture(event.pointerId);\n const room = trackElement.clientWidth - handleElement.offsetWidth;\n const startX = event.clientX;\n const startPosition = position;\n track = [];\n record();\n dragging = true;\n const move = (next: PointerEvent) => {\n position = clamp01(startPosition + (next.clientX - startX) / Math.max(room, 1));\n record();\n };\n const end = (next: PointerEvent) => {\n handleElement?.removeEventListener('pointermove', move);\n handleElement?.removeEventListener('pointerup', end);\n handleElement?.removeEventListener('pointercancel', end);\n handleElement?.releasePointerCapture(next.pointerId);\n dragging = false;\n if (next.type === 'pointercancel') {\n position = 0;\n track = [];\n } else {\n release();\n }\n };\n handleElement.addEventListener('pointermove', move);\n handleElement.addEventListener('pointerup', end);\n handleElement.addEventListener('pointercancel', end);\n }\n\n function onKeydown(event: KeyboardEvent) {\n if (!interactive()) return;\n const step = KEY_STEP / Math.max(travel(), 1);\n const isRtl = !!trackElement && getComputedStyle(trackElement).direction === 'rtl';\n const forward = isRtl ? 'ArrowLeft' : 'ArrowRight';\n const backward = isRtl ? 'ArrowRight' : 'ArrowLeft';\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n release();\n return;\n }\n const next =\n event.key === forward\n ? clamp01(position + step)\n : event.key === backward\n ? clamp01(position - step)\n : event.key === 'Home'\n ? 0\n : event.key === 'End'\n ? 1\n : null;\n if (next === null) return;\n event.preventDefault();\n position = next;\n record();\n }\n\n // 换了新图、或父级设回 idle(重试):滑块回到起点;没对准时滑块晃一下\n watch(\n () => challenge?.id,\n () => {\n position = 0;\n track = [];\n },\n );\n watch(\n () => status,\n (next, previous) => {\n if (next === 'idle' && previous !== 'idle') {\n position = 0;\n track = [];\n }\n if (\n next === 'error' &&\n handleElement &&\n !matchMedia('(prefers-reduced-motion: reduce)').matches\n ) {\n handleElement.animate(\n [\n { translate: '0' },\n { translate: '-6px' },\n { translate: '6px' },\n { translate: '-4px' },\n { translate: '4px' },\n { translate: '0' },\n ],\n { duration: 360 },\n );\n }\n },\n );\n\n return () => {\n const locked = !interactive();\n const settling = !dragging;\n const text =\n status === 'verifying'\n ? messages.slideVerifying\n : status === 'success'\n ? messages.slideSuccess\n : status === 'error'\n ? (errorText ?? messages.slideError)\n : (hint ?? messages.slideHint);\n const icon = status === 'success' ? Check : status === 'error' ? X : ChevronsRight;\n const piecePercent = challenge ? ((position * travel()) / challenge.width) * 100 : 0;\n const pieceWidthPercent = challenge ? (challenge.pieceWidth / challenge.width) * 100 : 0;\n const aspect = challenge ? challenge.width / challenge.height : 2;\n return (\n <div\n {...mergeAttrs<'div'>({ sx: slideCaptchaStyles.root }, rest)}\n aria-busy={status === 'verifying' || undefined}\n >\n <div\n {...mergeAttrs<'div'>({\n sx: [slideCaptchaStyles.picture, slideCaptchaDynamicStyles.ratio(aspect)],\n })}\n >\n {challenge ? (\n <>\n <img\n {...mergeAttrs<'img'>({ sx: slideCaptchaStyles.image })}\n src={challenge.background}\n alt=\"\"\n draggable={false}\n />\n <img\n {...mergeAttrs<'img'>({\n sx: [\n slideCaptchaStyles.piece,\n slideCaptchaDynamicStyles.pieceWidth(pieceWidthPercent),\n slideCaptchaDynamicStyles.at(piecePercent),\n settling && slideCaptchaStyles.pieceSettle,\n ],\n })}\n src={challenge.piece}\n alt=\"\"\n draggable={false}\n />\n </>\n ) : (\n <div {...mergeAttrs<'div'>({ sx: slideCaptchaStyles.loading })}>\n <Spinner />\n {messages.slideLoading}\n </div>\n )}\n <IconButton\n sx={slideCaptchaStyles.refresh}\n icon={RefreshCw}\n size=\"sm\"\n variant=\"ghost\"\n tone=\"neutral\"\n aria-label={messages.slideRefresh}\n disabled={status === 'verifying'}\n onClick={() => onRefresh?.()}\n />\n {(status === 'success' || status === 'error') && (\n <div\n {...mergeAttrs<'div'>({\n sx: [\n slideCaptchaStyles.banner,\n status === 'success'\n ? slideCaptchaStyles.bannerSuccess\n : slideCaptchaStyles.bannerError,\n ],\n })}\n >\n {text}\n </div>\n )}\n </div>\n <div\n {...mergeAttrs<'div'>({ sx: slideCaptchaStyles.track }, undefined, {\n ref: _toRef(trackElement),\n })}\n >\n <div\n {...mergeAttrs<'div'>({\n sx: [\n slideCaptchaStyles.fill,\n status === 'success' && slideCaptchaStyles.fillSuccess,\n status === 'error' && slideCaptchaStyles.fillError,\n settling && slideCaptchaStyles.settle,\n slideCaptchaDynamicStyles.fillTo(position),\n ],\n })}\n />\n <span {...mergeAttrs<'span'>({ sx: slideCaptchaStyles.hint })} aria-hidden=\"true\">\n {position === 0 || status !== 'idle' ? text : null}\n </span>\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n slideCaptchaStyles.handle,\n dragging && slideCaptchaStyles.handleActive,\n status === 'success' && slideCaptchaStyles.handleSuccess,\n status === 'error' && slideCaptchaStyles.handleError,\n locked && slideCaptchaStyles.locked,\n settling && slideCaptchaStyles.settle,\n slideCaptchaDynamicStyles.handleAt(position),\n ],\n },\n undefined,\n { ref: _toRef(handleElement) },\n )}\n role=\"slider\"\n aria-label={messages.slideLabel}\n aria-valuemin={0}\n aria-valuemax={travel()}\n aria-valuenow={pixels()}\n aria-valuetext={messages.slidePosition(pixels())}\n aria-disabled={locked || undefined}\n tabindex={locked ? -1 : 0}\n onPointerdown={grab}\n onKeydown={onKeydown}\n >\n <Icon icon={icon} />\n </div>\n </div>\n <VisuallyHidden aria-live=\"polite\">{status === 'idle' ? '' : text}</VisuallyHidden>\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';
1
+ import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
2
2
  import { type VNodeChild } from 'vue';
3
3
  import { type ButtonProps } from '../base/Button';
4
4
  import { type FormProps } from '../form/Form';
@@ -7,7 +7,7 @@ import { useMessages } from "../config/lang/messages.js";
7
7
  import { patternsMessages } from "./messages.js";
8
8
  import { createVNode, nextTick, shallowRef, useId } from "vue";
9
9
  import { _component, bindable, effect, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
10
- import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
10
+ import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
11
11
  //#region src/patterns/StepsForm.tsx
12
12
  /** 一步 */
13
13
  /** 未声明的属性落到 Form(form 元素)上;标签布局、只读、不可用同 Form */
@@ -1 +1 @@
1
- {"version":3,"file":"StepsForm.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../src/patterns/StepsForm.tsx"],"sourcesContent":["/**\n * 分步表单:一份 useForm 的表单分成几步填(开户、准入申请、配置向导),上方是步骤条,下方是这一步的字段与“上一步 / 下一步 / 提交”。\n * 同 Ant Design ProComponents 的 StepsForm。\n *\n * <StepsForm\n * form={form}\n * _current={step}\n * steps={[\n * { title: '企业信息', fields: ['company', 'contact'], content: () => <>…form.Field…</> },\n * { title: '账号', fields: ['password', 'confirm'], content: () => <>…</> },\n * ]}\n * />\n *\n * - “下一步”只校验这一步的字段(form.validate(fields)),通过才往后走,没通过的错误立即显示;走过的步骤可以点回去。\n * - 最后一步是“提交”(表单的原生提交):整份校验没通过时跳到第一个有错的步骤,那一步在步骤条上标成出错。\n * - 换了一步焦点移到这一步的内容上(读屏念出第几步、标题),键盘接着往下填。\n *\n * 部件:Root(Form)、Steps、Panel(这一步的内容,div)、Actions(Flex)、Previous、Next、Submit(Button)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { nextTick, useId, type VNodeChild } from 'vue';\nimport { Button, type ButtonProps } from '../base/Button';\nimport { useMessages } from '../config/lang/messages';\nimport { Form, type FormProps } from '../form/Form';\nimport type { FormControllerBase } from '../form/useForm';\nimport { Flex, type FlexProps } from '../layout/Flex';\nimport { Steps, type StepItem, type StepsProps } from '../navigation/Steps';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { patternsMessages } from './messages';\n\n/** 一步 */\nexport interface FormStep {\n /** 步骤条上的标题 */\n title: VNodeChild;\n /** 步骤条上的说明 */\n description?: VNodeChild;\n /** 这一步的字段路径(含子路径):“下一步”只校验它们,出错时这一步标成出错 */\n fields: readonly string[];\n /** 这一步的内容:form.Field 们 */\n content: () => VNodeChild;\n}\n\n/** 未声明的属性落到 Form(form 元素)上;标签布局、只读、不可用同 Form */\nexport interface StepsFormProps extends Omit<FormProps, 'controller' | 'children'> {\n /** useForm 的控制器 */\n form: FormControllerBase;\n /** 各步 */\n steps: readonly FormStep[];\n /** 当前第几步,从 0 开始:父级可以写 _current={x} */\n _current?: number;\n /** 提交按钮的文字,默认取文案(提交) */\n submitText?: VNodeChild;\n /** 步骤条(Steps)的部件属性 */\n propsSteps?: Partial<StepsProps>;\n /** 这一步内容外层的部件属性 */\n propsPanel?: PartProps<'div'>;\n /** 按钮行的部件属性 */\n propsActions?: Partial<FlexProps>;\n /** 上一步按钮的部件属性 */\n propsPrevious?: Partial<ButtonProps>;\n /** 下一步按钮的部件属性 */\n propsNext?: Partial<ButtonProps>;\n /** 提交按钮的部件属性 */\n propsSubmit?: Partial<ButtonProps>;\n}\n\n/** StepsForm 的样式:root、panel */\nexport const stepsFormStyles = css.create({\n root: { display: 'flex', flexDirection: 'column', gap: '_lg' },\n // 换步后焦点在这里:不画焦点环(内容本身不是控件),读屏念出它的名称\n panel: { display: 'flex', flexDirection: 'column', gap: '_md', outline: 'none' },\n});\n\n/** 字段 path 在这一步里:就是它,或是它的子路径(`address.city` 属于 `address`) */\nconst inStep = (step: FormStep, path: string) =>\n step.fields.some((field) => path === field || path.startsWith(`${field}.`));\n\n/** 分步表单:步骤条 + 这一步的字段 + 上一步、下一步、提交 */\nexport const StepsForm = _component(\n ({\n form,\n steps,\n _current: current = _bindable(0),\n submitText,\n propsSteps,\n propsPanel,\n propsActions,\n propsPrevious,\n propsNext,\n propsSubmit,\n ...rest\n }: StepsFormProps) => {\n const messages = useMessages('patterns', patternsMessages);\n const id = useId();\n let panel = _state.raw<HTMLElement | null>(null);\n\n /** 这一步有显示着的错误 */\n const hasError = (step: FormStep) =>\n Object.keys(form.errors).some((path) => inStep(step, path) && form.visibleError(path));\n\n /** 换到第 index 步,焦点移到这一步的内容上 */\n function go(index: number) {\n current = index;\n void nextTick(() => panel?.focus());\n }\n\n async function next() {\n const step = steps[current];\n if (step && (await form.validate(step.fields))) go(current + 1);\n }\n\n // 整份提交没通过:跳到第一个有错的步骤\n _effect(() => {\n if (form.submitCount === 0 || form.submitting) return;\n const first = steps.findIndex(hasError);\n if (first >= 0 && first !== current && !hasError(steps[current]!)) go(first);\n });\n\n const items = (): StepItem[] =>\n steps.map((step, index) => ({\n title: step.title,\n description: step.description,\n status: hasError(step) ? 'error' : undefined,\n // 只能点回走过的步骤\n disabled: index > current,\n }));\n\n return () => {\n const step = steps[current];\n const last = current >= steps.length - 1;\n return (\n <Form {...rest} controller={form}>\n <div {...css.attrs(stepsFormStyles.root)}>\n <Steps\n {...mergePartProps<StepsProps>({ items: items() }, propsSteps, {\n items: items(),\n navigable: true,\n })}\n _current={current}\n onUpdate:_current={(index: number) => go(index)}\n />\n <div\n {...mergeAttrs<'div'>({ sx: stepsFormStyles.panel }, propsPanel, {\n ref: _toRef(panel),\n id: `${id}-panel`,\n tabindex: -1,\n role: 'group',\n 'aria-label': messages.stepsFormStep(current + 1, steps.length),\n })}\n >\n {step?.content()}\n </div>\n <Flex {...mergePartProps<FlexProps>({ justify: 'end', gap: 'sm' }, propsActions)}>\n {current > 0 && (\n <Button\n {...mergePartProps<ButtonProps>(\n { variant: 'ghost', tone: 'neutral' },\n propsPrevious,\n { onClick: () => go(current - 1) },\n )}\n >\n {messages.stepsFormPrevious}\n </Button>\n )}\n {last ? (\n <Button\n {...mergePartProps<ButtonProps>({}, propsSubmit, {\n type: 'submit',\n loading: form.submitting,\n })}\n >\n {submitText ?? messages.stepsFormSubmit}\n </Button>\n ) : (\n <Button\n {...mergePartProps<ButtonProps>({}, propsNext, {\n loading: form.validating(),\n onClick: () => void next(),\n })}\n >\n {messages.stepsFormNext}\n </Button>\n )}\n </Flex>\n </div>\n </Form>\n );\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"StepsForm.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../src/patterns/StepsForm.tsx"],"sourcesContent":["/**\n * 分步表单:一份 useForm 的表单分成几步填(开户、准入申请、配置向导),上方是步骤条,下方是这一步的字段与“上一步 / 下一步 / 提交”。\n * 同 Ant Design ProComponents 的 StepsForm。\n *\n * <StepsForm\n * form={form}\n * _current={step}\n * steps={[\n * { title: '企业信息', fields: ['company', 'contact'], content: () => <>…form.Field…</> },\n * { title: '账号', fields: ['password', 'confirm'], content: () => <>…</> },\n * ]}\n * />\n *\n * - “下一步”只校验这一步的字段(form.validate(fields)),通过才往后走,没通过的错误立即显示;走过的步骤可以点回去。\n * - 最后一步是“提交”(表单的原生提交):整份校验没通过时跳到第一个有错的步骤,那一步在步骤条上标成出错。\n * - 换了一步焦点移到这一步的内容上(读屏念出第几步、标题),键盘接着往下填。\n *\n * 部件:Root(Form)、Steps、Panel(这一步的内容,div)、Actions(Flex)、Previous、Next、Submit(Button)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { nextTick, useId, type VNodeChild } from 'vue';\nimport { Button, type ButtonProps } from '../base/Button';\nimport { useMessages } from '../config/lang/messages';\nimport { Form, type FormProps } from '../form/Form';\nimport type { FormControllerBase } from '../form/useForm';\nimport { Flex, type FlexProps } from '../layout/Flex';\nimport { Steps, type StepItem, type StepsProps } from '../navigation/Steps';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { patternsMessages } from './messages';\n\n/** 一步 */\nexport interface FormStep {\n /** 步骤条上的标题 */\n title: VNodeChild;\n /** 步骤条上的说明 */\n description?: VNodeChild;\n /** 这一步的字段路径(含子路径):“下一步”只校验它们,出错时这一步标成出错 */\n fields: readonly string[];\n /** 这一步的内容:form.Field 们 */\n content: () => VNodeChild;\n}\n\n/** 未声明的属性落到 Form(form 元素)上;标签布局、只读、不可用同 Form */\nexport interface StepsFormProps extends Omit<FormProps, 'controller' | 'children'> {\n /** useForm 的控制器 */\n form: FormControllerBase;\n /** 各步 */\n steps: readonly FormStep[];\n /** 当前第几步,从 0 开始:父级可以写 _current={x} */\n _current?: number;\n /** 提交按钮的文字,默认取文案(提交) */\n submitText?: VNodeChild;\n /** 步骤条(Steps)的部件属性 */\n propsSteps?: Partial<StepsProps>;\n /** 这一步内容外层的部件属性 */\n propsPanel?: PartProps<'div'>;\n /** 按钮行的部件属性 */\n propsActions?: Partial<FlexProps>;\n /** 上一步按钮的部件属性 */\n propsPrevious?: Partial<ButtonProps>;\n /** 下一步按钮的部件属性 */\n propsNext?: Partial<ButtonProps>;\n /** 提交按钮的部件属性 */\n propsSubmit?: Partial<ButtonProps>;\n}\n\n/** StepsForm 的样式:root、panel */\nexport const stepsFormStyles = css.create({\n root: { display: 'flex', flexDirection: 'column', gap: '_lg' },\n // 换步后焦点在这里:不画焦点环(内容本身不是控件),读屏念出它的名称\n panel: { display: 'flex', flexDirection: 'column', gap: '_md', outline: 'none' },\n});\n\n/** 字段 path 在这一步里:就是它,或是它的子路径(`address.city` 属于 `address`) */\nconst inStep = (step: FormStep, path: string) =>\n step.fields.some((field) => path === field || path.startsWith(`${field}.`));\n\n/** 分步表单:步骤条 + 这一步的字段 + 上一步、下一步、提交 */\nexport const StepsForm = _component(\n ({\n form,\n steps,\n _current: current = _bindable(0),\n submitText,\n propsSteps,\n propsPanel,\n propsActions,\n propsPrevious,\n propsNext,\n propsSubmit,\n ...rest\n }: StepsFormProps) => {\n const messages = useMessages('patterns', patternsMessages);\n const id = useId();\n let panel = _state.raw<HTMLElement | null>(null);\n\n /** 这一步有显示着的错误 */\n const hasError = (step: FormStep) =>\n Object.keys(form.errors).some((path) => inStep(step, path) && form.visibleError(path));\n\n /** 换到第 index 步,焦点移到这一步的内容上 */\n function go(index: number) {\n current = index;\n void nextTick(() => panel?.focus());\n }\n\n async function next() {\n const step = steps[current];\n if (step && (await form.validate(step.fields))) go(current + 1);\n }\n\n // 整份提交没通过:跳到第一个有错的步骤\n _effect(() => {\n if (form.submitCount === 0 || form.submitting) return;\n const first = steps.findIndex(hasError);\n if (first >= 0 && first !== current && !hasError(steps[current]!)) go(first);\n });\n\n const items = (): StepItem[] =>\n steps.map((step, index) => ({\n title: step.title,\n description: step.description,\n status: hasError(step) ? 'error' : undefined,\n // 只能点回走过的步骤\n disabled: index > current,\n }));\n\n return () => {\n const step = steps[current];\n const last = current >= steps.length - 1;\n return (\n <Form {...rest} controller={form}>\n <div {...css.attrs(stepsFormStyles.root)}>\n <Steps\n {...mergePartProps<StepsProps>({ items: items() }, propsSteps, {\n items: items(),\n navigable: true,\n })}\n _current={current}\n onUpdate:_current={(index: number) => go(index)}\n />\n <div\n {...mergeAttrs<'div'>({ sx: stepsFormStyles.panel }, propsPanel, {\n ref: _toRef(panel),\n id: `${id}-panel`,\n tabindex: -1,\n role: 'group',\n 'aria-label': messages.stepsFormStep(current + 1, steps.length),\n })}\n >\n {step?.content()}\n </div>\n <Flex {...mergePartProps<FlexProps>({ justify: 'end', gap: 'sm' }, propsActions)}>\n {current > 0 && (\n <Button\n {...mergePartProps<ButtonProps>(\n { variant: 'ghost', tone: 'neutral' },\n propsPrevious,\n { onClick: () => go(current - 1) },\n )}\n >\n {messages.stepsFormPrevious}\n </Button>\n )}\n {last ? (\n <Button\n {...mergePartProps<ButtonProps>({}, propsSubmit, {\n type: 'submit',\n loading: form.submitting,\n })}\n >\n {submitText ?? messages.stepsFormSubmit}\n </Button>\n ) : (\n <Button\n {...mergePartProps<ButtonProps>({}, propsNext, {\n loading: form.validating(),\n onClick: () => void next(),\n })}\n >\n {messages.stepsFormNext}\n </Button>\n )}\n </Flex>\n </div>\n </Form>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';
1
+ import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
2
2
  import { type IconButtonProps } from '../base/IconButton';
3
3
  import type { ColumnFilterOption, ColumnStickies, SortState } from './columns';
4
4
  /** ColumnHeaderActions 的样式:trigger、active、panel、options、footer */
@@ -10,7 +10,7 @@ import { Popover } from "../overlay/Popover.js";
10
10
  import { TextField } from "../input/TextField.js";
11
11
  import { Fragment, createVNode, ref } from "vue";
12
12
  import { _component, mergeJsxProps, readonlyProp } from "@zerodep-dev/vue-tsx-pro-tsx";
13
- import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
13
+ import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
14
14
  import { EllipsisVertical, Funnel } from "@lucide/icons";
15
15
  //#region src/table/ColumnHeaderActions.tsx
16
16
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ColumnHeaderActions.js","names":["_vtp_readonlyProp","_vue_ref","_createVNode","_Fragment","_mergeProps","Menu"],"sources":["../../src/table/ColumnHeaderActions.tsx"],"sourcesContent":["/**\n * 列标题上的两个小按钮:表头筛选(ColumnFilterButton,弹出勾选的值或关键字)与列菜单(ColumnMenuButton:排序、固定、移动、隐藏)。\n * DataTableView 在列定义写了 filter、或表格开了 columnMenu 时放进列标题;状态都在外层(DataTable),这里只管画与报告。\n */\nimport { EllipsisVertical, Funnel } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { Button } from '../base/Button';\nimport { IconButton, type IconButtonProps } from '../base/IconButton';\nimport { useLang, useTextMatcher } from '../config/context';\nimport { Checkbox } from '../input/Checkbox';\nimport { TextField } from '../input/TextField';\nimport { Separator } from '../layout/Separator';\nimport { Menu, MenuItem } from '../overlay/Menu';\nimport { Popover } from '../overlay/Popover';\nimport { plainText } from '../utils/data/text';\nimport { mergePartProps } from '../utils/props';\nimport type { ColumnFilterOption, ColumnStickies, SortState } from './columns';\n\n/** 选项多于这么多时,筛选里多一个搜索框 */\nconst SEARCH_THRESHOLD = 8;\n\n/** ColumnHeaderActions 的样式:trigger、active、panel、options、footer */\nexport const columnHeaderActionStyles = css.create({\n // 比正文小一档,不撑高表头\n trigger: { flexShrink: 0, marginBlock: '-0.25em' },\n active: { color: '_accentText' },\n panel: { display: 'flex', flexDirection: 'column', gap: '_sm', minWidth: '12rem' },\n options: {\n display: 'flex',\n flexDirection: 'column',\n gap: '_xs',\n maxHeight: '16rem',\n overflowY: 'auto',\n fontWeight: '_normal',\n color: '_text',\n },\n footer: { display: 'flex', justifyContent: 'flex-end' },\n});\n\n/** 表头筛选按钮的属性 */\nexport interface ColumnFilterButtonProps {\n /** 列标题的文字:按钮的名称 */\n label: string;\n /** 可以勾选的值;关键字筛选时为 'text' */\n options: readonly ColumnFilterOption[] | 'text';\n /** 选中的值(关键字筛选时是 [关键字]) */\n values: readonly string[];\n /** 改了筛选 */\n onChange: (values: string[]) => void;\n /** 按钮的部件属性 */\n propsTrigger?: Partial<IconButtonProps>;\n}\n\n/** 表头筛选:漏斗按钮,弹出勾选的值(多时可以搜索)或关键字输入框;改了立即生效 */\nexport const ColumnFilterButton = _component(\n ({ label, options, values, onChange, propsTrigger }: ColumnFilterButtonProps) => {\n const lang = useLang();\n const matcher = useTextMatcher();\n let search = _state('');\n\n const shown = () => {\n if (options === 'text' || !search) return options === 'text' ? [] : options;\n const match = matcher();\n return options.filter((option) => match(plainText(option.label) ?? option.value, search));\n };\n\n function toggle(value: string, checked: boolean) {\n onChange(checked ? [...values, value] : values.filter((item) => item !== value));\n }\n\n function renderOptions(): VNodeChild {\n if (options === 'text')\n return (\n <TextField\n _value={values[0] ?? ''}\n onUpdate:_value={(text: string) => onChange(text ? [text] : [])}\n aria-label={lang.tableFilterSearch}\n placeholder={lang.tableFilterSearch}\n clearable\n autofocus\n size=\"sm\"\n />\n );\n return (\n <>\n {options.length > SEARCH_THRESHOLD && (\n <TextField\n _value={search}\n onUpdate:_value={(text: string) => (search = text)}\n aria-label={lang.tableFilterSearch}\n placeholder={lang.tableFilterSearch}\n clearable\n size=\"sm\"\n />\n )}\n <div {...css.attrs(columnHeaderActionStyles.options)} role=\"group\" aria-label={label}>\n {shown().map((option) => (\n <Checkbox\n key={option.value}\n _checked={values.includes(option.value)}\n onUpdate:_checked={(checked: boolean) => toggle(option.value, checked)}\n >\n {option.label ?? option.value}\n </Checkbox>\n ))}\n </div>\n </>\n );\n }\n\n return () => {\n const active = values.length > 0;\n return (\n <Popover\n placement=\"bottom-end\"\n aria-label={lang.tableFilterColumn(label, false)}\n trigger={(props) => (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: Funnel,\n size: 'xs',\n variant: 'ghost',\n tone: 'neutral',\n sx: [columnHeaderActionStyles.trigger, active && columnHeaderActionStyles.active],\n 'aria-label': lang.tableFilterColumn(label, active),\n },\n propsTrigger,\n props,\n )}\n />\n )}\n >\n <div {...css.attrs(columnHeaderActionStyles.panel)}>\n {renderOptions()}\n <div {...css.attrs(columnHeaderActionStyles.footer)}>\n <Button size=\"sm\" variant=\"ghost\" disabled={!active} onClick={() => onChange([])}>\n {lang.tableFilterClear}\n </Button>\n </div>\n </div>\n </Popover>\n );\n };\n },\n);\n\n/** 列菜单里的一项操作 */\nexport interface ColumnMenuActions {\n /** 按这一列升序 */\n sortAscending: unknown;\n /** 按这一列降序 */\n sortDescending: unknown;\n /** 取消这一列的排序 */\n unsort: unknown;\n /** 固定在开头 */\n pinStart: unknown;\n /** 固定在结尾 */\n pinEnd: unknown;\n /** 取消固定 */\n unpin: unknown;\n /** 往前移一列 */\n moveBackward: unknown;\n /** 往后移一列 */\n moveForward: unknown;\n /** 隐藏这一列 */\n hide: unknown;\n}\n\n/** 列菜单按钮的属性 */\nexport interface ColumnMenuButtonProps {\n /** 列标题的文字:按钮的名称 */\n label: string;\n /** 可以排序:菜单里有升序、降序 */\n sortable: boolean;\n /** 这一列当前的排序 */\n sorted?: SortState['direction'];\n /** 这一列当前固定在哪一侧 */\n pinned?: keyof ColumnStickies;\n /** 能不能往前、往后移(已经在头上、尾上时不能) */\n canMove: { backward: boolean; forward: boolean };\n /** 能不能隐藏(只剩一列时不能) */\n canHide: boolean;\n /** 选了一项 */\n onAction: (action: keyof ColumnMenuActions) => void;\n /** 按钮的部件属性 */\n propsTrigger?: Partial<IconButtonProps>;\n}\n\n/** 列菜单:⋮ 按钮,弹出排序、固定、移动、隐藏 */\nexport const ColumnMenuButton = _component(\n ({\n label,\n sortable,\n sorted,\n pinned,\n canMove,\n canHide,\n onAction,\n propsTrigger,\n }: ColumnMenuButtonProps) => {\n const lang = useLang();\n return () => (\n <Menu\n placement=\"bottom-end\"\n trigger={(props) => (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: EllipsisVertical,\n size: 'xs',\n variant: 'ghost',\n tone: 'neutral',\n sx: columnHeaderActionStyles.trigger,\n 'aria-label': lang.tableColumnMenu(label),\n },\n propsTrigger,\n props,\n )}\n />\n )}\n >\n {sortable && (\n <>\n <MenuItem disabled={sorted === 'ascending'} onAction={() => onAction('sortAscending')}>\n {lang.tableSortAscending}\n </MenuItem>\n <MenuItem\n disabled={sorted === 'descending'}\n onAction={() => onAction('sortDescending')}\n >\n {lang.tableSortDescending}\n </MenuItem>\n {sorted && (\n <MenuItem onAction={() => onAction('unsort')}>{lang.tableSortClear}</MenuItem>\n )}\n <Separator decorative={false} />\n </>\n )}\n {pinned !== 'start' && (\n <MenuItem onAction={() => onAction('pinStart')}>{lang.tablePinStart}</MenuItem>\n )}\n {pinned !== 'end' && (\n <MenuItem onAction={() => onAction('pinEnd')}>{lang.tablePinEnd}</MenuItem>\n )}\n {pinned && <MenuItem onAction={() => onAction('unpin')}>{lang.tableUnpin}</MenuItem>}\n <Separator decorative={false} />\n <MenuItem disabled={!canMove.backward} onAction={() => onAction('moveBackward')}>\n {lang.tableMoveBackward}\n </MenuItem>\n <MenuItem disabled={!canMove.forward} onAction={() => onAction('moveForward')}>\n {lang.tableMoveForward}\n </MenuItem>\n <MenuItem disabled={!canHide} onAction={() => onAction('hide')}>\n {lang.tableHideColumn}\n </MenuItem>\n </Menu>\n );\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"ColumnHeaderActions.js","names":["_vtp_readonlyProp","_vue_ref","_createVNode","_Fragment","_mergeProps","Menu"],"sources":["../../src/table/ColumnHeaderActions.tsx"],"sourcesContent":["/**\n * 列标题上的两个小按钮:表头筛选(ColumnFilterButton,弹出勾选的值或关键字)与列菜单(ColumnMenuButton:排序、固定、移动、隐藏)。\n * DataTableView 在列定义写了 filter、或表格开了 columnMenu 时放进列标题;状态都在外层(DataTable),这里只管画与报告。\n */\nimport { EllipsisVertical, Funnel } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { Button } from '../base/Button';\nimport { IconButton, type IconButtonProps } from '../base/IconButton';\nimport { useLang, useTextMatcher } from '../config/context';\nimport { Checkbox } from '../input/Checkbox';\nimport { TextField } from '../input/TextField';\nimport { Separator } from '../layout/Separator';\nimport { Menu, MenuItem } from '../overlay/Menu';\nimport { Popover } from '../overlay/Popover';\nimport { plainText } from '../utils/data/text';\nimport { mergePartProps } from '../utils/props';\nimport type { ColumnFilterOption, ColumnStickies, SortState } from './columns';\n\n/** 选项多于这么多时,筛选里多一个搜索框 */\nconst SEARCH_THRESHOLD = 8;\n\n/** ColumnHeaderActions 的样式:trigger、active、panel、options、footer */\nexport const columnHeaderActionStyles = css.create({\n // 比正文小一档,不撑高表头\n trigger: { flexShrink: 0, marginBlock: '-0.25em' },\n active: { color: '_accentText' },\n panel: { display: 'flex', flexDirection: 'column', gap: '_sm', minWidth: '12rem' },\n options: {\n display: 'flex',\n flexDirection: 'column',\n gap: '_xs',\n maxHeight: '16rem',\n overflowY: 'auto',\n fontWeight: '_normal',\n color: '_text',\n },\n footer: { display: 'flex', justifyContent: 'flex-end' },\n});\n\n/** 表头筛选按钮的属性 */\nexport interface ColumnFilterButtonProps {\n /** 列标题的文字:按钮的名称 */\n label: string;\n /** 可以勾选的值;关键字筛选时为 'text' */\n options: readonly ColumnFilterOption[] | 'text';\n /** 选中的值(关键字筛选时是 [关键字]) */\n values: readonly string[];\n /** 改了筛选 */\n onChange: (values: string[]) => void;\n /** 按钮的部件属性 */\n propsTrigger?: Partial<IconButtonProps>;\n}\n\n/** 表头筛选:漏斗按钮,弹出勾选的值(多时可以搜索)或关键字输入框;改了立即生效 */\nexport const ColumnFilterButton = _component(\n ({ label, options, values, onChange, propsTrigger }: ColumnFilterButtonProps) => {\n const lang = useLang();\n const matcher = useTextMatcher();\n let search = _state('');\n\n const shown = () => {\n if (options === 'text' || !search) return options === 'text' ? [] : options;\n const match = matcher();\n return options.filter((option) => match(plainText(option.label) ?? option.value, search));\n };\n\n function toggle(value: string, checked: boolean) {\n onChange(checked ? [...values, value] : values.filter((item) => item !== value));\n }\n\n function renderOptions(): VNodeChild {\n if (options === 'text')\n return (\n <TextField\n _value={values[0] ?? ''}\n onUpdate:_value={(text: string) => onChange(text ? [text] : [])}\n aria-label={lang.tableFilterSearch}\n placeholder={lang.tableFilterSearch}\n clearable\n autofocus\n size=\"sm\"\n />\n );\n return (\n <>\n {options.length > SEARCH_THRESHOLD && (\n <TextField\n _value={search}\n onUpdate:_value={(text: string) => (search = text)}\n aria-label={lang.tableFilterSearch}\n placeholder={lang.tableFilterSearch}\n clearable\n size=\"sm\"\n />\n )}\n <div {...css.attrs(columnHeaderActionStyles.options)} role=\"group\" aria-label={label}>\n {shown().map((option) => (\n <Checkbox\n key={option.value}\n _checked={values.includes(option.value)}\n onUpdate:_checked={(checked: boolean) => toggle(option.value, checked)}\n >\n {option.label ?? option.value}\n </Checkbox>\n ))}\n </div>\n </>\n );\n }\n\n return () => {\n const active = values.length > 0;\n return (\n <Popover\n placement=\"bottom-end\"\n aria-label={lang.tableFilterColumn(label, false)}\n trigger={(props) => (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: Funnel,\n size: 'xs',\n variant: 'ghost',\n tone: 'neutral',\n sx: [columnHeaderActionStyles.trigger, active && columnHeaderActionStyles.active],\n 'aria-label': lang.tableFilterColumn(label, active),\n },\n propsTrigger,\n props,\n )}\n />\n )}\n >\n <div {...css.attrs(columnHeaderActionStyles.panel)}>\n {renderOptions()}\n <div {...css.attrs(columnHeaderActionStyles.footer)}>\n <Button size=\"sm\" variant=\"ghost\" disabled={!active} onClick={() => onChange([])}>\n {lang.tableFilterClear}\n </Button>\n </div>\n </div>\n </Popover>\n );\n };\n },\n);\n\n/** 列菜单里的一项操作 */\nexport interface ColumnMenuActions {\n /** 按这一列升序 */\n sortAscending: unknown;\n /** 按这一列降序 */\n sortDescending: unknown;\n /** 取消这一列的排序 */\n unsort: unknown;\n /** 固定在开头 */\n pinStart: unknown;\n /** 固定在结尾 */\n pinEnd: unknown;\n /** 取消固定 */\n unpin: unknown;\n /** 往前移一列 */\n moveBackward: unknown;\n /** 往后移一列 */\n moveForward: unknown;\n /** 隐藏这一列 */\n hide: unknown;\n}\n\n/** 列菜单按钮的属性 */\nexport interface ColumnMenuButtonProps {\n /** 列标题的文字:按钮的名称 */\n label: string;\n /** 可以排序:菜单里有升序、降序 */\n sortable: boolean;\n /** 这一列当前的排序 */\n sorted?: SortState['direction'];\n /** 这一列当前固定在哪一侧 */\n pinned?: keyof ColumnStickies;\n /** 能不能往前、往后移(已经在头上、尾上时不能) */\n canMove: { backward: boolean; forward: boolean };\n /** 能不能隐藏(只剩一列时不能) */\n canHide: boolean;\n /** 选了一项 */\n onAction: (action: keyof ColumnMenuActions) => void;\n /** 按钮的部件属性 */\n propsTrigger?: Partial<IconButtonProps>;\n}\n\n/** 列菜单:⋮ 按钮,弹出排序、固定、移动、隐藏 */\nexport const ColumnMenuButton = _component(\n ({\n label,\n sortable,\n sorted,\n pinned,\n canMove,\n canHide,\n onAction,\n propsTrigger,\n }: ColumnMenuButtonProps) => {\n const lang = useLang();\n return () => (\n <Menu\n placement=\"bottom-end\"\n trigger={(props) => (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: EllipsisVertical,\n size: 'xs',\n variant: 'ghost',\n tone: 'neutral',\n sx: columnHeaderActionStyles.trigger,\n 'aria-label': lang.tableColumnMenu(label),\n },\n propsTrigger,\n props,\n )}\n />\n )}\n >\n {sortable && (\n <>\n <MenuItem disabled={sorted === 'ascending'} onAction={() => onAction('sortAscending')}>\n {lang.tableSortAscending}\n </MenuItem>\n <MenuItem\n disabled={sorted === 'descending'}\n onAction={() => onAction('sortDescending')}\n >\n {lang.tableSortDescending}\n </MenuItem>\n {sorted && (\n <MenuItem onAction={() => onAction('unsort')}>{lang.tableSortClear}</MenuItem>\n )}\n <Separator decorative={false} />\n </>\n )}\n {pinned !== 'start' && (\n <MenuItem onAction={() => onAction('pinStart')}>{lang.tablePinStart}</MenuItem>\n )}\n {pinned !== 'end' && (\n <MenuItem onAction={() => onAction('pinEnd')}>{lang.tablePinEnd}</MenuItem>\n )}\n {pinned && <MenuItem onAction={() => onAction('unpin')}>{lang.tableUnpin}</MenuItem>}\n <Separator decorative={false} />\n <MenuItem disabled={!canMove.backward} onAction={() => onAction('moveBackward')}>\n {lang.tableMoveBackward}\n </MenuItem>\n <MenuItem disabled={!canMove.forward} onAction={() => onAction('moveForward')}>\n {lang.tableMoveForward}\n </MenuItem>\n <MenuItem disabled={!canHide} onAction={() => onAction('hide')}>\n {lang.tableHideColumn}\n </MenuItem>\n </Menu>\n );\n },\n);\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';
1
+ import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
2
2
  import { type ButtonProps } from '../base/Button';
3
3
  import { type IconButtonProps } from '../base/IconButton';
4
4
  import { type SortableProps } from '../display/Sortable';
@@ -9,7 +9,7 @@ import { Checkbox } from "../input/Checkbox.js";
9
9
  import { Popover } from "../overlay/Popover.js";
10
10
  import { createVNode, isVNode } from "vue";
11
11
  import { _component, bindable, mergeJsxProps, readonlyProp } from "@zerodep-dev/vue-tsx-pro-tsx";
12
- import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
12
+ import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
13
13
  import { Columns3 } from "@lucide/icons";
14
14
  //#region src/table/ColumnSettings.tsx
15
15
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ColumnSettings.js","names":["_isVNode","_vtp_readonlyProp","_vtp_bindable","_createVNode","_mergeProps"],"sources":["../../src/table/ColumnSettings.tsx"],"sourcesContent":["/**\n * 列设置:表格工具栏上的按钮,弹出全部的列——勾选显示哪些、拖动(或聚焦把手后用键盘)调整顺序,“重置”回到列定义。\n * 写回的 hidden、order 与 DataTable 的 hiddenColumns、columnOrder 是同一份,两边双向绑定同一个状态即可。\n *\n * <ColumnSettings columns={columns} _hidden={hidden} _order={order} />\n * <DataTable columns={columns} _hiddenColumns={hidden} _columnOrder={order} … />\n *\n * 只剩一列可见时不能再隐藏。部件:Trigger(IconButton)、Panel(Popover 的弹出层)、List(Sortable)、Reset(Button)。\n */\nimport { Columns3 } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { Button, type ButtonProps } from '../base/Button';\nimport { IconButton, type IconButtonProps } from '../base/IconButton';\nimport { useLang } from '../config/context';\nimport { Sortable, type SortableProps } from '../display/Sortable';\nimport { Checkbox } from '../input/Checkbox';\nimport { Popover, type PopoverProps } from '../overlay/Popover';\nimport { plainText } from '../utils/data/text';\nimport { mergePartProps } from '../utils/props';\nimport { arrangeColumns, type DataTableColumn } from './columns';\n\n/** ColumnSettings 的属性 */\nexport interface ColumnSettingsProps<T> {\n /** 全部的列(列定义的顺序) */\n columns: readonly DataTableColumn<T>[];\n /** 隐藏的列的 key:父级写 _hidden={x},与 DataTable 的 hiddenColumns 绑同一个状态 */\n _hidden?: string[];\n /** 列的顺序:父级写 _order={x},与 DataTable 的 columnOrder 绑同一个状态 */\n _order?: string[];\n /** 点了“重置”:显示与顺序回到列定义;要连列宽、固定一起还原时在这里清掉 */\n onReset?: () => void;\n /** 触发按钮的部件属性 */\n propsTrigger?: Partial<IconButtonProps>;\n /** 弹出层(Popover)的部件属性 */\n propsPanel?: Partial<PopoverProps>;\n /** 列表(Sortable)的部件属性 */\n propsList?: Partial<SortableProps<DataTableColumn<T>>>;\n /** “重置”按钮的部件属性 */\n propsReset?: Partial<ButtonProps>;\n}\n\n/** ColumnSettings 的样式:panel、list、header */\nexport const columnSettingsStyles = css.create({\n panel: { display: 'flex', flexDirection: 'column', gap: '_sm', minWidth: '14rem' },\n list: { maxHeight: '20rem', overflowY: 'auto' },\n header: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '_md' },\n title: { fontWeight: '_semibold', fontSize: '_sm' },\n});\n\n/** 列设置:勾选显示、拖动排序、重置 */\nexport const ColumnSettings = _component(\n <T,>({\n columns,\n _hidden: hidden = _bindable<string[]>([]),\n _order: order = _bindable<string[]>([]),\n onReset,\n propsTrigger,\n propsPanel,\n propsList,\n propsReset,\n }: ColumnSettingsProps<T>) => {\n const lang = useLang();\n const labelOf = (column: DataTableColumn<T>) => plainText(column.header) ?? column.key;\n // 按当前顺序列出(固定列照常在两头)\n const arranged = () => arrangeColumns(columns, order, undefined);\n const visibleCount = () => columns.length - hidden.length;\n\n function toggle(key: string, visible: boolean) {\n hidden = visible ? hidden.filter((item) => item !== key) : [...hidden, key];\n }\n\n function reset() {\n hidden = [];\n order = [];\n onReset?.();\n }\n\n return () => (\n <Popover\n {...mergePartProps<Partial<PopoverProps>>(\n { placement: 'bottom-end', 'aria-label': lang.tableColumnSettings },\n propsPanel,\n )}\n trigger={(props) => (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: Columns3,\n variant: 'ghost',\n tone: 'neutral',\n 'aria-label': lang.tableColumnSettings,\n },\n propsTrigger,\n props,\n )}\n />\n )}\n >\n <div {...css.attrs(columnSettingsStyles.panel)}>\n <div {...css.attrs(columnSettingsStyles.header)}>\n <span {...css.attrs(columnSettingsStyles.title)}>{lang.tableColumnSettings}</span>\n <Button\n {...mergePartProps<ButtonProps>({ size: 'sm', variant: 'ghost' }, propsReset, {\n disabled: hidden.length === 0 && order.length === 0,\n onClick: reset,\n })}\n >\n {lang.tableColumnSettingsReset}\n </Button>\n </div>\n <Sortable\n {...mergePartProps<Partial<SortableProps<DataTableColumn<T>>>>(\n { sx: columnSettingsStyles.list, 'aria-label': lang.tableColumnSettings },\n propsList,\n )}\n _items={arranged()}\n onUpdate:_items={(next: DataTableColumn<T>[]) =>\n (order = next.map((column) => column.key))\n }\n getKey={(column) => column.key}\n getLabel={labelOf}\n >\n {(column) => {\n const visible = !hidden.includes(column.key);\n return (\n <Checkbox\n _checked={visible}\n // 只剩这一列可见时不能再隐藏\n disabled={visible && visibleCount() <= 1}\n onUpdate:_checked={(checked: boolean) => toggle(column.key, checked)}\n >\n {labelOf(column)}\n </Checkbox>\n );\n }}\n </Sortable>\n </div>\n </Popover>\n );\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"ColumnSettings.js","names":["_isVNode","_vtp_readonlyProp","_vtp_bindable","_createVNode","_mergeProps"],"sources":["../../src/table/ColumnSettings.tsx"],"sourcesContent":["/**\n * 列设置:表格工具栏上的按钮,弹出全部的列——勾选显示哪些、拖动(或聚焦把手后用键盘)调整顺序,“重置”回到列定义。\n * 写回的 hidden、order 与 DataTable 的 hiddenColumns、columnOrder 是同一份,两边双向绑定同一个状态即可。\n *\n * <ColumnSettings columns={columns} _hidden={hidden} _order={order} />\n * <DataTable columns={columns} _hiddenColumns={hidden} _columnOrder={order} … />\n *\n * 只剩一列可见时不能再隐藏。部件:Trigger(IconButton)、Panel(Popover 的弹出层)、List(Sortable)、Reset(Button)。\n */\nimport { Columns3 } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { Button, type ButtonProps } from '../base/Button';\nimport { IconButton, type IconButtonProps } from '../base/IconButton';\nimport { useLang } from '../config/context';\nimport { Sortable, type SortableProps } from '../display/Sortable';\nimport { Checkbox } from '../input/Checkbox';\nimport { Popover, type PopoverProps } from '../overlay/Popover';\nimport { plainText } from '../utils/data/text';\nimport { mergePartProps } from '../utils/props';\nimport { arrangeColumns, type DataTableColumn } from './columns';\n\n/** ColumnSettings 的属性 */\nexport interface ColumnSettingsProps<T> {\n /** 全部的列(列定义的顺序) */\n columns: readonly DataTableColumn<T>[];\n /** 隐藏的列的 key:父级写 _hidden={x},与 DataTable 的 hiddenColumns 绑同一个状态 */\n _hidden?: string[];\n /** 列的顺序:父级写 _order={x},与 DataTable 的 columnOrder 绑同一个状态 */\n _order?: string[];\n /** 点了“重置”:显示与顺序回到列定义;要连列宽、固定一起还原时在这里清掉 */\n onReset?: () => void;\n /** 触发按钮的部件属性 */\n propsTrigger?: Partial<IconButtonProps>;\n /** 弹出层(Popover)的部件属性 */\n propsPanel?: Partial<PopoverProps>;\n /** 列表(Sortable)的部件属性 */\n propsList?: Partial<SortableProps<DataTableColumn<T>>>;\n /** “重置”按钮的部件属性 */\n propsReset?: Partial<ButtonProps>;\n}\n\n/** ColumnSettings 的样式:panel、list、header */\nexport const columnSettingsStyles = css.create({\n panel: { display: 'flex', flexDirection: 'column', gap: '_sm', minWidth: '14rem' },\n list: { maxHeight: '20rem', overflowY: 'auto' },\n header: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '_md' },\n title: { fontWeight: '_semibold', fontSize: '_sm' },\n});\n\n/** 列设置:勾选显示、拖动排序、重置 */\nexport const ColumnSettings = _component(\n <T,>({\n columns,\n _hidden: hidden = _bindable<string[]>([]),\n _order: order = _bindable<string[]>([]),\n onReset,\n propsTrigger,\n propsPanel,\n propsList,\n propsReset,\n }: ColumnSettingsProps<T>) => {\n const lang = useLang();\n const labelOf = (column: DataTableColumn<T>) => plainText(column.header) ?? column.key;\n // 按当前顺序列出(固定列照常在两头)\n const arranged = () => arrangeColumns(columns, order, undefined);\n const visibleCount = () => columns.length - hidden.length;\n\n function toggle(key: string, visible: boolean) {\n hidden = visible ? hidden.filter((item) => item !== key) : [...hidden, key];\n }\n\n function reset() {\n hidden = [];\n order = [];\n onReset?.();\n }\n\n return () => (\n <Popover\n {...mergePartProps<Partial<PopoverProps>>(\n { placement: 'bottom-end', 'aria-label': lang.tableColumnSettings },\n propsPanel,\n )}\n trigger={(props) => (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: Columns3,\n variant: 'ghost',\n tone: 'neutral',\n 'aria-label': lang.tableColumnSettings,\n },\n propsTrigger,\n props,\n )}\n />\n )}\n >\n <div {...css.attrs(columnSettingsStyles.panel)}>\n <div {...css.attrs(columnSettingsStyles.header)}>\n <span {...css.attrs(columnSettingsStyles.title)}>{lang.tableColumnSettings}</span>\n <Button\n {...mergePartProps<ButtonProps>({ size: 'sm', variant: 'ghost' }, propsReset, {\n disabled: hidden.length === 0 && order.length === 0,\n onClick: reset,\n })}\n >\n {lang.tableColumnSettingsReset}\n </Button>\n </div>\n <Sortable\n {...mergePartProps<Partial<SortableProps<DataTableColumn<T>>>>(\n { sx: columnSettingsStyles.list, 'aria-label': lang.tableColumnSettings },\n propsList,\n )}\n _items={arranged()}\n onUpdate:_items={(next: DataTableColumn<T>[]) =>\n (order = next.map((column) => column.key))\n }\n getKey={(column) => column.key}\n getLabel={labelOf}\n >\n {(column) => {\n const visible = !hidden.includes(column.key);\n return (\n <Checkbox\n _checked={visible}\n // 只剩这一列可见时不能再隐藏\n disabled={visible && visibleCount() <= 1}\n onUpdate:_checked={(checked: boolean) => toggle(column.key, checked)}\n >\n {labelOf(column)}\n </Checkbox>\n );\n }}\n </Sortable>\n </div>\n </Popover>\n );\n },\n);\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';
1
+ import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
2
2
  import type { VNodeChild } from 'vue';
3
3
  import { type PartProps } from '../utils/props';
4
4
  import { type DataTableColumn } from './columns';
@@ -5,7 +5,7 @@ import { useColumnDisplay } from "./column-display.js";
5
5
  import { Table, TableBody, TableCell, TableFoot, TableHead, TableHeaderCell, TableRow } from "./Table.js";
6
6
  import { computed, createVNode, isVNode } from "vue";
7
7
  import { _component, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
8
- import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
8
+ import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
9
9
  //#region src/table/ColumnTable.tsx
10
10
  /** 一格合并几行、几列;0 是被别的格合并掉(不渲染) */
11
11
  /** 列标题的部件属性:对齐与宽度跟随列定义 */
@@ -1 +1 @@
1
- {"version":3,"file":"ColumnTable.js","names":["_isVNode","_vtp_readonlyProp","_vtp_restProps","_vue_computed","_createVNode","_mergeProps"],"sources":["../../src/table/ColumnTable.tsx"],"sourcesContent":["/**\n * 按列定义渲染的静态表格:列定义与 DataTable 相同(type、format、statuses、empty、summary、align、cell),\n * 渲染成普通的 Table(不虚拟滚动、列宽按内容、单元格可以换行),可以合并单元格。打印、导出预览、详情页里的明细表用它;\n * 要排序、勾选、筛选、十万行的用 DataTable。\n *\n * <ColumnTable rows={items} columns={columns} getKey={(item) => item.id} mergeRepeated={['supplier']} aria-label=\"报价明细\" />\n *\n * 合并单元格:mergeRepeated 写列的 key,这几列里上下相邻、值相同的格合成一格(后一列只在前一列的同一格里合并,层层分组);\n * 更灵活的用 cellSpan,返回 { rowSpan, colSpan },被合并掉的格返回 0(同 Ant Design 的 onCell)。合并的格垂直居中。\n *\n * 部件:Root(Table)、HeaderCell(th)、Row(tr)、Cell(td)、SummaryCell(表尾的 td)。\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 { useLang } from '../config/context';\nimport { mergeProps, type PartProps } from '../utils/props';\nimport { useColumnDisplay } from './column-display';\nimport { columnType, columnValue, sumColumn, type DataTableColumn } from './columns';\nimport {\n Table,\n TableBody,\n TableCell,\n TableFoot,\n TableHead,\n TableHeaderCell,\n TableRow,\n type TableHeaderCellProps,\n type TableProps,\n} from './Table';\n\n/** 一格合并几行、几列;0 是被别的格合并掉(不渲染) */\nexport interface CellSpan {\n /** 往下合并几行,默认 1 */\n rowSpan?: number;\n /** 往后合并几列,默认 1 */\n colSpan?: number;\n}\n\n/** 列标题的部件属性:对齐与宽度跟随列定义 */\ntype HeaderCellParts = Partial<TableHeaderCellProps>;\n/** 单元格的部件属性:对齐跟随列定义,合并由 cellSpan、mergeRepeated 决定 */\ntype CellParts = PartProps<'td', 'align' | 'rowspan' | 'colspan'>;\n\n/** 未声明的属性落到 table 上;外观(density、variant、striped)同 Table */\nexport interface ColumnTableProps<T> extends Omit<TableProps, 'children'> {\n /** 数据 */\n rows: readonly T[];\n /** 列定义(与 DataTable 相同;sortable、filter、sticky、resizable 在这里不起作用) */\n columns: readonly DataTableColumn<T>[];\n /** 行的 key;不写时用下标 */\n getKey?: (row: T, index: number) => string;\n /** 这几列里上下相邻、值相同的格合成一格;后一列只在前一列的同一格里合并 */\n mergeRepeated?: readonly string[];\n /** 合并单元格:返回这一格合并几行、几列,被合并掉的返回 { rowSpan: 0 } 或 { colSpan: 0 } */\n cellSpan?: (row: T, column: DataTableColumn<T>, index: number) => CellSpan | undefined;\n /** 合计行第一列的文字(第一列自己没写 summary 时),默认取语言包(合计) */\n summaryLabel?: VNodeChild;\n /** 列标题(th)的部件属性,可以按列计算 */\n propsHeaderCell?: HeaderCellParts | ((column: DataTableColumn<T>) => HeaderCellParts);\n /** 每一行(tr)的部件属性,可以按行计算 */\n propsRow?: PartProps<'tr'> | ((row: T, index: number) => PartProps<'tr'>);\n /** 每个单元格(td)的部件属性,可以按行与列计算 */\n propsCell?: CellParts | ((row: T, column: DataTableColumn<T>) => CellParts);\n /** 合计行每个单元格的部件属性,可以按列计算 */\n propsSummaryCell?: CellParts | ((column: DataTableColumn<T>) => CellParts);\n}\n\n/** ColumnTable 的样式:merged */\nexport const columnTableStyles = css.create({\n // 合并的格跨了几行:内容垂直居中,下边线照常\n merged: { verticalAlign: 'middle' },\n});\n\n/**\n * mergeRepeated 的跨行数:每列一个数组,第 i 行是这一格往下合并几行,被合并掉的是 0。\n * 后一列在前一列的分组边界处断开(不把不同供应商下同名的品类合在一起)\n */\nexport function repeatedRowSpans<T>(\n rows: readonly T[],\n columns: readonly DataTableColumn<T>[],\n keys: readonly string[],\n): Map<string, number[]> {\n const spans = new Map<string, number[]>();\n // 上一列的分组从哪些行开始:本列的合并不能跨过它们\n let boundaries = new Set<number>([0]);\n for (const key of keys) {\n const column = columns.find((item) => item.key === key);\n if (!column) continue;\n const list = Array.from({ length: rows.length }, () => 1);\n const starts = new Set<number>();\n let start = 0;\n for (let index = 0; index < rows.length; index++) {\n const same =\n index > start &&\n !boundaries.has(index) &&\n String(columnValue(column, rows[index]!)) === String(columnValue(column, rows[start]!));\n if (same) {\n list[start]!++;\n list[index] = 0;\n } else {\n start = index;\n starts.add(index);\n }\n }\n spans.set(key, list);\n boundaries = new Set([...boundaries, ...starts]);\n }\n return spans;\n}\n\n/** 按列定义渲染的静态表格:格式化同 DataTable,可以合并单元格、带合计行 */\nexport const ColumnTable = _component(\n <T,>({\n rows,\n columns,\n getKey,\n mergeRepeated,\n cellSpan,\n summaryLabel,\n propsHeaderCell,\n propsRow,\n propsCell,\n propsSummaryCell,\n ...rest\n }: ColumnTableProps<T>) => {\n const lang = useLang();\n const display = useColumnDisplay<T>();\n const types = _derived(columns.map((column) => columnType(column, rows)));\n const shown = _derived(display.columns(columns, types));\n const merged = _derived(\n mergeRepeated?.length ? repeatedRowSpans(rows, columns, mergeRepeated) : null,\n );\n const hasSummary = _derived(columns.some((column) => column.summary != null));\n\n /** 一格的合并:cellSpan 优先,其次 mergeRepeated */\n function spanOf(row: T, column: DataTableColumn<T>, index: number): CellSpan | undefined {\n const own = cellSpan?.(row, column, index);\n if (own) return own;\n const rowSpan = merged?.get(column.key)?.[index];\n return rowSpan == null || rowSpan === 1 ? undefined : { rowSpan };\n }\n\n function summaryCell(column: DataTableColumn<T>, position: number): VNodeChild {\n if (column.summary === 'sum') {\n const total = sumColumn(column, rows);\n return total == null\n ? (column.empty ?? lang.emptyValue)\n : display.value(column, types[position]!, total);\n }\n if (column.summary) return column.summary(rows);\n return position === 0 ? (summaryLabel ?? lang.tableSummary) : null;\n }\n\n return () => (\n <Table {...rest}>\n <TableHead>\n <TableRow>\n {shown.map((column) => (\n <TableHeaderCell\n key={column.key}\n {...(typeof propsHeaderCell === 'function'\n ? propsHeaderCell(column)\n : propsHeaderCell)}\n align={column.align}\n width={column.width}\n >\n {column.header}\n </TableHeaderCell>\n ))}\n </TableRow>\n </TableHead>\n <TableBody>\n {rows.map((row, index) => (\n <TableRow\n key={getKey?.(row, index) ?? index}\n {...mergeProps<'tr'>(\n {},\n typeof propsRow === 'function' ? propsRow(row, index) : propsRow,\n )}\n >\n {shown.map((column) => {\n const span = spanOf(row, column, index);\n if (span?.rowSpan === 0 || span?.colSpan === 0) return null;\n const own = typeof propsCell === 'function' ? propsCell(row, column) : propsCell;\n return (\n <TableCell\n key={column.key}\n {...mergeProps<'td'>(\n { sx: span?.rowSpan ? columnTableStyles.merged : undefined },\n own,\n { rowspan: span?.rowSpan, colspan: span?.colSpan },\n )}\n align={column.align}\n nowrap={!column.wrap && column.width != null}\n >\n {column.cell!(row, index)}\n </TableCell>\n );\n })}\n </TableRow>\n ))}\n </TableBody>\n {hasSummary && (\n <TableFoot>\n <TableRow>\n {shown.map((column, position) => (\n <TableCell\n key={column.key}\n {...(typeof propsSummaryCell === 'function'\n ? propsSummaryCell(column)\n : propsSummaryCell)}\n align={column.align}\n >\n {summaryCell(column, position)}\n </TableCell>\n ))}\n </TableRow>\n </TableFoot>\n )}\n </Table>\n );\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"ColumnTable.js","names":["_isVNode","_vtp_readonlyProp","_vtp_restProps","_vue_computed","_createVNode","_mergeProps"],"sources":["../../src/table/ColumnTable.tsx"],"sourcesContent":["/**\n * 按列定义渲染的静态表格:列定义与 DataTable 相同(type、format、statuses、empty、summary、align、cell),\n * 渲染成普通的 Table(不虚拟滚动、列宽按内容、单元格可以换行),可以合并单元格。打印、导出预览、详情页里的明细表用它;\n * 要排序、勾选、筛选、十万行的用 DataTable。\n *\n * <ColumnTable rows={items} columns={columns} getKey={(item) => item.id} mergeRepeated={['supplier']} aria-label=\"报价明细\" />\n *\n * 合并单元格:mergeRepeated 写列的 key,这几列里上下相邻、值相同的格合成一格(后一列只在前一列的同一格里合并,层层分组);\n * 更灵活的用 cellSpan,返回 { rowSpan, colSpan },被合并掉的格返回 0(同 Ant Design 的 onCell)。合并的格垂直居中。\n *\n * 部件:Root(Table)、HeaderCell(th)、Row(tr)、Cell(td)、SummaryCell(表尾的 td)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { useLang } from '../config/context';\nimport { mergeProps, type PartProps } from '../utils/props';\nimport { useColumnDisplay } from './column-display';\nimport { columnType, columnValue, sumColumn, type DataTableColumn } from './columns';\nimport {\n Table,\n TableBody,\n TableCell,\n TableFoot,\n TableHead,\n TableHeaderCell,\n TableRow,\n type TableHeaderCellProps,\n type TableProps,\n} from './Table';\n\n/** 一格合并几行、几列;0 是被别的格合并掉(不渲染) */\nexport interface CellSpan {\n /** 往下合并几行,默认 1 */\n rowSpan?: number;\n /** 往后合并几列,默认 1 */\n colSpan?: number;\n}\n\n/** 列标题的部件属性:对齐与宽度跟随列定义 */\ntype HeaderCellParts = Partial<TableHeaderCellProps>;\n/** 单元格的部件属性:对齐跟随列定义,合并由 cellSpan、mergeRepeated 决定 */\ntype CellParts = PartProps<'td', 'align' | 'rowspan' | 'colspan'>;\n\n/** 未声明的属性落到 table 上;外观(density、variant、striped)同 Table */\nexport interface ColumnTableProps<T> extends Omit<TableProps, 'children'> {\n /** 数据 */\n rows: readonly T[];\n /** 列定义(与 DataTable 相同;sortable、filter、sticky、resizable 在这里不起作用) */\n columns: readonly DataTableColumn<T>[];\n /** 行的 key;不写时用下标 */\n getKey?: (row: T, index: number) => string;\n /** 这几列里上下相邻、值相同的格合成一格;后一列只在前一列的同一格里合并 */\n mergeRepeated?: readonly string[];\n /** 合并单元格:返回这一格合并几行、几列,被合并掉的返回 { rowSpan: 0 } 或 { colSpan: 0 } */\n cellSpan?: (row: T, column: DataTableColumn<T>, index: number) => CellSpan | undefined;\n /** 合计行第一列的文字(第一列自己没写 summary 时),默认取语言包(合计) */\n summaryLabel?: VNodeChild;\n /** 列标题(th)的部件属性,可以按列计算 */\n propsHeaderCell?: HeaderCellParts | ((column: DataTableColumn<T>) => HeaderCellParts);\n /** 每一行(tr)的部件属性,可以按行计算 */\n propsRow?: PartProps<'tr'> | ((row: T, index: number) => PartProps<'tr'>);\n /** 每个单元格(td)的部件属性,可以按行与列计算 */\n propsCell?: CellParts | ((row: T, column: DataTableColumn<T>) => CellParts);\n /** 合计行每个单元格的部件属性,可以按列计算 */\n propsSummaryCell?: CellParts | ((column: DataTableColumn<T>) => CellParts);\n}\n\n/** ColumnTable 的样式:merged */\nexport const columnTableStyles = css.create({\n // 合并的格跨了几行:内容垂直居中,下边线照常\n merged: { verticalAlign: 'middle' },\n});\n\n/**\n * mergeRepeated 的跨行数:每列一个数组,第 i 行是这一格往下合并几行,被合并掉的是 0。\n * 后一列在前一列的分组边界处断开(不把不同供应商下同名的品类合在一起)\n */\nexport function repeatedRowSpans<T>(\n rows: readonly T[],\n columns: readonly DataTableColumn<T>[],\n keys: readonly string[],\n): Map<string, number[]> {\n const spans = new Map<string, number[]>();\n // 上一列的分组从哪些行开始:本列的合并不能跨过它们\n let boundaries = new Set<number>([0]);\n for (const key of keys) {\n const column = columns.find((item) => item.key === key);\n if (!column) continue;\n const list = Array.from({ length: rows.length }, () => 1);\n const starts = new Set<number>();\n let start = 0;\n for (let index = 0; index < rows.length; index++) {\n const same =\n index > start &&\n !boundaries.has(index) &&\n String(columnValue(column, rows[index]!)) === String(columnValue(column, rows[start]!));\n if (same) {\n list[start]!++;\n list[index] = 0;\n } else {\n start = index;\n starts.add(index);\n }\n }\n spans.set(key, list);\n boundaries = new Set([...boundaries, ...starts]);\n }\n return spans;\n}\n\n/** 按列定义渲染的静态表格:格式化同 DataTable,可以合并单元格、带合计行 */\nexport const ColumnTable = _component(\n <T,>({\n rows,\n columns,\n getKey,\n mergeRepeated,\n cellSpan,\n summaryLabel,\n propsHeaderCell,\n propsRow,\n propsCell,\n propsSummaryCell,\n ...rest\n }: ColumnTableProps<T>) => {\n const lang = useLang();\n const display = useColumnDisplay<T>();\n const types = _derived(columns.map((column) => columnType(column, rows)));\n const shown = _derived(display.columns(columns, types));\n const merged = _derived(\n mergeRepeated?.length ? repeatedRowSpans(rows, columns, mergeRepeated) : null,\n );\n const hasSummary = _derived(columns.some((column) => column.summary != null));\n\n /** 一格的合并:cellSpan 优先,其次 mergeRepeated */\n function spanOf(row: T, column: DataTableColumn<T>, index: number): CellSpan | undefined {\n const own = cellSpan?.(row, column, index);\n if (own) return own;\n const rowSpan = merged?.get(column.key)?.[index];\n return rowSpan == null || rowSpan === 1 ? undefined : { rowSpan };\n }\n\n function summaryCell(column: DataTableColumn<T>, position: number): VNodeChild {\n if (column.summary === 'sum') {\n const total = sumColumn(column, rows);\n return total == null\n ? (column.empty ?? lang.emptyValue)\n : display.value(column, types[position]!, total);\n }\n if (column.summary) return column.summary(rows);\n return position === 0 ? (summaryLabel ?? lang.tableSummary) : null;\n }\n\n return () => (\n <Table {...rest}>\n <TableHead>\n <TableRow>\n {shown.map((column) => (\n <TableHeaderCell\n key={column.key}\n {...(typeof propsHeaderCell === 'function'\n ? propsHeaderCell(column)\n : propsHeaderCell)}\n align={column.align}\n width={column.width}\n >\n {column.header}\n </TableHeaderCell>\n ))}\n </TableRow>\n </TableHead>\n <TableBody>\n {rows.map((row, index) => (\n <TableRow\n key={getKey?.(row, index) ?? index}\n {...mergeProps<'tr'>(\n {},\n typeof propsRow === 'function' ? propsRow(row, index) : propsRow,\n )}\n >\n {shown.map((column) => {\n const span = spanOf(row, column, index);\n if (span?.rowSpan === 0 || span?.colSpan === 0) return null;\n const own = typeof propsCell === 'function' ? propsCell(row, column) : propsCell;\n return (\n <TableCell\n key={column.key}\n {...mergeProps<'td'>(\n { sx: span?.rowSpan ? columnTableStyles.merged : undefined },\n own,\n { rowspan: span?.rowSpan, colspan: span?.colSpan },\n )}\n align={column.align}\n nowrap={!column.wrap && column.width != null}\n >\n {column.cell!(row, index)}\n </TableCell>\n );\n })}\n </TableRow>\n ))}\n </TableBody>\n {hasSummary && (\n <TableFoot>\n <TableRow>\n {shown.map((column, position) => (\n <TableCell\n key={column.key}\n {...(typeof propsSummaryCell === 'function'\n ? propsSummaryCell(column)\n : propsSummaryCell)}\n align={column.align}\n >\n {summaryCell(column, position)}\n </TableCell>\n ))}\n </TableRow>\n </TableFoot>\n )}\n </Table>\n );\n },\n);\n"],"mappings":"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"}