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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (416) hide show
  1. package/dist/base/Badge.js +3 -3
  2. package/dist/base/Badge.js.map +1 -1
  3. package/dist/base/Can.d.ts +12 -0
  4. package/dist/base/Can.js +20 -0
  5. package/dist/base/Can.js.map +1 -0
  6. package/dist/base/ClientOnly.d.ts +10 -0
  7. package/dist/base/ClientOnly.js +18 -0
  8. package/dist/base/ClientOnly.js.map +1 -0
  9. package/dist/base/CloseButton.js +3 -3
  10. package/dist/base/CloseButton.js.map +1 -1
  11. package/dist/base/CodeBlock.js +5 -5
  12. package/dist/base/CodeBlock.js.map +1 -1
  13. package/dist/base/CopyButton.js +3 -3
  14. package/dist/base/CopyButton.js.map +1 -1
  15. package/dist/base/Icon.js +3 -3
  16. package/dist/base/Icon.js.map +1 -1
  17. package/dist/base/Indicator.js +3 -3
  18. package/dist/base/Indicator.js.map +1 -1
  19. package/dist/base/StatusDot.js +3 -3
  20. package/dist/base/StatusDot.js.map +1 -1
  21. package/dist/base/Tag.js +5 -5
  22. package/dist/base/Tag.js.map +1 -1
  23. package/dist/base/button-core.js +4 -4
  24. package/dist/base/button-core.js.map +1 -1
  25. package/dist/charts/AreaChart.js +3 -3
  26. package/dist/charts/AreaChart.js.map +1 -1
  27. package/dist/charts/BarChart.js +3 -3
  28. package/dist/charts/BarChart.js.map +1 -1
  29. package/dist/charts/ChordChart.js +3 -3
  30. package/dist/charts/ChordChart.js.map +1 -1
  31. package/dist/charts/ComboChart.js +3 -3
  32. package/dist/charts/ComboChart.js.map +1 -1
  33. package/dist/charts/DonutChart.js +3 -3
  34. package/dist/charts/DonutChart.js.map +1 -1
  35. package/dist/charts/FunnelChart.js +5 -5
  36. package/dist/charts/FunnelChart.js.map +1 -1
  37. package/dist/charts/GraphChart.js +3 -3
  38. package/dist/charts/GraphChart.js.map +1 -1
  39. package/dist/charts/LineChart.js +3 -3
  40. package/dist/charts/LineChart.js.map +1 -1
  41. package/dist/charts/MapChart.js +7 -7
  42. package/dist/charts/MapChart.js.map +1 -1
  43. package/dist/charts/RadarChart.js +16 -15
  44. package/dist/charts/RadarChart.js.map +1 -1
  45. package/dist/charts/SankeyChart.js +3 -3
  46. package/dist/charts/SankeyChart.js.map +1 -1
  47. package/dist/charts/ScatterChart.js +3 -3
  48. package/dist/charts/ScatterChart.js.map +1 -1
  49. package/dist/charts/TimelineChart.js +6 -5
  50. package/dist/charts/TimelineChart.js.map +1 -1
  51. package/dist/charts/TreemapChart.js +3 -3
  52. package/dist/charts/TreemapChart.js.map +1 -1
  53. package/dist/charts/WaterfallChart.js +3 -3
  54. package/dist/charts/WaterfallChart.js.map +1 -1
  55. package/dist/charts/XYChart.js +9 -7
  56. package/dist/charts/XYChart.js.map +1 -1
  57. package/dist/charts/frame.js +10 -8
  58. package/dist/charts/frame.js.map +1 -1
  59. package/dist/charts/single.js +4 -3
  60. package/dist/charts/single.js.map +1 -1
  61. package/dist/config/Provider.d.ts +3 -1
  62. package/dist/config/Provider.js +9 -4
  63. package/dist/config/Provider.js.map +1 -1
  64. package/dist/config/context.d.ts +18 -0
  65. package/dist/config/context.js +16 -1
  66. package/dist/config/context.js.map +1 -1
  67. package/dist/config/createUi.d.ts +20 -3
  68. package/dist/config/createUi.js +80 -49
  69. package/dist/config/createUi.js.map +1 -1
  70. package/dist/config/layout/preference.d.ts +43 -0
  71. package/dist/config/layout/preference.js +108 -0
  72. package/dist/config/layout/preference.js.map +1 -0
  73. package/dist/date/Calendar.js +3 -3
  74. package/dist/date/Calendar.js.map +1 -1
  75. package/dist/date/CalendarBoard.js +9 -9
  76. package/dist/date/CalendarBoard.js.map +1 -1
  77. package/dist/date/CalendarView.js +7 -7
  78. package/dist/date/CalendarView.js.map +1 -1
  79. package/dist/date/DateField.js +3 -3
  80. package/dist/date/DateField.js.map +1 -1
  81. package/dist/date/DatePicker.js +5 -5
  82. package/dist/date/DatePicker.js.map +1 -1
  83. package/dist/date/DateRangePicker.js +5 -5
  84. package/dist/date/DateRangePicker.js.map +1 -1
  85. package/dist/date/DateSegmentGroup.js +5 -5
  86. package/dist/date/DateSegmentGroup.js.map +1 -1
  87. package/dist/date/QuarterCalendar.js +6 -6
  88. package/dist/date/QuarterCalendar.js.map +1 -1
  89. package/dist/date/RangeCalendar.js +3 -3
  90. package/dist/date/RangeCalendar.js.map +1 -1
  91. package/dist/date/SegmentedField.js +3 -3
  92. package/dist/date/SegmentedField.js.map +1 -1
  93. package/dist/date/TimeField.js +3 -3
  94. package/dist/date/TimeField.js.map +1 -1
  95. package/dist/date/TimePicker.js +4 -4
  96. package/dist/date/TimePicker.js.map +1 -1
  97. package/dist/date/date-segments.js +1 -1
  98. package/dist/date/date-segments.js.map +1 -1
  99. package/dist/date/picker-popover.js +3 -2
  100. package/dist/date/picker-popover.js.map +1 -1
  101. package/dist/diagram/Diagram.js +12 -12
  102. package/dist/diagram/Diagram.js.map +1 -1
  103. package/dist/diagram/DiagramLanes.js +3 -3
  104. package/dist/diagram/DiagramLanes.js.map +1 -1
  105. package/dist/diagram/DiagramMinimap.js +4 -4
  106. package/dist/diagram/DiagramMinimap.js.map +1 -1
  107. package/dist/display/Accordion.js +6 -6
  108. package/dist/display/Accordion.js.map +1 -1
  109. package/dist/display/AnimatedNumber.js +4 -4
  110. package/dist/display/AnimatedNumber.js.map +1 -1
  111. package/dist/display/Avatar.js +4 -4
  112. package/dist/display/Avatar.js.map +1 -1
  113. package/dist/display/Checklist.js +7 -7
  114. package/dist/display/Checklist.js.map +1 -1
  115. package/dist/display/Collapse.js +8 -5
  116. package/dist/display/Collapse.js.map +1 -1
  117. package/dist/display/Collapsible.js +3 -3
  118. package/dist/display/Collapsible.js.map +1 -1
  119. package/dist/display/Descriptions.js +5 -5
  120. package/dist/display/Descriptions.js.map +1 -1
  121. package/dist/display/Ellipsis.js +3 -3
  122. package/dist/display/Ellipsis.js.map +1 -1
  123. package/dist/display/FieldCompare.js +4 -4
  124. package/dist/display/FieldCompare.js.map +1 -1
  125. package/dist/display/Gauge.js +11 -11
  126. package/dist/display/Gauge.js.map +1 -1
  127. package/dist/display/Image.js +4 -4
  128. package/dist/display/Image.js.map +1 -1
  129. package/dist/display/Marquee.js +3 -3
  130. package/dist/display/Marquee.js.map +1 -1
  131. package/dist/display/ProportionBar.js +4 -4
  132. package/dist/display/ProportionBar.js.map +1 -1
  133. package/dist/display/Sortable.js +4 -4
  134. package/dist/display/Sortable.js.map +1 -1
  135. package/dist/display/Sparkline.js +6 -6
  136. package/dist/display/Sparkline.js.map +1 -1
  137. package/dist/display/Stat.js +3 -3
  138. package/dist/display/Stat.js.map +1 -1
  139. package/dist/display/Timeline.js +7 -7
  140. package/dist/display/Timeline.js.map +1 -1
  141. package/dist/display/Tree.js +10 -10
  142. package/dist/display/Tree.js.map +1 -1
  143. package/dist/display/VirtualList.js +7 -7
  144. package/dist/display/VirtualList.js.map +1 -1
  145. package/dist/display/Watermark.js +3 -3
  146. package/dist/display/Watermark.js.map +1 -1
  147. package/dist/docs-kit/CodeGroup.js +5 -5
  148. package/dist/docs-kit/CodeGroup.js.map +1 -1
  149. package/dist/docs-kit/CodePreview.js +6 -6
  150. package/dist/docs-kit/CodePreview.js.map +1 -1
  151. package/dist/docs-kit/PropsTable.js +4 -4
  152. package/dist/docs-kit/PropsTable.js.map +1 -1
  153. package/dist/feedback/Alert.js +5 -5
  154. package/dist/feedback/Alert.js.map +1 -1
  155. package/dist/feedback/Banner.js +5 -5
  156. package/dist/feedback/Banner.js.map +1 -1
  157. package/dist/feedback/Empty.js +4 -4
  158. package/dist/feedback/Empty.js.map +1 -1
  159. package/dist/feedback/LoadingBar.js +20 -13
  160. package/dist/feedback/LoadingBar.js.map +1 -1
  161. package/dist/feedback/LoadingOverlay.js +3 -3
  162. package/dist/feedback/LoadingOverlay.js.map +1 -1
  163. package/dist/feedback/Progress.js +14 -14
  164. package/dist/feedback/Progress.js.map +1 -1
  165. package/dist/feedback/Result.js +4 -4
  166. package/dist/feedback/Result.js.map +1 -1
  167. package/dist/feedback/SkeletonText.js +3 -3
  168. package/dist/feedback/SkeletonText.js.map +1 -1
  169. package/dist/feedback/Toast.js +6 -6
  170. package/dist/feedback/Toast.js.map +1 -1
  171. package/dist/form/Field.js +7 -7
  172. package/dist/form/Field.js.map +1 -1
  173. package/dist/form/Form.js +3 -3
  174. package/dist/form/Form.js.map +1 -1
  175. package/dist/form/FormErrorSummary.js +3 -3
  176. package/dist/form/FormErrorSummary.js.map +1 -1
  177. package/dist/form/FormSection.js +6 -6
  178. package/dist/form/FormSection.js.map +1 -1
  179. package/dist/index.d.ts +11 -6
  180. package/dist/index.js +10 -5
  181. package/dist/input/Autocomplete.js +3 -3
  182. package/dist/input/Autocomplete.js.map +1 -1
  183. package/dist/input/Cascader.js +7 -7
  184. package/dist/input/Cascader.js.map +1 -1
  185. package/dist/input/CharacterCount.js +3 -3
  186. package/dist/input/CharacterCount.js.map +1 -1
  187. package/dist/input/Checkbox.js +5 -5
  188. package/dist/input/Checkbox.js.map +1 -1
  189. package/dist/input/ColorField.js +4 -4
  190. package/dist/input/ColorField.js.map +1 -1
  191. package/dist/input/Combobox.js +4 -4
  192. package/dist/input/Combobox.js.map +1 -1
  193. package/dist/input/ConditionBuilder.js +15 -14
  194. package/dist/input/ConditionBuilder.js.map +1 -1
  195. package/dist/input/FileDrop.js +3 -3
  196. package/dist/input/FileDrop.js.map +1 -1
  197. package/dist/input/Listbox.js +9 -9
  198. package/dist/input/Listbox.js.map +1 -1
  199. package/dist/input/Mentions.js +3 -3
  200. package/dist/input/Mentions.js.map +1 -1
  201. package/dist/input/NumberField.js +3 -3
  202. package/dist/input/NumberField.js.map +1 -1
  203. package/dist/input/NumberRangeField.js +5 -5
  204. package/dist/input/NumberRangeField.js.map +1 -1
  205. package/dist/input/OtpField.js +5 -5
  206. package/dist/input/OtpField.js.map +1 -1
  207. package/dist/input/PeoplePicker.js +6 -6
  208. package/dist/input/PeoplePicker.js.map +1 -1
  209. package/dist/input/PeoplePickerPanel.js +4 -4
  210. package/dist/input/PeoplePickerPanel.js.map +1 -1
  211. package/dist/input/Radio.js +4 -4
  212. package/dist/input/Radio.js.map +1 -1
  213. package/dist/input/Rating.js +5 -5
  214. package/dist/input/Rating.js.map +1 -1
  215. package/dist/input/Select.js +4 -4
  216. package/dist/input/Select.js.map +1 -1
  217. package/dist/input/SelectedTags.js +4 -4
  218. package/dist/input/SelectedTags.js.map +1 -1
  219. package/dist/input/Slider.js +6 -6
  220. package/dist/input/Slider.js.map +1 -1
  221. package/dist/input/Switch.js +3 -3
  222. package/dist/input/Switch.js.map +1 -1
  223. package/dist/input/TagsInput.js +5 -5
  224. package/dist/input/TagsInput.js.map +1 -1
  225. package/dist/input/TextField.js +5 -5
  226. package/dist/input/TextField.js.map +1 -1
  227. package/dist/input/Textarea.js +4 -4
  228. package/dist/input/Textarea.js.map +1 -1
  229. package/dist/input/ToggleGroup.js +4 -4
  230. package/dist/input/ToggleGroup.js.map +1 -1
  231. package/dist/input/Transfer.js +8 -8
  232. package/dist/input/Transfer.js.map +1 -1
  233. package/dist/input/TreeSelect.js +6 -6
  234. package/dist/input/TreeSelect.js.map +1 -1
  235. package/dist/input/Upload.js +8 -8
  236. package/dist/input/Upload.js.map +1 -1
  237. package/dist/layout/Affix.js +4 -4
  238. package/dist/layout/Affix.js.map +1 -1
  239. package/dist/layout/ResizeHandle.d.ts +6 -2
  240. package/dist/layout/ResizeHandle.js +32 -9
  241. package/dist/layout/ResizeHandle.js.map +1 -1
  242. package/dist/layout/ScrollArea.js +3 -3
  243. package/dist/layout/ScrollArea.js.map +1 -1
  244. package/dist/layout/Separator.js +3 -3
  245. package/dist/layout/Separator.js.map +1 -1
  246. package/dist/layout/Splitter.js +3 -3
  247. package/dist/layout/Splitter.js.map +1 -1
  248. package/dist/layout/ViewportFill.d.ts +2 -2
  249. package/dist/layout/ViewportFill.js +4 -4
  250. package/dist/layout/ViewportFill.js.map +1 -1
  251. package/dist/navigation/Breadcrumbs.js +4 -4
  252. package/dist/navigation/Breadcrumbs.js.map +1 -1
  253. package/dist/navigation/NavBar.js +6 -6
  254. package/dist/navigation/NavBar.js.map +1 -1
  255. package/dist/navigation/NavList.d.ts +1 -0
  256. package/dist/navigation/NavList.js +20 -12
  257. package/dist/navigation/NavList.js.map +1 -1
  258. package/dist/navigation/NavMenu.d.ts +27 -0
  259. package/dist/navigation/NavMenu.js +54 -0
  260. package/dist/navigation/NavMenu.js.map +1 -0
  261. package/dist/navigation/PageJump.js +3 -3
  262. package/dist/navigation/PageJump.js.map +1 -1
  263. package/dist/navigation/PageSizeSelect.js +4 -4
  264. package/dist/navigation/PageSizeSelect.js.map +1 -1
  265. package/dist/navigation/Pagination.js +6 -6
  266. package/dist/navigation/Pagination.js.map +1 -1
  267. package/dist/navigation/PaginationBar.js +5 -5
  268. package/dist/navigation/PaginationBar.js.map +1 -1
  269. package/dist/navigation/Steps.js +4 -4
  270. package/dist/navigation/Steps.js.map +1 -1
  271. package/dist/navigation/TableOfContents.js +5 -5
  272. package/dist/navigation/TableOfContents.js.map +1 -1
  273. package/dist/navigation/Tabs.js +7 -7
  274. package/dist/navigation/Tabs.js.map +1 -1
  275. package/dist/navigation/Toolbar.js +3 -3
  276. package/dist/navigation/Toolbar.js.map +1 -1
  277. package/dist/overlay/AlertDialog.js +4 -4
  278. package/dist/overlay/AlertDialog.js.map +1 -1
  279. package/dist/overlay/CommandPalette.js +4 -4
  280. package/dist/overlay/CommandPalette.js.map +1 -1
  281. package/dist/overlay/ContextMenu.js +3 -3
  282. package/dist/overlay/ContextMenu.js.map +1 -1
  283. package/dist/overlay/Dialog.js +4 -4
  284. package/dist/overlay/Dialog.js.map +1 -1
  285. package/dist/overlay/Drawer.js +5 -5
  286. package/dist/overlay/Drawer.js.map +1 -1
  287. package/dist/overlay/HoverCard.js +5 -3
  288. package/dist/overlay/HoverCard.js.map +1 -1
  289. package/dist/overlay/Lightbox.js +5 -5
  290. package/dist/overlay/Lightbox.js.map +1 -1
  291. package/dist/overlay/Menu.js +7 -7
  292. package/dist/overlay/Menu.js.map +1 -1
  293. package/dist/overlay/ModalCore.js +9 -9
  294. package/dist/overlay/ModalCore.js.map +1 -1
  295. package/dist/overlay/Popconfirm.js +6 -6
  296. package/dist/overlay/Popconfirm.js.map +1 -1
  297. package/dist/overlay/Popover.js +5 -3
  298. package/dist/overlay/Popover.js.map +1 -1
  299. package/dist/overlay/Tooltip.js +5 -3
  300. package/dist/overlay/Tooltip.js.map +1 -1
  301. package/dist/overlay/Tour.js +8 -8
  302. package/dist/overlay/Tour.js.map +1 -1
  303. package/dist/overlay/detached.d.ts +2 -0
  304. package/dist/overlay/detached.js +73 -42
  305. package/dist/overlay/detached.js.map +1 -1
  306. package/dist/patterns/ActionBar.js +3 -3
  307. package/dist/patterns/ActionBar.js.map +1 -1
  308. package/dist/patterns/AppShell.d.ts +28 -1
  309. package/dist/patterns/AppShell.js +158 -52
  310. package/dist/patterns/AppShell.js.map +1 -1
  311. package/dist/patterns/AuthLayout.d.ts +28 -0
  312. package/dist/patterns/AuthLayout.js +77 -0
  313. package/dist/patterns/AuthLayout.js.map +1 -0
  314. package/dist/patterns/CommentThread.js +9 -9
  315. package/dist/patterns/CommentThread.js.map +1 -1
  316. package/dist/patterns/DataImport.js +4 -4
  317. package/dist/patterns/DataImport.js.map +1 -1
  318. package/dist/patterns/DeadlineBadge.js +3 -3
  319. package/dist/patterns/DeadlineBadge.js.map +1 -1
  320. package/dist/patterns/FilterBar.d.ts +11 -1
  321. package/dist/patterns/FilterBar.js +39 -10
  322. package/dist/patterns/FilterBar.js.map +1 -1
  323. package/dist/patterns/FormDialog.d.ts +18 -0
  324. package/dist/patterns/FormDialog.js +46 -0
  325. package/dist/patterns/FormDialog.js.map +1 -0
  326. package/dist/patterns/KanbanBoard.js +8 -8
  327. package/dist/patterns/KanbanBoard.js.map +1 -1
  328. package/dist/patterns/LayoutSwitcher.d.ts +12 -0
  329. package/dist/patterns/LayoutSwitcher.js +79 -0
  330. package/dist/patterns/LayoutSwitcher.js.map +1 -0
  331. package/dist/patterns/NotificationCenter.js +8 -8
  332. package/dist/patterns/NotificationCenter.js.map +1 -1
  333. package/dist/patterns/PageTabs.d.ts +12 -7
  334. package/dist/patterns/PageTabs.js +41 -29
  335. package/dist/patterns/PageTabs.js.map +1 -1
  336. package/dist/patterns/QueryTable.d.ts +7 -1
  337. package/dist/patterns/QueryTable.js +116 -81
  338. package/dist/patterns/QueryTable.js.map +1 -1
  339. package/dist/patterns/SlideCaptcha.d.ts +80 -0
  340. package/dist/patterns/SlideCaptcha.js +354 -0
  341. package/dist/patterns/SlideCaptcha.js.map +1 -0
  342. package/dist/patterns/StepsForm.js +7 -7
  343. package/dist/patterns/StepsForm.js.map +1 -1
  344. package/dist/patterns/ThemeSwitcher.js +3 -3
  345. package/dist/patterns/ThemeSwitcher.js.map +1 -1
  346. package/dist/patterns/index.d.ts +7 -3
  347. package/dist/patterns/index.js +5 -1
  348. package/dist/patterns/messages.d.ts +37 -1
  349. package/dist/patterns/messages.js +38 -2
  350. package/dist/patterns/messages.js.map +1 -1
  351. package/dist/table/ColumnHeaderActions.js +3 -3
  352. package/dist/table/ColumnHeaderActions.js.map +1 -1
  353. package/dist/table/ColumnResizer.js +3 -3
  354. package/dist/table/ColumnResizer.js.map +1 -1
  355. package/dist/table/ColumnSettings.js +5 -5
  356. package/dist/table/ColumnSettings.js.map +1 -1
  357. package/dist/table/ColumnTable.js +8 -8
  358. package/dist/table/ColumnTable.js.map +1 -1
  359. package/dist/table/DataTable.js +8 -8
  360. package/dist/table/DataTable.js.map +1 -1
  361. package/dist/table/DataTableView.js +21 -21
  362. package/dist/table/DataTableView.js.map +1 -1
  363. package/dist/table/PivotTable.js +3 -3
  364. package/dist/table/PivotTable.js.map +1 -1
  365. package/dist/table/SelectionBar.js +4 -4
  366. package/dist/table/SelectionBar.js.map +1 -1
  367. package/dist/table/TreeDataTable.js +5 -5
  368. package/dist/table/TreeDataTable.js.map +1 -1
  369. package/dist/theme-customize/ThemeCustomizer.js +7 -6
  370. package/dist/theme-customize/ThemeCustomizer.js.map +1 -1
  371. package/dist/theme-customize/ThemeThumbnail.js +3 -3
  372. package/dist/theme-customize/ThemeThumbnail.js.map +1 -1
  373. package/dist/three/background/AuroraBackground.js +3 -3
  374. package/dist/three/background/AuroraBackground.js.map +1 -1
  375. package/dist/three/background/MeshGradient.js +3 -3
  376. package/dist/three/background/MeshGradient.js.map +1 -1
  377. package/dist/three/background/ShaderBackground.js +3 -3
  378. package/dist/three/background/ShaderBackground.js.map +1 -1
  379. package/dist/three/core/EffectSurface.js +3 -3
  380. package/dist/three/core/EffectSurface.js.map +1 -1
  381. package/dist/three/core/ThreeCanvas.js +4 -4
  382. package/dist/three/core/ThreeCanvas.js.map +1 -1
  383. package/dist/three/effects/Confetti.js +3 -3
  384. package/dist/three/effects/Confetti.js.map +1 -1
  385. package/dist/three/effects/ParticleField.js +3 -3
  386. package/dist/three/effects/ParticleField.js.map +1 -1
  387. package/dist/three/effects/WaveGrid.js +3 -3
  388. package/dist/three/effects/WaveGrid.js.map +1 -1
  389. package/dist/three/globe/Globe.js +3 -3
  390. package/dist/three/globe/Globe.js.map +1 -1
  391. package/dist/three/model/ModelViewer.js +3 -3
  392. package/dist/three/model/ModelViewer.js.map +1 -1
  393. package/dist/utils/data/number.d.ts +5 -0
  394. package/dist/utils/data/number.js +8 -1
  395. package/dist/utils/data/number.js.map +1 -1
  396. package/dist/utils/dom/element.d.ts +3 -1
  397. package/dist/utils/dom/element.js +8 -4
  398. package/dist/utils/dom/element.js.map +1 -1
  399. package/dist/utils/dom/fullscreen.d.ts +1 -1
  400. package/dist/utils/dom/fullscreen.js +12 -8
  401. package/dist/utils/dom/fullscreen.js.map +1 -1
  402. package/dist/utils/dom/mounted.d.ts +7 -0
  403. package/dist/utils/dom/mounted.js +16 -0
  404. package/dist/utils/dom/mounted.js.map +1 -0
  405. package/dist/utils/dom/overflow.js +2 -1
  406. package/dist/utils/dom/overflow.js.map +1 -1
  407. package/dist/utils/dom/pan-zoom.js +2 -1
  408. package/dist/utils/dom/pan-zoom.js.map +1 -1
  409. package/dist/utils/props.js +3 -13
  410. package/dist/utils/props.js.map +1 -1
  411. package/dist/utils/request/http.d.ts +12 -0
  412. package/dist/utils/request/http.js +6 -2
  413. package/dist/utils/request/http.js.map +1 -1
  414. package/dist/utils/request/use-request.js +4 -2
  415. package/dist/utils/request/use-request.js.map +1 -1
  416. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"SelectionBar.js","names":["_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_vtp_untrack","_createVNode","_mergeProps"],"sources":["../../src/table/SelectionBar.tsx"],"sourcesContent":["/**\n * 批量操作栏(div):表格勾选了行之后出现在表格上方,“已选 N 项 · 取消选择”,结束边是批量操作。\n *\n * <SelectionBar count={selected.length} onClear={() => (selected = [])}>\n * <Button size=\"sm\" variant=\"outline\" tone=\"neutral\">批量导出</Button>\n * <Button size=\"sm\" tone=\"danger\" variant=\"soft\">批量删除</Button>\n * </SelectionBar>\n *\n * count 为 0 时不显示(淡出);已选的数目在读屏的播报区里,勾选变化时念出来。\n * 部件:Root(div)、Count(span)、Clear(Button)、Actions(div)。数目变化经共用的播报区(announce)念出。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { watch, type VNodeChild } from 'vue';\nimport { Button, type ButtonProps } from '../base/Button';\nimport { useLang } from '../config/context';\nimport { announce } from '../utils/dom/announcer';\nimport { usePresence } from '../utils/motion/presence';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { presenceStyles } from '../utils/style/transitions';\n\n/** 未声明的属性落到外层 div 上 */\nexport interface SelectionBarProps extends PartProps<'div'> {\n /** 已选几项;0 时不显示 */\n count: number;\n /** 点“取消选择”:清空选择由使用方做 */\n onClear?: () => void;\n /** 已选数目的文字,默认取语言包(已选 N 项):跨页全选时写“已选全部 1,286 项” */\n label?: VNodeChild;\n /** 已选数目的部件属性 */\n propsCount?: PartProps<'span'>;\n /** 取消选择按钮的部件属性 */\n propsClear?: Partial<ButtonProps>;\n /** 批量操作区的部件属性 */\n propsActions?: PartProps<'div'>;\n /** 批量操作的按钮 */\n children?: VNodeChild;\n}\n\n/** SelectionBar 的样式:root、count、actions */\nexport const selectionBarStyles = css.create({\n root: {\n display: 'flex',\n alignItems: 'center',\n flexWrap: 'wrap',\n gap: '_md',\n minHeight: '_control',\n paddingBlock: '_xs',\n paddingInline: '_md',\n borderRadius: '_md',\n backgroundColor: '_accentSoft',\n color: '_text',\n fontSize: '_sm',\n },\n count: { fontWeight: '_semibold', color: '_accentText', fontVariantNumeric: 'tabular-nums' },\n actions: {\n display: 'flex',\n alignItems: 'center',\n flexWrap: 'wrap',\n gap: '_sm',\n marginInlineStart: 'auto',\n },\n});\n\n/** 批量操作栏:已选几项、取消选择、批量操作;没有选择时淡出 */\nexport const SelectionBar = _component(\n ({\n count,\n onClear,\n label,\n propsCount,\n propsClear,\n propsActions,\n children,\n ...rest\n }: SelectionBarProps) => {\n const lang = useLang();\n // 数目变了给读屏播报:栏是随第一次选择一起出现的,挂在它里面的 aria-live 区域第一句念不出来\n // 给了文字的 label(“已选全部 1,286 项”)就念它\n watch(\n () => [count, label] as const,\n ([next, text]) => announce(typeof text === 'string' ? text : lang.tableSelectedCount(next)),\n );\n // 数目变成 0 后等淡出结束再卸载;淡出时仍显示最后的数目,不闪成“已选 0 项”\n const presence = usePresence(() => count > 0);\n let shownCount = _untrack(count);\n return () => {\n if (count > 0) shownCount = count;\n return (\n presence.mounted && (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n selectionBarStyles.root,\n presenceStyles.fade,\n presence.state === 'closed' && presenceStyles.leaving,\n ],\n },\n rest,\n { ref: presence.ref },\n )}\n data-state={presence.state}\n >\n <span {...mergeAttrs<'span'>({ sx: selectionBarStyles.count }, propsCount)}>\n {label ?? lang.tableSelectedCount(shownCount)}\n </span>\n <Button\n {...mergePartProps<ButtonProps>({ variant: 'link', size: 'sm' }, propsClear, {\n onClick: () => onClear?.(),\n })}\n >\n {lang.tableClearSelection}\n </Button>\n <div {...mergeAttrs<'div'>({ sx: selectionBarStyles.actions }, propsActions)}>\n {children}\n </div>\n </div>\n )\n );\n };\n },\n);\n"],"mappings":";;;;;;;;;;;;AAwCA,IAAa,qBAAqB,IAAI,OAAO;CAC3C,MAAM;EACJ,SAAS;EACT,YAAY;EACZ,UAAU;EACV,KAAK;EACL,WAAW;EACX,cAAc;EACd,eAAe;EACf,cAAc;EACd,iBAAiB;EACjB,OAAO;EACP,UAAU;CACZ;CACA,OAAO;EAAE,YAAY;EAAa,OAAO;EAAe,oBAAoB;CAAe;CAC3F,SAAS;EACP,SAAS;EACT,YAAY;EACZ,UAAU;EACV,KAAK;EACL,mBAAmB;CACrB;AACF,CAAC;;AAGD,IAAa,eAAe,0BAC1B,QAAA,SASyB;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,UAAAA,aAAA,QAAA,SAAA;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,aAAAA,aAAA,QAAA,YAAA;CAAA,MAAA,aAAAA,aAAA,QAAA,YAAA;CAAA,MAAA,eAAAA,aAAA,QAAA,cAAA;CAAA,MAAA,WAAAC,aAAA,MAAA;CAAA,MADpB,OAAIC,UAAA,QAAA,MAAA,KAAA;CAEP,MAAM,OAAO,QAAQ;CAGrB,YACQ,CAAA,MAAA,OAAA,MAAA,KAAA,IACL,CAAC,MAAM,UAAU,SAAS,OAAO,SAAS,WAAW,OAAO,KAAK,mBAAmB,IAAI,CAAC,CAC5F;CAEA,MAAM,WAAW,kBAAkB,MAAA,QAAQ,CAAC;CAC5C,IAAI,aAAUC,cAAA,MAAA,KAAA;CACd,aAAa;EACX,IAAI,MAAA,QAAQ,GAAG,aAAU,MAAA;EACzB,OACE,SAAS,WAAOC,YAAA,OAAAC,WAER,WACF,EACE,IAAI;GACF,mBAAmB;GACnB,eAAe;GACf,SAAS,UAAU,YAAY,eAAe;EAAO,EAEzD,GACA,MACA,EAAE,KAAK,SAAS,IAAI,CACtB,GAAC,EAAA,cACW,SAAS,MAAK,CAAA,GAAA;GAAAD,YAAA,QAEhB,WAAmB,EAAE,IAAI,mBAAmB,MAAM,GAAC,WAAA,KAAY,GAAC,CACvE,MAAA,SAAS,KAAK,mBAAmB,UAAU,CAAC,CAAA;GAAAA,YAAA,QAAAC,WAGzC,eAA4B;IAAE,SAAS;IAAQ,MAAM;GAAK,GAAC,WAAA,OAAc,EAC3E,eAAe,QAAA,QAAU,EAC3B,CAAC,GAAC,EAAA,OAAA,UAAA,CAAA,GAAA;IAAA,eAAA,CAED,KAAK,mBAAmB;IAAA,SAAA;GAAA,CAAA;GAAAD,YAAA,OAElB,WAAkB,EAAE,IAAI,mBAAmB,QAAQ,GAAC,aAAA,KAAc,GAAC,CAAA,SAAA,KAAA,CAAA;EAAA,CAAA;CAMpF;AACF,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
1
+ {"version":3,"file":"SelectionBar.js","names":["_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_vtp_untrack","_createVNode","_mergeProps"],"sources":["../../src/table/SelectionBar.tsx"],"sourcesContent":["/**\n * 批量操作栏(div):表格勾选了行之后出现在表格上方,“已选 N 项 · 取消选择”,结束边是批量操作。\n *\n * <SelectionBar count={selected.length} onClear={() => (selected = [])}>\n * <Button size=\"sm\" variant=\"outline\" tone=\"neutral\">批量导出</Button>\n * <Button size=\"sm\" tone=\"danger\" variant=\"soft\">批量删除</Button>\n * </SelectionBar>\n *\n * count 为 0 时不显示(淡出);已选的数目在读屏的播报区里,勾选变化时念出来。\n * 部件:Root(div)、Count(span)、Clear(Button)、Actions(div)。数目变化经共用的播报区(announce)念出。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { watch, type VNodeChild } from 'vue';\nimport { Button, type ButtonProps } from '../base/Button';\nimport { useLang } from '../config/context';\nimport { announce } from '../utils/dom/announcer';\nimport { usePresence } from '../utils/motion/presence';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { presenceStyles } from '../utils/style/transitions';\n\n/** 未声明的属性落到外层 div 上 */\nexport interface SelectionBarProps extends PartProps<'div'> {\n /** 已选几项;0 时不显示 */\n count: number;\n /** 点“取消选择”:清空选择由使用方做 */\n onClear?: () => void;\n /** 已选数目的文字,默认取语言包(已选 N 项):跨页全选时写“已选全部 1,286 项” */\n label?: VNodeChild;\n /** 已选数目的部件属性 */\n propsCount?: PartProps<'span'>;\n /** 取消选择按钮的部件属性 */\n propsClear?: Partial<ButtonProps>;\n /** 批量操作区的部件属性 */\n propsActions?: PartProps<'div'>;\n /** 批量操作的按钮 */\n children?: VNodeChild;\n}\n\n/** SelectionBar 的样式:root、count、actions */\nexport const selectionBarStyles = css.create({\n root: {\n display: 'flex',\n alignItems: 'center',\n flexWrap: 'wrap',\n gap: '_md',\n minHeight: '_control',\n paddingBlock: '_xs',\n paddingInline: '_md',\n borderRadius: '_md',\n backgroundColor: '_accentSoft',\n color: '_text',\n fontSize: '_sm',\n },\n count: { fontWeight: '_semibold', color: '_accentText', fontVariantNumeric: 'tabular-nums' },\n actions: {\n display: 'flex',\n alignItems: 'center',\n flexWrap: 'wrap',\n gap: '_sm',\n marginInlineStart: 'auto',\n },\n});\n\n/** 批量操作栏:已选几项、取消选择、批量操作;没有选择时淡出 */\nexport const SelectionBar = _component(\n ({\n count,\n onClear,\n label,\n propsCount,\n propsClear,\n propsActions,\n children,\n ...rest\n }: SelectionBarProps) => {\n const lang = useLang();\n // 数目变了给读屏播报:栏是随第一次选择一起出现的,挂在它里面的 aria-live 区域第一句念不出来\n // 给了文字的 label(“已选全部 1,286 项”)就念它\n watch(\n () => [count, label] as const,\n ([next, text]) => announce(typeof text === 'string' ? text : lang.tableSelectedCount(next)),\n );\n // 数目变成 0 后等淡出结束再卸载;淡出时仍显示最后的数目,不闪成“已选 0 项”\n const presence = usePresence(() => count > 0);\n let shownCount = _untrack(count);\n return () => {\n if (count > 0) shownCount = count;\n return (\n presence.mounted && (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n selectionBarStyles.root,\n presenceStyles.fade,\n presence.state === 'closed' && presenceStyles.leaving,\n ],\n },\n rest,\n { ref: presence.ref },\n )}\n data-state={presence.state}\n >\n <span {...mergeAttrs<'span'>({ sx: selectionBarStyles.count }, propsCount)}>\n {label ?? lang.tableSelectedCount(shownCount)}\n </span>\n <Button\n {...mergePartProps<ButtonProps>({ variant: 'link', size: 'sm' }, propsClear, {\n onClick: () => onClear?.(),\n })}\n >\n {lang.tableClearSelection}\n </Button>\n <div {...mergeAttrs<'div'>({ sx: selectionBarStyles.actions }, propsActions)}>\n {children}\n </div>\n </div>\n )\n );\n };\n },\n);\n"],"mappings":";;;;;;;;;;;;AAwCA,IAAa,qBAAqB,IAAI,OAAO;CAC3C,MAAM;EACJ,SAAS;EACT,YAAY;EACZ,UAAU;EACV,KAAK;EACL,WAAW;EACX,cAAc;EACd,eAAe;EACf,cAAc;EACd,iBAAiB;EACjB,OAAO;EACP,UAAU;CACZ;CACA,OAAO;EAAE,YAAY;EAAa,OAAO;EAAe,oBAAoB;CAAe;CAC3F,SAAS;EACP,SAAS;EACT,YAAY;EACZ,UAAU;EACV,KAAK;EACL,mBAAmB;CACrB;AACF,CAAC;;AAGD,IAAa,eAAe,0BAC1B,QAAA,SASyB;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,UAAAA,aAAA,QAAA,SAAA;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,aAAAA,aAAA,QAAA,YAAA;CAAA,MAAA,aAAAA,aAAA,QAAA,YAAA;CAAA,MAAA,eAAAA,aAAA,QAAA,cAAA;CAAA,MAAA,WAAAC,aAAA,MAAA;CAAA,MADpB,OAAIC,UAAA,QAAA,MAAA,KAAA;CAEP,MAAM,OAAO,QAAQ;CAGrB,YACQ,CAAA,MAAA,OAAA,MAAA,KAAA,IACL,CAAC,MAAM,UAAU,SAAS,OAAO,SAAS,WAAW,OAAO,KAAK,mBAAmB,IAAI,CAAC,CAC5F;CAEA,MAAM,WAAW,kBAAkB,MAAA,QAAQ,CAAC;CAC5C,IAAI,aAAUC,cAAA,MAAA,KAAA;CACd,aAAa;EACX,IAAI,MAAA,QAAQ,GAAG,aAAU,MAAA;EACzB,OACE,SAAS,WAAOC,YAAA,OAAAC,cAER,WACF,EACE,IAAI;GACF,mBAAmB;GACnB,eAAe;GACf,SAAS,UAAU,YAAY,eAAe;EAAO,EAEzD,GACA,MACA,EAAE,KAAK,SAAS,IAAI,CACtB,GAAC,EAAA,cACW,SAAS,MAAK,CAAA,GAAA;GAAAD,YAAA,QAEhB,WAAmB,EAAE,IAAI,mBAAmB,MAAM,GAAC,WAAA,KAAY,GAAC,CACvE,MAAA,SAAS,KAAK,mBAAmB,UAAU,CAAC,CAAA;GAAAA,YAAA,QAAAC,cAGzC,eAA4B;IAAE,SAAS;IAAQ,MAAM;GAAK,GAAC,WAAA,OAAc,EAC3E,eAAe,QAAA,QAAU,EAC3B,CAAC,GAAC,EAAA,OAAA,UAAA,CAAA,GAAA;IAAA,eAAA,CAED,KAAK,mBAAmB;IAAA,SAAA;GAAA,CAAA;GAAAD,YAAA,OAElB,WAAkB,EAAE,IAAI,mBAAmB,QAAQ,GAAC,aAAA,KAAc,GAAC,CAAA,SAAA,KAAA,CAAA;EAAA,CAAA;CAMpF;AACF,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
@@ -1,12 +1,12 @@
1
1
  import { useLang } from "../config/context.js";
2
- import { mergePartProps, mergeProps as mergeProps$1 } from "../utils/props.js";
2
+ import { mergePartProps, mergeProps } from "../utils/props.js";
3
3
  import { disclosureStyles } from "../utils/style/transitions.js";
4
4
  import { IconButton } from "../base/IconButton.js";
5
5
  import { columnValue, sortRows } from "./columns.js";
6
6
  import { checkStates, flattenTree, indexTree, toggleChecked, useTreeExpansion } from "../utils/data/tree.js";
7
7
  import { DataTable } from "./DataTable.js";
8
- import { Fragment, computed, createVNode, mergeProps } from "vue";
9
- import { _component, bindable, readonlyProp, restProps, untrack } from "@zerodep-dev/vue-tsx-pro-tsx";
8
+ import { Fragment, computed, createVNode } from "vue";
9
+ import { _component, bindable, mergeJsxProps, readonlyProp, restProps, untrack } from "@zerodep-dev/vue-tsx-pro-tsx";
10
10
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
11
11
  import { ChevronRight } from "@lucide/icons";
12
12
  //#region src/table/TreeDataTable.tsx
@@ -117,14 +117,14 @@ var TreeDataTable = /*#__PURE__*/ _component((_props, _ctx) => {
117
117
  }, propsToggle.value, {
118
118
  loading: expansion.isLoading(model.key),
119
119
  "aria-expanded": open,
120
- propsIcon: mergeProps$1({
120
+ propsIcon: mergeProps({
121
121
  flipInRtl: true,
122
122
  sx: disclosureStyles.icon
123
123
  }, propsToggle.value?.propsIcon, open ? { sx: treeDataTableStyles.chevronOpen } : void 0),
124
124
  onClick: () => void expansion.setOpen(model.data, model.key, !open)
125
125
  }), null) : createVNode("span", css.attrs(treeDataTableStyles.placeholder), null)]);
126
126
  }
127
- return () => createVNode(DataTable, mergeProps(rest, {
127
+ return () => createVNode(DataTable, mergeJsxProps(rest, {
128
128
  "rows": nodes.value,
129
129
  "getKey": keyOf,
130
130
  "columns": columns.value,
@@ -1 +1 @@
1
- {"version":3,"file":"TreeDataTable.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vtp_untrack","_vue_computed","_createVNode","_Fragment","mergeProps","_mergeProps"],"sources":["../../src/table/TreeDataTable.tsx"],"sourcesContent":["/**\n * 树形表格:有层级的行(部门 → 小组 → 成员、文件夹 → 文件),第一列带缩进与展开按钮。\n * 建在 DataTable 上:列定义、排序、勾选、列宽、虚拟滚动、加载与空状态、外观都和 DataTable 一样;\n * 这里只做两件事:按展开状态把树展开成一列行(同级之间按 sort 排序),以及第一列前面的缩进与展开按钮。\n *\n * <TreeDataTable\n * rows={departments}\n * columns={columns}\n * getKey={(row) => row.id}\n * getChildren={(row) => row.children}\n * _expanded={open}\n * aria-label=\"组织架构\"\n * />\n *\n * - 懒加载:hasChildren 说有子项、getChildren 还没有时,展开会调用 loadChildren(加载中按钮显示加载指示),\n * 调用方把取到的子项放进数据里。\n * - 展开按钮的名称是“行名 的子项”(第一列的文字),展开与否由 aria-expanded 表示。\n * 表格仍是 table 语义(不是 treegrid:那要求逐个单元格的方向键导航),层级由缩进与按钮表达。\n *\n * 部件:DataTable 的全部部件,加上 Toggle(展开按钮,IconButton)。\n */\nimport { ChevronRight } 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 { IconProps } from '../base/Icon';\nimport { IconButton, type IconButtonProps } from '../base/IconButton';\nimport { useLang } from '../config/context';\nimport {\n checkStates,\n flattenTree,\n indexTree,\n toggleChecked,\n useTreeExpansion,\n type TreeAccessors,\n} from '../utils/data/tree';\nimport { mergePartProps, mergeProps } from '../utils/props';\nimport { columnValue, sortRows, type SortState } from './columns';\nimport { DataTable, type DataTableProps } from './DataTable';\nimport type { DataTableRowModel } from './DataTableView';\nimport { disclosureStyles } from '../utils/style/transitions';\n\n/** 未声明的属性落到 table 上;aria-label 或 aria-labelledby 是表格的名称 */\nexport interface TreeDataTableProps<T> extends Omit<DataTableProps<T>, 'leading'> {\n /** 第一层的行 */\n rows: readonly T[];\n /** 一行的子项;没有子项(叶子)或还没加载时返回 undefined / 空数组 */\n getChildren: (row: T) => readonly T[] | undefined;\n /** 这一行有没有子项(懒加载时子项还没取回来也要显示展开按钮);不写时看 getChildren 是否非空 */\n hasChildren?: (row: T) => boolean;\n /** 展开一个还没有子项的行时调用:取回子项并放进数据里;返回 Promise 时按钮显示加载中 */\n loadChildren?: (row: T) => Promise<unknown> | void;\n /** 子项加载失败(loadChildren 的 Promise 被拒绝):这一行收回去,再展开会重试;不写时在控制台报错 */\n onLoadError?: (error: unknown, row: T) => void;\n /** 展开的行的 key:父级写 _expanded={keys} */\n _expanded?: string[];\n /** 每一层缩进多少(em),默认 1.25 */\n indent?: number;\n /** 多选时勾选父子不联动:每一行各自勾选;默认联动(勾上父行连带子孙,子行全勾上时父行也勾上,只勾一部分时父行半选) */\n checkStrictly?: boolean;\n /** 展开按钮的部件属性;加载中、展开状态与点击由组件管理 */\n propsToggle?: Omit<Partial<IconButtonProps>, 'loading' | 'aria-expanded' | 'onClick'>;\n}\n\n/** TreeDataTable 的样式:toggle、chevronOpen、placeholder */\nexport const treeDataTableStyles = css.create({\n toggle: { flexShrink: 0, width: '1.5em', minHeight: '1.5em' },\n chevronOpen: { rotate: '90deg' },\n // 叶子没有按钮,用同样宽的占位让文字对齐\n placeholder: { flexShrink: 0, width: '1.5em' },\n});\n\n// 缩进是任意值,用动态样式;单独一个 create,见 COMPONENTS.md §4\n/** TreeDataTable 的样式:depth */\nexport const treeDataTableIndentStyles = css.create({\n depth: (em: number) => ({ width: `${em}em`, flexShrink: 0 }),\n});\n\n/** 树形表格:按展开状态展开的层级行,复用 DataTable 的一切 */\nexport const TreeDataTable = _component(\n <T,>({\n rows,\n columns,\n getKey,\n getChildren,\n hasChildren,\n loadChildren,\n onLoadError,\n _expanded: expanded = _bindable<string[]>([]),\n indent = 1.25,\n checkStrictly = false,\n propsToggle,\n _sort: sort = _bindable<SortState | null>(null),\n manualSort = false,\n _selected: selected = _bindable<string[]>([]),\n _columnWidths: columnWidths = _bindable<Record<string, number>>({}),\n ...rest\n }: TreeDataTableProps<T>) => {\n const lang = useLang();\n const accessors = (): TreeAccessors<T> => ({ getKey, getChildren, hasChildren });\n const expansion = useTreeExpansion<T>({\n expanded: () => expanded,\n setExpanded: (keys) => (expanded = keys),\n getChildren: (row) => getChildren(row),\n loadChildren: (row) => loadChildren?.(row),\n // 没给 onLoadError 时交给 useTreeExpansion 在控制台报错\n onLoadError: _untrack(onLoadError) && ((error, row) => onLoadError?.(error, row)),\n });\n\n /** 按展开状态深度优先展开成一列;同级之间按当前排序(manualSort 时按数据里的顺序) */\n const flat = _derived.by(() =>\n flattenTree(rows, accessors(), new Set(expanded), {\n order: (level) => (manualSort ? level : sortRows(level, columns, sort, lang.code)),\n }),\n );\n\n // 多选联动:整棵树的索引(含折叠着的行),勾选状态按它推出;交给 DataTable 的是实际勾上的行与半选的父行\n const index = _derived.by(() =>\n rest.selectionMode === 'multiple' && !checkStrictly ? indexTree(rows, accessors()) : null,\n );\n const states = _derived.by(() => (index ? checkStates(index, selected) : null));\n const checkedKeys = _derived.by(() =>\n states ? [...states].flatMap(([key, state]) => (state === 'checked' ? [key] : [])) : selected,\n );\n const partialKeys = _derived.by(() =>\n states\n ? [...states].flatMap(([key, state]) => (state === 'indeterminate' ? [key] : []))\n : undefined,\n );\n\n /** DataTable 写回的勾选:只变了一行时按它联动子孙与祖先;全选、取消全选原样写回 */\n function writeSelected(next: string[]) {\n if (!index) {\n selected = next;\n return;\n }\n const before = new Set(checkedKeys);\n const after = new Set(next);\n const changed = [\n ...next.filter((key) => !before.has(key)),\n ...checkedKeys.filter((key) => !after.has(key)),\n ];\n selected = changed.length === 1 ? toggleChecked(index, checkedKeys, changed[0]!) : next;\n }\n const byKey = _derived.by(() => new Map(flat.map((item) => [item.key, item])));\n // 交给 DataTable 的行与取 key 的函数要保持同一个引用:每次渲染都新建的话,DataTable 会重排全部行\n const nodes = _derived(flat.map((item) => item.node));\n const keyOf = (_: T, index: number) => flat[index]!.key;\n\n function leading(model: DataTableRowModel<T>) {\n const item = byKey.get(model.key);\n const depth = item?.depth ?? 0;\n const first = columns[0] ? columnValue(columns[0], model.data) : undefined;\n const label = first != null ? String(first) : model.key;\n const open = expansion.isExpanded(model.key);\n return (\n <>\n {depth > 0 && <span {...css.attrs(treeDataTableIndentStyles.depth(depth * indent))} />}\n {item?.expandable ? (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: ChevronRight,\n size: 'sm',\n radius: 'full',\n 'aria-label': lang.treeToggle(label),\n sx: treeDataTableStyles.toggle,\n },\n propsToggle,\n {\n loading: expansion.isLoading(model.key),\n 'aria-expanded': open,\n // 箭头的转向跟着展开状态:使用方的 propsIcon 合并进来,而不是整个替换掉\n propsIcon: mergeProps<IconProps>(\n { flipInRtl: true, sx: disclosureStyles.icon },\n propsToggle?.propsIcon,\n open ? { sx: treeDataTableStyles.chevronOpen } : undefined,\n ),\n onClick: () => void expansion.setOpen(model.data, model.key, !open),\n },\n )}\n />\n ) : (\n <span {...css.attrs(treeDataTableStyles.placeholder)} />\n )}\n </>\n );\n }\n\n return () => (\n <DataTable\n {...rest}\n rows={nodes}\n getKey={keyOf}\n columns={columns}\n manualSort\n _sort={sort}\n _selected={checkedKeys as string[]}\n onUpdate:_selected={writeSelected}\n partialKeys={partialKeys}\n _columnWidths={columnWidths}\n leading={leading}\n />\n );\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"TreeDataTable.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vtp_untrack","_vue_computed","_createVNode","_Fragment","_mergeProps"],"sources":["../../src/table/TreeDataTable.tsx"],"sourcesContent":["/**\n * 树形表格:有层级的行(部门 → 小组 → 成员、文件夹 → 文件),第一列带缩进与展开按钮。\n * 建在 DataTable 上:列定义、排序、勾选、列宽、虚拟滚动、加载与空状态、外观都和 DataTable 一样;\n * 这里只做两件事:按展开状态把树展开成一列行(同级之间按 sort 排序),以及第一列前面的缩进与展开按钮。\n *\n * <TreeDataTable\n * rows={departments}\n * columns={columns}\n * getKey={(row) => row.id}\n * getChildren={(row) => row.children}\n * _expanded={open}\n * aria-label=\"组织架构\"\n * />\n *\n * - 懒加载:hasChildren 说有子项、getChildren 还没有时,展开会调用 loadChildren(加载中按钮显示加载指示),\n * 调用方把取到的子项放进数据里。\n * - 展开按钮的名称是“行名 的子项”(第一列的文字),展开与否由 aria-expanded 表示。\n * 表格仍是 table 语义(不是 treegrid:那要求逐个单元格的方向键导航),层级由缩进与按钮表达。\n *\n * 部件:DataTable 的全部部件,加上 Toggle(展开按钮,IconButton)。\n */\nimport { ChevronRight } 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 { IconProps } from '../base/Icon';\nimport { IconButton, type IconButtonProps } from '../base/IconButton';\nimport { useLang } from '../config/context';\nimport {\n checkStates,\n flattenTree,\n indexTree,\n toggleChecked,\n useTreeExpansion,\n type TreeAccessors,\n} from '../utils/data/tree';\nimport { mergePartProps, mergeProps } from '../utils/props';\nimport { columnValue, sortRows, type SortState } from './columns';\nimport { DataTable, type DataTableProps } from './DataTable';\nimport type { DataTableRowModel } from './DataTableView';\nimport { disclosureStyles } from '../utils/style/transitions';\n\n/** 未声明的属性落到 table 上;aria-label 或 aria-labelledby 是表格的名称 */\nexport interface TreeDataTableProps<T> extends Omit<DataTableProps<T>, 'leading'> {\n /** 第一层的行 */\n rows: readonly T[];\n /** 一行的子项;没有子项(叶子)或还没加载时返回 undefined / 空数组 */\n getChildren: (row: T) => readonly T[] | undefined;\n /** 这一行有没有子项(懒加载时子项还没取回来也要显示展开按钮);不写时看 getChildren 是否非空 */\n hasChildren?: (row: T) => boolean;\n /** 展开一个还没有子项的行时调用:取回子项并放进数据里;返回 Promise 时按钮显示加载中 */\n loadChildren?: (row: T) => Promise<unknown> | void;\n /** 子项加载失败(loadChildren 的 Promise 被拒绝):这一行收回去,再展开会重试;不写时在控制台报错 */\n onLoadError?: (error: unknown, row: T) => void;\n /** 展开的行的 key:父级写 _expanded={keys} */\n _expanded?: string[];\n /** 每一层缩进多少(em),默认 1.25 */\n indent?: number;\n /** 多选时勾选父子不联动:每一行各自勾选;默认联动(勾上父行连带子孙,子行全勾上时父行也勾上,只勾一部分时父行半选) */\n checkStrictly?: boolean;\n /** 展开按钮的部件属性;加载中、展开状态与点击由组件管理 */\n propsToggle?: Omit<Partial<IconButtonProps>, 'loading' | 'aria-expanded' | 'onClick'>;\n}\n\n/** TreeDataTable 的样式:toggle、chevronOpen、placeholder */\nexport const treeDataTableStyles = css.create({\n toggle: { flexShrink: 0, width: '1.5em', minHeight: '1.5em' },\n chevronOpen: { rotate: '90deg' },\n // 叶子没有按钮,用同样宽的占位让文字对齐\n placeholder: { flexShrink: 0, width: '1.5em' },\n});\n\n// 缩进是任意值,用动态样式;单独一个 create,见 COMPONENTS.md §4\n/** TreeDataTable 的样式:depth */\nexport const treeDataTableIndentStyles = css.create({\n depth: (em: number) => ({ width: `${em}em`, flexShrink: 0 }),\n});\n\n/** 树形表格:按展开状态展开的层级行,复用 DataTable 的一切 */\nexport const TreeDataTable = _component(\n <T,>({\n rows,\n columns,\n getKey,\n getChildren,\n hasChildren,\n loadChildren,\n onLoadError,\n _expanded: expanded = _bindable<string[]>([]),\n indent = 1.25,\n checkStrictly = false,\n propsToggle,\n _sort: sort = _bindable<SortState | null>(null),\n manualSort = false,\n _selected: selected = _bindable<string[]>([]),\n _columnWidths: columnWidths = _bindable<Record<string, number>>({}),\n ...rest\n }: TreeDataTableProps<T>) => {\n const lang = useLang();\n const accessors = (): TreeAccessors<T> => ({ getKey, getChildren, hasChildren });\n const expansion = useTreeExpansion<T>({\n expanded: () => expanded,\n setExpanded: (keys) => (expanded = keys),\n getChildren: (row) => getChildren(row),\n loadChildren: (row) => loadChildren?.(row),\n // 没给 onLoadError 时交给 useTreeExpansion 在控制台报错\n onLoadError: _untrack(onLoadError) && ((error, row) => onLoadError?.(error, row)),\n });\n\n /** 按展开状态深度优先展开成一列;同级之间按当前排序(manualSort 时按数据里的顺序) */\n const flat = _derived.by(() =>\n flattenTree(rows, accessors(), new Set(expanded), {\n order: (level) => (manualSort ? level : sortRows(level, columns, sort, lang.code)),\n }),\n );\n\n // 多选联动:整棵树的索引(含折叠着的行),勾选状态按它推出;交给 DataTable 的是实际勾上的行与半选的父行\n const index = _derived.by(() =>\n rest.selectionMode === 'multiple' && !checkStrictly ? indexTree(rows, accessors()) : null,\n );\n const states = _derived.by(() => (index ? checkStates(index, selected) : null));\n const checkedKeys = _derived.by(() =>\n states ? [...states].flatMap(([key, state]) => (state === 'checked' ? [key] : [])) : selected,\n );\n const partialKeys = _derived.by(() =>\n states\n ? [...states].flatMap(([key, state]) => (state === 'indeterminate' ? [key] : []))\n : undefined,\n );\n\n /** DataTable 写回的勾选:只变了一行时按它联动子孙与祖先;全选、取消全选原样写回 */\n function writeSelected(next: string[]) {\n if (!index) {\n selected = next;\n return;\n }\n const before = new Set(checkedKeys);\n const after = new Set(next);\n const changed = [\n ...next.filter((key) => !before.has(key)),\n ...checkedKeys.filter((key) => !after.has(key)),\n ];\n selected = changed.length === 1 ? toggleChecked(index, checkedKeys, changed[0]!) : next;\n }\n const byKey = _derived.by(() => new Map(flat.map((item) => [item.key, item])));\n // 交给 DataTable 的行与取 key 的函数要保持同一个引用:每次渲染都新建的话,DataTable 会重排全部行\n const nodes = _derived(flat.map((item) => item.node));\n const keyOf = (_: T, index: number) => flat[index]!.key;\n\n function leading(model: DataTableRowModel<T>) {\n const item = byKey.get(model.key);\n const depth = item?.depth ?? 0;\n const first = columns[0] ? columnValue(columns[0], model.data) : undefined;\n const label = first != null ? String(first) : model.key;\n const open = expansion.isExpanded(model.key);\n return (\n <>\n {depth > 0 && <span {...css.attrs(treeDataTableIndentStyles.depth(depth * indent))} />}\n {item?.expandable ? (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: ChevronRight,\n size: 'sm',\n radius: 'full',\n 'aria-label': lang.treeToggle(label),\n sx: treeDataTableStyles.toggle,\n },\n propsToggle,\n {\n loading: expansion.isLoading(model.key),\n 'aria-expanded': open,\n // 箭头的转向跟着展开状态:使用方的 propsIcon 合并进来,而不是整个替换掉\n propsIcon: mergeProps<IconProps>(\n { flipInRtl: true, sx: disclosureStyles.icon },\n propsToggle?.propsIcon,\n open ? { sx: treeDataTableStyles.chevronOpen } : undefined,\n ),\n onClick: () => void expansion.setOpen(model.data, model.key, !open),\n },\n )}\n />\n ) : (\n <span {...css.attrs(treeDataTableStyles.placeholder)} />\n )}\n </>\n );\n }\n\n return () => (\n <DataTable\n {...rest}\n rows={nodes}\n getKey={keyOf}\n columns={columns}\n manualSort\n _sort={sort}\n _selected={checkedKeys as string[]}\n onUpdate:_selected={writeSelected}\n partialKeys={partialKeys}\n _columnWidths={columnWidths}\n leading={leading}\n />\n );\n },\n);\n"],"mappings":"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"}
@@ -18,8 +18,8 @@ import { CONTRAST_PAIRS, checkContrast } from "./contrast.js";
18
18
  import { elementDesignTokens } from "./design-tokens.js";
19
19
  import { ACCENT_SCALES, NEUTRAL_SCALES, scaleSwatch } from "./palette.js";
20
20
  import { themeSettingsCode } from "./customize.js";
21
- import { Fragment, createTextVNode, createVNode, isVNode, mergeProps, nextTick, shallowRef, watch } from "vue";
22
- import { _component, bindable, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
21
+ import { Fragment, createTextVNode, createVNode, isVNode, nextTick, shallowRef, watch } from "vue";
22
+ import { _component, bindable, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
23
23
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
24
24
  import { Download, FileBraces, RotateCcw } from "@lucide/icons";
25
25
  //#region src/theme-customize/ThemeCustomizer.tsx
@@ -186,6 +186,7 @@ var ThemeCustomizer = /*#__PURE__*/ _component((_props, _ctx) => {
186
186
  };
187
187
  }
188
188
  watch(() => [settings.value, base.value], async () => {
189
+ if (typeof document === "undefined") return;
189
190
  await nextTick();
190
191
  const target = contrastTarget.value ?? document.documentElement;
191
192
  try {
@@ -290,7 +291,7 @@ var ThemeCustomizer = /*#__PURE__*/ _component((_props, _ctx) => {
290
291
  label
291
292
  })), motion, (next) => set("motion", next))]),
292
293
  group(messages.groupExport, messages.groupExportHint, [
293
- createVNode(Alert, mergeProps(mergePartProps({ title: messages.contrast }, propsContrast.value, { tone: issues.value.length === 0 ? "success" : "warning" }), { "key": "__site1" }), {
294
+ createVNode(Alert, mergeJsxProps(mergePartProps({ title: messages.contrast }, propsContrast.value, { tone: issues.value.length === 0 ? "success" : "warning" }), { "key": "__site1" }), {
294
295
  default: () => [issues.value.length === 0 ? messages.contrastOk(CONTRAST_PAIRS.length) : createVNode(Flex, {
295
296
  "direction": "column",
296
297
  "gap": "xs",
@@ -313,21 +314,21 @@ var ThemeCustomizer = /*#__PURE__*/ _component((_props, _ctx) => {
313
314
  "gap": "sm",
314
315
  "wrap": true
315
316
  }, { default: () => [
316
- createVNode(Button, mergeProps(mergePartProps({
317
+ createVNode(Button, mergeJsxProps(mergePartProps({
317
318
  variant: "soft",
318
319
  icon: Download
319
320
  }, propsDownload.value, { onClick: () => downloadFile("theme.ts", code, "text/typescript") }), { "key": "__site2" }), {
320
321
  default: () => [messages.download],
321
322
  $stable: true
322
323
  }),
323
- createVNode(Button, mergeProps(mergePartProps({
324
+ createVNode(Button, mergeJsxProps(mergePartProps({
324
325
  variant: "soft",
325
326
  icon: FileBraces
326
327
  }, propsDownloadTokens.value, { onClick: () => downloadTokens(customized) }), { "key": "__site3" }), {
327
328
  default: () => [messages.downloadTokens],
328
329
  $stable: true
329
330
  }),
330
- createVNode(Button, mergeProps(mergePartProps({
331
+ createVNode(Button, mergeJsxProps(mergePartProps({
331
332
  variant: "soft",
332
333
  tone: "neutral",
333
334
  icon: RotateCcw,
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeCustomizer.js","names":["_isVNode","_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","Text","_Fragment","_createTextVNode","_mergeProps"],"sources":["../../src/theme-customize/ThemeCustomizer.tsx"],"sourcesContent":["/**\n * 主题编辑器:几个旋钮(品牌色、中性色、圆角、缩放、字体、动效)调出自己的主题,实时检查对比度,给出可以粘贴的代码。\n * 只管设置(ThemeSettings);把设置套到主题上由使用方做(customizeTheme),这样设置可以记在本地、和主题偏好组合:\n *\n * let settings = _state<ThemeSettings>({});\n * app.use(createUi({ theme: () => customizeTheme(preference.theme, settings) }));\n * <ThemeCustomizer _settings={settings} base={preference.theme} />\n *\n * 旋钮分成颜色、形状与尺寸、字体与动效、检查与导出四组;每个选项带示意(色块与名字、圆角的角、字号、字体),\n * 当前取值写在旋钮名称旁边。对比度按 CONTRAST_PAIRS 检查,读的是 contrastTarget(默认页面根元素)上实际生效的颜色,\n * 所以改了设置、换了主题都会重新检查。\n */\nimport { Download, FileBraces, RotateCcw } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { nextTick, watch, type VNodeChild } from 'vue';\nimport { Button, type ButtonProps } from '../base/Button';\nimport { CodeBlock, type CodeBlockProps } from '../base/CodeBlock';\nimport { Text } from '../base/Text';\nimport { Alert, type AlertProps } from '../feedback/Alert';\nimport { ToggleGroup, ToggleItem } from '../input/ToggleGroup';\nimport { Flex } from '../layout/Flex';\nimport { downloadFile } from '../utils/dom/download';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { VisuallyHidden } from '../base/VisuallyHidden';\nimport { swatchStyles } from '../utils/style/swatch-styles';\nimport { useFormat } from '../config/lang/format';\nimport { useMessages } from '../config/lang/messages';\nimport { themeCustomizerMessages } from './messages';\nimport { builtinThemes } from '../config/theme/builtin';\nimport { CONTRAST_PAIRS, checkContrast, type ContrastIssue } from './contrast';\nimport {\n themeSettingsCode,\n type FontPresets,\n type MotionPresets,\n type RadiusPresets,\n type ThemeSettings,\n} from './customize';\nimport { elementDesignTokens } from './design-tokens';\nimport {\n ACCENT_SCALES,\n NEUTRAL_SCALES,\n scaleSwatch,\n type AccentScale,\n type NeutralScale,\n} from './palette';\nimport { readToken, type Theme } from '../config/theme/theme';\nimport { colors } from '../config/theme/tokens';\n\n/** 未声明的属性落到外层 div 上 */\nexport interface ThemeCustomizerProps extends PartProps<'div'> {\n /** 设置:父级写 _settings={x} */\n _settings?: ThemeSettings;\n /** 设置套在哪套主题上:决定色块取亮色还是暗色色阶、导出代码里的基础主题 */\n base: Theme;\n /** 从哪个元素上读实际生效的颜色做对比度检查,默认页面根元素 */\n contrastTarget?: HTMLElement | null;\n /** 每个分组(section)的部件属性 */\n propsGroup?: PartProps<'section'>;\n /** 对比度检查结果(Alert)的部件属性;色调由检查结果决定 */\n propsContrast?: Omit<Partial<AlertProps>, 'tone'>;\n /** 导出代码(CodeBlock)的部件属性;代码与语言由组件管理 */\n propsCode?: Omit<Partial<CodeBlockProps>, 'code' | 'lang'>;\n /** 下载代码按钮的部件属性 */\n propsDownload?: Omit<Partial<ButtonProps>, 'onClick'>;\n /** 下载设计令牌(Figma 变量能导入的 JSON)按钮的部件属性 */\n propsDownloadTokens?: Omit<Partial<ButtonProps>, 'onClick'>;\n /** 恢复默认按钮的部件属性 */\n propsReset?: Omit<Partial<ButtonProps>, 'onClick'>;\n}\n\n/** ThemeCustomizer 的样式:root、group、groupHeader、field、fieldHeader、options、option、optionContent 等 */\nexport const themeCustomizerStyles = css.create({\n root: { display: 'flex', flexDirection: 'column', gap: '_xl' },\n group: {\n display: 'flex',\n flexDirection: 'column',\n gap: '_lg',\n // 组与组之间一条分隔线;第一组上面不画\n paddingBlockStart: { default: '_lg', ':first-child': 0 },\n borderBlockStartWidth: { default: '_xs', ':first-child': 0 },\n borderBlockStartStyle: 'solid',\n borderBlockStartColor: '_borderMuted',\n },\n groupHeader: { display: 'flex', flexDirection: 'column', gap: '_xs' },\n field: { display: 'flex', flexDirection: 'column', gap: '_sm' },\n fieldHeader: {\n display: 'flex',\n alignItems: 'baseline',\n justifyContent: 'space-between',\n gap: '_sm',\n },\n // 选项排成网格,窄栏里自动换行;每项左对齐,示意在前、名字在后\n options: {\n display: 'grid',\n // ToggleGroup 默认按内容宽:这里占满整栏,auto-fill 才按栏宽排出几列\n width: 'auto',\n gridTemplateColumns: 'repeat(auto-fill, minmax(6.5em, 1fr))',\n },\n option: { justifyContent: 'flex-start', minWidth: 0 },\n // 色板:只放色块,排成紧凑的网格;名字在悬停提示与读屏文字里,选中的名字与色值写在旋钮标题旁\n swatches: { gridTemplateColumns: 'repeat(auto-fill, minmax(2em, 1fr))' },\n swatchOption: { justifyContent: 'center', paddingInline: 0 },\n swatchLarge: { width: '1.25em', height: '1.25em' },\n optionContent: { display: 'flex', alignItems: 'center', gap: '_sm', minWidth: 0 },\n optionLabel: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' },\n swatch: { flexShrink: 0, width: '1em', height: '1em', borderRadius: '_full' },\n // 主题默认:虚线圈,表示“不覆盖,沿用主题自己的颜色”\n swatchDefault: {\n boxSizing: 'border-box',\n borderWidth: '_xs',\n borderStyle: 'dashed',\n borderColor: '_borderStrong',\n },\n // 圆角示意:一个只有上边与左边的角\n corner: {\n flexShrink: 0,\n boxSizing: 'border-box',\n width: '1em',\n height: '1em',\n borderBlockStartWidth: '_sm',\n borderInlineStartWidth: '_sm',\n borderBlockStartStyle: 'solid',\n borderInlineStartStyle: 'solid',\n borderColor: 'currentColor',\n },\n sample: { flexShrink: 0, lineHeight: 1, fontWeight: '_semibold' },\n sans: { fontFamily: '_sans' },\n serif: { fontFamily: '_serif' },\n});\n\n/** ThemeCustomizer 的样式:圆角示意的四档(none、small、medium、large) */\nexport const themeCustomizerCornerStyles = css.create({\n none: { borderStartStartRadius: 0 },\n small: { borderStartStartRadius: '0.2em' },\n medium: { borderStartStartRadius: '0.45em' },\n large: { borderStartStartRadius: '0.8em' },\n});\n\n// 色块颜色与示例字号是任意值,用动态样式;单独一个 create,见 COMPONENTS.md §4\n/** ThemeCustomizer 的动态样式:色块的颜色、缩放示例的字号 */\nexport const themeCustomizerDynamicStyles = css.create({\n fill: (color: string) => ({ backgroundColor: color }),\n scale: (factor: number) => ({ fontSize: `${factor}em` }),\n});\n\n/** 内置主题名 → 导出代码里的变量名(high-contrast → highContrastTheme);不是内置主题时没有 */\nfunction baseVariable(name: string): string | undefined {\n if (!(name in builtinThemes)) return undefined;\n return `${name.replace(/-(\\w)/g, (_, letter: string) => letter.toUpperCase())}Theme`;\n}\n\nconst SCALINGS = [0.9, 0.95, 1, 1.05, 1.1];\n\n/** 一个选项:值、示意、名字、悬停提示 */\ninterface Option {\n value: string;\n preview?: VNodeChild;\n label: VNodeChild;\n title?: string;\n}\n\n/** 选项的排法:list 是示意加名字,swatches 只放色块 */\ntype OptionLayout = 'list' | 'swatches';\n\n/** 主题编辑器:分组的旋钮、对比度检查与导出代码 */\nexport const ThemeCustomizer = _component(\n ({\n _settings: settings = _bindable<ThemeSettings>({}),\n base,\n contrastTarget,\n propsGroup,\n propsContrast,\n propsCode,\n propsDownload,\n propsDownloadTokens,\n propsReset,\n ...rest\n }: ThemeCustomizerProps) => {\n const messages = useMessages('themeCustomizer', themeCustomizerMessages);\n const format = useFormat();\n let issues = _state.raw<ContrastIssue[]>([]);\n\n /** 改一个旋钮:空值表示沿用主题本来的取值 */\n function set<Key extends keyof ThemeSettings>(key: Key, value: ThemeSettings[Key] | '') {\n settings = { ...settings, [key]: value === '' ? undefined : value };\n }\n\n // 设置或主题变了:等新主题写进页面,再读实际生效的颜色检查对比度\n watch(\n () => [settings, base],\n async () => {\n await nextTick();\n const target = contrastTarget ?? document.documentElement;\n try {\n issues = checkContrast((token) =>\n readToken(target, colors[token as keyof typeof colors] as never),\n );\n } catch {\n // 主题的颜色还没写进页面(服务端渲染、没有样式的测试环境):读不到就不检查\n issues = [];\n }\n },\n { immediate: true, deep: true, flush: 'post' },\n );\n\n /** 页面上实际生效的主题(已经套上这些设置)存成 Figma 变量能导入的设计令牌 */\n function downloadTokens(customized: boolean) {\n const name = `${base.name.replace(/-custom$/, '')}${customized ? '-custom' : ''}`;\n const tokens = elementDesignTokens(contrastTarget ?? document.documentElement);\n downloadFile(`${name}.tokens.json`, JSON.stringify(tokens, null, 2), 'application/json');\n }\n\n const group = (title: string, hint: string, children: VNodeChild) => (\n <section {...mergeAttrs<'section'>({ sx: themeCustomizerStyles.group }, propsGroup)}>\n <div {...css.attrs(themeCustomizerStyles.groupHeader)}>\n <Text weight=\"semibold\">{title}</Text>\n <Text size=\"sm\" tone=\"muted\">\n {hint}\n </Text>\n </div>\n {children}\n </section>\n );\n\n /** 一个旋钮:名称与当前取值,下面是选项网格(单选、至少选一项) */\n const field = (\n label: string,\n current: VNodeChild,\n options: readonly Option[],\n value: string,\n onChange: (next: string) => void,\n layout: OptionLayout = 'list',\n ) => (\n <div {...css.attrs(themeCustomizerStyles.field)}>\n <div {...css.attrs(themeCustomizerStyles.fieldHeader)}>\n <Text size=\"sm\" weight=\"medium\">\n {label}\n </Text>\n <Text size=\"xs\" tone=\"muted\">\n {current}\n </Text>\n </div>\n <ToggleGroup\n _value={value}\n onUpdate:_value={onChange}\n required\n size=\"sm\"\n aria-label={label}\n sx={[\n themeCustomizerStyles.options,\n layout === 'swatches' && themeCustomizerStyles.swatches,\n ]}\n >\n {options.map((option) => (\n <ToggleItem\n key={option.value}\n value={option.value}\n title={option.title}\n sx={[\n themeCustomizerStyles.option,\n layout === 'swatches' && themeCustomizerStyles.swatchOption,\n ]}\n >\n {layout === 'swatches' ? (\n <>\n {option.preview}\n <VisuallyHidden>{option.label}</VisuallyHidden>\n </>\n ) : (\n <span {...css.attrs(themeCustomizerStyles.optionContent)}>\n {option.preview}\n <span {...css.attrs(themeCustomizerStyles.optionLabel)}>{option.label}</span>\n </span>\n )}\n </ToggleItem>\n ))}\n </ToggleGroup>\n </div>\n );\n\n /** 色阶在当前语言下的名字与色值:“靛蓝 #3e63dd”;没选(主题默认)时是“主题默认” */\n const scaleText = (scale: AccentScale | NeutralScale | undefined) =>\n scale\n ? `${messages.colorNames[scale]} ${scaleSwatch(scale as never, base.colorScheme)}`\n : messages.themeDefault;\n\n /** 色阶选项:第一项是“主题默认”,其余是色块;名字与色值在悬停提示与读屏文字里 */\n const scaleOptions = (scales: readonly (AccentScale | NeutralScale)[]): Option[] => [\n {\n value: '',\n preview: (\n <span\n {...css.attrs(\n themeCustomizerStyles.swatch,\n themeCustomizerStyles.swatchLarge,\n themeCustomizerStyles.swatchDefault,\n )}\n />\n ),\n label: messages.themeDefault,\n title: messages.themeDefault,\n },\n ...scales.map((scale) => {\n const color = scaleSwatch(scale as never, base.colorScheme);\n return {\n value: scale,\n title: `${messages.colorNames[scale]}(${scale})${color}`,\n preview: (\n <span\n {...css.attrs(\n themeCustomizerStyles.swatch,\n themeCustomizerStyles.swatchLarge,\n swatchStyles.ring,\n themeCustomizerDynamicStyles.fill(color),\n )}\n />\n ),\n label: messages.colorNames[scale],\n };\n }),\n ];\n\n return () => {\n const radii: [keyof RadiusPresets, string][] = [\n ['none', messages.radiusNone],\n ['small', messages.radiusSmall],\n ['medium', messages.radiusMedium],\n ['large', messages.radiusLarge],\n ];\n const fonts: [keyof FontPresets, string][] = [\n ['sans', messages.fontSans],\n ['serifHeadings', messages.fontSerifHeadings],\n ];\n const motions: [keyof MotionPresets, string][] = [\n ['none', messages.motionNone],\n ['fast', messages.motionFast],\n ['normal', messages.motionNormal],\n ['slow', messages.motionSlow],\n ];\n const radius = settings.radius ?? 'medium';\n const scaling = settings.scaling ?? 1;\n const font = settings.font ?? 'sans';\n const motion = settings.motion ?? 'normal';\n const percent = (factor: number) => format.number(factor, { style: 'percent' });\n const labelOf = <Key extends string>(list: [Key, string][], key: Key) =>\n list.find(([value]) => value === key)?.[1];\n const code = themeSettingsCode(\n baseVariable(base.name.replace(/-custom$/, '')) ??\n (base.colorScheme === 'dark' ? 'darkTheme' : 'lightTheme'),\n settings,\n base.colorScheme,\n );\n const customized = Object.values(settings).some((value) => value !== undefined);\n\n return (\n <div {...mergeAttrs<'div'>({ sx: themeCustomizerStyles.root }, rest)}>\n {group(messages.groupColor, messages.groupColorHint, [\n field(\n messages.accent,\n scaleText(settings.accent),\n scaleOptions(ACCENT_SCALES),\n settings.accent ?? '',\n (next) => set('accent', next as ThemeSettings['accent'] | ''),\n 'swatches',\n ),\n field(\n messages.neutral,\n scaleText(settings.neutral),\n scaleOptions(NEUTRAL_SCALES),\n settings.neutral ?? '',\n (next) => set('neutral', next as ThemeSettings['neutral'] | ''),\n 'swatches',\n ),\n ])}\n {group(messages.groupShape, messages.groupShapeHint, [\n field(\n messages.radius,\n labelOf(radii, radius),\n radii.map(([value, label]) => ({\n value,\n label,\n preview: (\n <span\n {...css.attrs(themeCustomizerStyles.corner, themeCustomizerCornerStyles[value])}\n />\n ),\n })),\n radius,\n (next) => set('radius', next as keyof RadiusPresets),\n ),\n field(\n messages.scaling,\n percent(scaling),\n SCALINGS.map((factor) => ({\n value: String(factor),\n label: percent(factor),\n preview: (\n <span\n {...css.attrs(\n themeCustomizerStyles.sample,\n themeCustomizerDynamicStyles.scale(factor),\n )}\n >\n Aa\n </span>\n ),\n })),\n String(scaling),\n (next) => set('scaling', Number(next)),\n ),\n ])}\n {group(messages.groupType, messages.groupTypeHint, [\n field(\n messages.font,\n labelOf(fonts, font),\n fonts.map(([value, label]) => ({\n value,\n label,\n preview: (\n <span\n {...css.attrs(\n themeCustomizerStyles.sample,\n value === 'sans' ? themeCustomizerStyles.sans : themeCustomizerStyles.serif,\n )}\n >\n Aa\n </span>\n ),\n })),\n font,\n (next) => set('font', next as keyof FontPresets),\n ),\n field(\n messages.motion,\n labelOf(motions, motion),\n motions.map(([value, label]) => ({ value, label })),\n motion,\n (next) => set('motion', next as keyof MotionPresets),\n ),\n ])}\n {group(messages.groupExport, messages.groupExportHint, [\n <Alert\n {...mergePartProps<AlertProps>({ title: messages.contrast }, propsContrast, {\n tone: issues.length === 0 ? 'success' : 'warning',\n })}\n >\n {issues.length === 0 ? (\n messages.contrastOk(CONTRAST_PAIRS.length)\n ) : (\n <Flex direction=\"column\" gap=\"xs\">\n {issues.map((issue) => (\n <span key={`${issue.foreground}-${issue.background}`}>\n {messages.contrastIssue(\n `${issue.foreground} / ${issue.background}`,\n format.number(issue.ratio, {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n }),\n issue.minimum,\n )}\n </span>\n ))}\n </Flex>\n )}\n </Alert>,\n <CodeBlock\n {...mergePartProps<CodeBlockProps>(\n { title: messages.code, code, lang: 'ts' },\n propsCode,\n )}\n />,\n <Flex gap=\"sm\" wrap>\n <Button\n {...mergePartProps<ButtonProps>(\n { variant: 'soft', icon: Download },\n propsDownload,\n { onClick: () => downloadFile('theme.ts', code, 'text/typescript') },\n )}\n >\n {messages.download}\n </Button>\n <Button\n {...mergePartProps<ButtonProps>(\n { variant: 'soft', icon: FileBraces },\n propsDownloadTokens,\n { onClick: () => downloadTokens(customized) },\n )}\n >\n {messages.downloadTokens}\n </Button>\n <Button\n {...mergePartProps<ButtonProps>(\n { variant: 'soft', tone: 'neutral', icon: RotateCcw, disabled: !customized },\n propsReset,\n { onClick: () => (settings = {}) },\n )}\n >\n {messages.reset}\n </Button>\n </Flex>,\n ])}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"ThemeCustomizer.js","names":["_isVNode","_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","Text","_Fragment","_createTextVNode","_mergeProps"],"sources":["../../src/theme-customize/ThemeCustomizer.tsx"],"sourcesContent":["/**\n * 主题编辑器:几个旋钮(品牌色、中性色、圆角、缩放、字体、动效)调出自己的主题,实时检查对比度,给出可以粘贴的代码。\n * 只管设置(ThemeSettings);把设置套到主题上由使用方做(customizeTheme),这样设置可以记在本地、和主题偏好组合:\n *\n * let settings = _state<ThemeSettings>({});\n * app.use(createUi({ theme: () => customizeTheme(preference.theme, settings) }));\n * <ThemeCustomizer _settings={settings} base={preference.theme} />\n *\n * 旋钮分成颜色、形状与尺寸、字体与动效、检查与导出四组;每个选项带示意(色块与名字、圆角的角、字号、字体),\n * 当前取值写在旋钮名称旁边。对比度按 CONTRAST_PAIRS 检查,读的是 contrastTarget(默认页面根元素)上实际生效的颜色,\n * 所以改了设置、换了主题都会重新检查。\n */\nimport { Download, FileBraces, RotateCcw } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { nextTick, watch, type VNodeChild } from 'vue';\nimport { Button, type ButtonProps } from '../base/Button';\nimport { CodeBlock, type CodeBlockProps } from '../base/CodeBlock';\nimport { Text } from '../base/Text';\nimport { Alert, type AlertProps } from '../feedback/Alert';\nimport { ToggleGroup, ToggleItem } from '../input/ToggleGroup';\nimport { Flex } from '../layout/Flex';\nimport { downloadFile } from '../utils/dom/download';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { VisuallyHidden } from '../base/VisuallyHidden';\nimport { swatchStyles } from '../utils/style/swatch-styles';\nimport { useFormat } from '../config/lang/format';\nimport { useMessages } from '../config/lang/messages';\nimport { themeCustomizerMessages } from './messages';\nimport { builtinThemes } from '../config/theme/builtin';\nimport { CONTRAST_PAIRS, checkContrast, type ContrastIssue } from './contrast';\nimport {\n themeSettingsCode,\n type FontPresets,\n type MotionPresets,\n type RadiusPresets,\n type ThemeSettings,\n} from './customize';\nimport { elementDesignTokens } from './design-tokens';\nimport {\n ACCENT_SCALES,\n NEUTRAL_SCALES,\n scaleSwatch,\n type AccentScale,\n type NeutralScale,\n} from './palette';\nimport { readToken, type Theme } from '../config/theme/theme';\nimport { colors } from '../config/theme/tokens';\n\n/** 未声明的属性落到外层 div 上 */\nexport interface ThemeCustomizerProps extends PartProps<'div'> {\n /** 设置:父级写 _settings={x} */\n _settings?: ThemeSettings;\n /** 设置套在哪套主题上:决定色块取亮色还是暗色色阶、导出代码里的基础主题 */\n base: Theme;\n /** 从哪个元素上读实际生效的颜色做对比度检查,默认页面根元素 */\n contrastTarget?: HTMLElement | null;\n /** 每个分组(section)的部件属性 */\n propsGroup?: PartProps<'section'>;\n /** 对比度检查结果(Alert)的部件属性;色调由检查结果决定 */\n propsContrast?: Omit<Partial<AlertProps>, 'tone'>;\n /** 导出代码(CodeBlock)的部件属性;代码与语言由组件管理 */\n propsCode?: Omit<Partial<CodeBlockProps>, 'code' | 'lang'>;\n /** 下载代码按钮的部件属性 */\n propsDownload?: Omit<Partial<ButtonProps>, 'onClick'>;\n /** 下载设计令牌(Figma 变量能导入的 JSON)按钮的部件属性 */\n propsDownloadTokens?: Omit<Partial<ButtonProps>, 'onClick'>;\n /** 恢复默认按钮的部件属性 */\n propsReset?: Omit<Partial<ButtonProps>, 'onClick'>;\n}\n\n/** ThemeCustomizer 的样式:root、group、groupHeader、field、fieldHeader、options、option、optionContent 等 */\nexport const themeCustomizerStyles = css.create({\n root: { display: 'flex', flexDirection: 'column', gap: '_xl' },\n group: {\n display: 'flex',\n flexDirection: 'column',\n gap: '_lg',\n // 组与组之间一条分隔线;第一组上面不画\n paddingBlockStart: { default: '_lg', ':first-child': 0 },\n borderBlockStartWidth: { default: '_xs', ':first-child': 0 },\n borderBlockStartStyle: 'solid',\n borderBlockStartColor: '_borderMuted',\n },\n groupHeader: { display: 'flex', flexDirection: 'column', gap: '_xs' },\n field: { display: 'flex', flexDirection: 'column', gap: '_sm' },\n fieldHeader: {\n display: 'flex',\n alignItems: 'baseline',\n justifyContent: 'space-between',\n gap: '_sm',\n },\n // 选项排成网格,窄栏里自动换行;每项左对齐,示意在前、名字在后\n options: {\n display: 'grid',\n // ToggleGroup 默认按内容宽:这里占满整栏,auto-fill 才按栏宽排出几列\n width: 'auto',\n gridTemplateColumns: 'repeat(auto-fill, minmax(6.5em, 1fr))',\n },\n option: { justifyContent: 'flex-start', minWidth: 0 },\n // 色板:只放色块,排成紧凑的网格;名字在悬停提示与读屏文字里,选中的名字与色值写在旋钮标题旁\n swatches: { gridTemplateColumns: 'repeat(auto-fill, minmax(2em, 1fr))' },\n swatchOption: { justifyContent: 'center', paddingInline: 0 },\n swatchLarge: { width: '1.25em', height: '1.25em' },\n optionContent: { display: 'flex', alignItems: 'center', gap: '_sm', minWidth: 0 },\n optionLabel: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' },\n swatch: { flexShrink: 0, width: '1em', height: '1em', borderRadius: '_full' },\n // 主题默认:虚线圈,表示“不覆盖,沿用主题自己的颜色”\n swatchDefault: {\n boxSizing: 'border-box',\n borderWidth: '_xs',\n borderStyle: 'dashed',\n borderColor: '_borderStrong',\n },\n // 圆角示意:一个只有上边与左边的角\n corner: {\n flexShrink: 0,\n boxSizing: 'border-box',\n width: '1em',\n height: '1em',\n borderBlockStartWidth: '_sm',\n borderInlineStartWidth: '_sm',\n borderBlockStartStyle: 'solid',\n borderInlineStartStyle: 'solid',\n borderColor: 'currentColor',\n },\n sample: { flexShrink: 0, lineHeight: 1, fontWeight: '_semibold' },\n sans: { fontFamily: '_sans' },\n serif: { fontFamily: '_serif' },\n});\n\n/** ThemeCustomizer 的样式:圆角示意的四档(none、small、medium、large) */\nexport const themeCustomizerCornerStyles = css.create({\n none: { borderStartStartRadius: 0 },\n small: { borderStartStartRadius: '0.2em' },\n medium: { borderStartStartRadius: '0.45em' },\n large: { borderStartStartRadius: '0.8em' },\n});\n\n// 色块颜色与示例字号是任意值,用动态样式;单独一个 create,见 COMPONENTS.md §4\n/** ThemeCustomizer 的动态样式:色块的颜色、缩放示例的字号 */\nexport const themeCustomizerDynamicStyles = css.create({\n fill: (color: string) => ({ backgroundColor: color }),\n scale: (factor: number) => ({ fontSize: `${factor}em` }),\n});\n\n/** 内置主题名 → 导出代码里的变量名(high-contrast → highContrastTheme);不是内置主题时没有 */\nfunction baseVariable(name: string): string | undefined {\n if (!(name in builtinThemes)) return undefined;\n return `${name.replace(/-(\\w)/g, (_, letter: string) => letter.toUpperCase())}Theme`;\n}\n\nconst SCALINGS = [0.9, 0.95, 1, 1.05, 1.1];\n\n/** 一个选项:值、示意、名字、悬停提示 */\ninterface Option {\n value: string;\n preview?: VNodeChild;\n label: VNodeChild;\n title?: string;\n}\n\n/** 选项的排法:list 是示意加名字,swatches 只放色块 */\ntype OptionLayout = 'list' | 'swatches';\n\n/** 主题编辑器:分组的旋钮、对比度检查与导出代码 */\nexport const ThemeCustomizer = _component(\n ({\n _settings: settings = _bindable<ThemeSettings>({}),\n base,\n contrastTarget,\n propsGroup,\n propsContrast,\n propsCode,\n propsDownload,\n propsDownloadTokens,\n propsReset,\n ...rest\n }: ThemeCustomizerProps) => {\n const messages = useMessages('themeCustomizer', themeCustomizerMessages);\n const format = useFormat();\n let issues = _state.raw<ContrastIssue[]>([]);\n\n /** 改一个旋钮:空值表示沿用主题本来的取值 */\n function set<Key extends keyof ThemeSettings>(key: Key, value: ThemeSettings[Key] | '') {\n settings = { ...settings, [key]: value === '' ? undefined : value };\n }\n\n // 设置或主题变了:等新主题写进页面,再读实际生效的颜色检查对比度\n watch(\n () => [settings, base],\n async () => {\n // 服务端渲染时 immediate 的侦听也会执行,页面上没有主题可读\n if (typeof document === 'undefined') return;\n await nextTick();\n const target = contrastTarget ?? document.documentElement;\n try {\n issues = checkContrast((token) =>\n readToken(target, colors[token as keyof typeof colors] as never),\n );\n } catch {\n // 主题的颜色还没写进页面(服务端渲染、没有样式的测试环境):读不到就不检查\n issues = [];\n }\n },\n { immediate: true, deep: true, flush: 'post' },\n );\n\n /** 页面上实际生效的主题(已经套上这些设置)存成 Figma 变量能导入的设计令牌 */\n function downloadTokens(customized: boolean) {\n const name = `${base.name.replace(/-custom$/, '')}${customized ? '-custom' : ''}`;\n const tokens = elementDesignTokens(contrastTarget ?? document.documentElement);\n downloadFile(`${name}.tokens.json`, JSON.stringify(tokens, null, 2), 'application/json');\n }\n\n const group = (title: string, hint: string, children: VNodeChild) => (\n <section {...mergeAttrs<'section'>({ sx: themeCustomizerStyles.group }, propsGroup)}>\n <div {...css.attrs(themeCustomizerStyles.groupHeader)}>\n <Text weight=\"semibold\">{title}</Text>\n <Text size=\"sm\" tone=\"muted\">\n {hint}\n </Text>\n </div>\n {children}\n </section>\n );\n\n /** 一个旋钮:名称与当前取值,下面是选项网格(单选、至少选一项) */\n const field = (\n label: string,\n current: VNodeChild,\n options: readonly Option[],\n value: string,\n onChange: (next: string) => void,\n layout: OptionLayout = 'list',\n ) => (\n <div {...css.attrs(themeCustomizerStyles.field)}>\n <div {...css.attrs(themeCustomizerStyles.fieldHeader)}>\n <Text size=\"sm\" weight=\"medium\">\n {label}\n </Text>\n <Text size=\"xs\" tone=\"muted\">\n {current}\n </Text>\n </div>\n <ToggleGroup\n _value={value}\n onUpdate:_value={onChange}\n required\n size=\"sm\"\n aria-label={label}\n sx={[\n themeCustomizerStyles.options,\n layout === 'swatches' && themeCustomizerStyles.swatches,\n ]}\n >\n {options.map((option) => (\n <ToggleItem\n key={option.value}\n value={option.value}\n title={option.title}\n sx={[\n themeCustomizerStyles.option,\n layout === 'swatches' && themeCustomizerStyles.swatchOption,\n ]}\n >\n {layout === 'swatches' ? (\n <>\n {option.preview}\n <VisuallyHidden>{option.label}</VisuallyHidden>\n </>\n ) : (\n <span {...css.attrs(themeCustomizerStyles.optionContent)}>\n {option.preview}\n <span {...css.attrs(themeCustomizerStyles.optionLabel)}>{option.label}</span>\n </span>\n )}\n </ToggleItem>\n ))}\n </ToggleGroup>\n </div>\n );\n\n /** 色阶在当前语言下的名字与色值:“靛蓝 #3e63dd”;没选(主题默认)时是“主题默认” */\n const scaleText = (scale: AccentScale | NeutralScale | undefined) =>\n scale\n ? `${messages.colorNames[scale]} ${scaleSwatch(scale as never, base.colorScheme)}`\n : messages.themeDefault;\n\n /** 色阶选项:第一项是“主题默认”,其余是色块;名字与色值在悬停提示与读屏文字里 */\n const scaleOptions = (scales: readonly (AccentScale | NeutralScale)[]): Option[] => [\n {\n value: '',\n preview: (\n <span\n {...css.attrs(\n themeCustomizerStyles.swatch,\n themeCustomizerStyles.swatchLarge,\n themeCustomizerStyles.swatchDefault,\n )}\n />\n ),\n label: messages.themeDefault,\n title: messages.themeDefault,\n },\n ...scales.map((scale) => {\n const color = scaleSwatch(scale as never, base.colorScheme);\n return {\n value: scale,\n title: `${messages.colorNames[scale]}(${scale})${color}`,\n preview: (\n <span\n {...css.attrs(\n themeCustomizerStyles.swatch,\n themeCustomizerStyles.swatchLarge,\n swatchStyles.ring,\n themeCustomizerDynamicStyles.fill(color),\n )}\n />\n ),\n label: messages.colorNames[scale],\n };\n }),\n ];\n\n return () => {\n const radii: [keyof RadiusPresets, string][] = [\n ['none', messages.radiusNone],\n ['small', messages.radiusSmall],\n ['medium', messages.radiusMedium],\n ['large', messages.radiusLarge],\n ];\n const fonts: [keyof FontPresets, string][] = [\n ['sans', messages.fontSans],\n ['serifHeadings', messages.fontSerifHeadings],\n ];\n const motions: [keyof MotionPresets, string][] = [\n ['none', messages.motionNone],\n ['fast', messages.motionFast],\n ['normal', messages.motionNormal],\n ['slow', messages.motionSlow],\n ];\n const radius = settings.radius ?? 'medium';\n const scaling = settings.scaling ?? 1;\n const font = settings.font ?? 'sans';\n const motion = settings.motion ?? 'normal';\n const percent = (factor: number) => format.number(factor, { style: 'percent' });\n const labelOf = <Key extends string>(list: [Key, string][], key: Key) =>\n list.find(([value]) => value === key)?.[1];\n const code = themeSettingsCode(\n baseVariable(base.name.replace(/-custom$/, '')) ??\n (base.colorScheme === 'dark' ? 'darkTheme' : 'lightTheme'),\n settings,\n base.colorScheme,\n );\n const customized = Object.values(settings).some((value) => value !== undefined);\n\n return (\n <div {...mergeAttrs<'div'>({ sx: themeCustomizerStyles.root }, rest)}>\n {group(messages.groupColor, messages.groupColorHint, [\n field(\n messages.accent,\n scaleText(settings.accent),\n scaleOptions(ACCENT_SCALES),\n settings.accent ?? '',\n (next) => set('accent', next as ThemeSettings['accent'] | ''),\n 'swatches',\n ),\n field(\n messages.neutral,\n scaleText(settings.neutral),\n scaleOptions(NEUTRAL_SCALES),\n settings.neutral ?? '',\n (next) => set('neutral', next as ThemeSettings['neutral'] | ''),\n 'swatches',\n ),\n ])}\n {group(messages.groupShape, messages.groupShapeHint, [\n field(\n messages.radius,\n labelOf(radii, radius),\n radii.map(([value, label]) => ({\n value,\n label,\n preview: (\n <span\n {...css.attrs(themeCustomizerStyles.corner, themeCustomizerCornerStyles[value])}\n />\n ),\n })),\n radius,\n (next) => set('radius', next as keyof RadiusPresets),\n ),\n field(\n messages.scaling,\n percent(scaling),\n SCALINGS.map((factor) => ({\n value: String(factor),\n label: percent(factor),\n preview: (\n <span\n {...css.attrs(\n themeCustomizerStyles.sample,\n themeCustomizerDynamicStyles.scale(factor),\n )}\n >\n Aa\n </span>\n ),\n })),\n String(scaling),\n (next) => set('scaling', Number(next)),\n ),\n ])}\n {group(messages.groupType, messages.groupTypeHint, [\n field(\n messages.font,\n labelOf(fonts, font),\n fonts.map(([value, label]) => ({\n value,\n label,\n preview: (\n <span\n {...css.attrs(\n themeCustomizerStyles.sample,\n value === 'sans' ? themeCustomizerStyles.sans : themeCustomizerStyles.serif,\n )}\n >\n Aa\n </span>\n ),\n })),\n font,\n (next) => set('font', next as keyof FontPresets),\n ),\n field(\n messages.motion,\n labelOf(motions, motion),\n motions.map(([value, label]) => ({ value, label })),\n motion,\n (next) => set('motion', next as keyof MotionPresets),\n ),\n ])}\n {group(messages.groupExport, messages.groupExportHint, [\n <Alert\n {...mergePartProps<AlertProps>({ title: messages.contrast }, propsContrast, {\n tone: issues.length === 0 ? 'success' : 'warning',\n })}\n >\n {issues.length === 0 ? (\n messages.contrastOk(CONTRAST_PAIRS.length)\n ) : (\n <Flex direction=\"column\" gap=\"xs\">\n {issues.map((issue) => (\n <span key={`${issue.foreground}-${issue.background}`}>\n {messages.contrastIssue(\n `${issue.foreground} / ${issue.background}`,\n format.number(issue.ratio, {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n }),\n issue.minimum,\n )}\n </span>\n ))}\n </Flex>\n )}\n </Alert>,\n <CodeBlock\n {...mergePartProps<CodeBlockProps>(\n { title: messages.code, code, lang: 'ts' },\n propsCode,\n )}\n />,\n <Flex gap=\"sm\" wrap>\n <Button\n {...mergePartProps<ButtonProps>(\n { variant: 'soft', icon: Download },\n propsDownload,\n { onClick: () => downloadFile('theme.ts', code, 'text/typescript') },\n )}\n >\n {messages.download}\n </Button>\n <Button\n {...mergePartProps<ButtonProps>(\n { variant: 'soft', icon: FileBraces },\n propsDownloadTokens,\n { onClick: () => downloadTokens(customized) },\n )}\n >\n {messages.downloadTokens}\n </Button>\n <Button\n {...mergePartProps<ButtonProps>(\n { variant: 'soft', tone: 'neutral', icon: RotateCcw, disabled: !customized },\n propsReset,\n { onClick: () => (settings = {}) },\n )}\n >\n {messages.reset}\n </Button>\n </Flex>,\n ])}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { mergeAttrs } from "../utils/props.js";
2
2
  import { themeAttrs } from "../config/theme/theme.js";
3
3
  import { swatchStyles } from "../utils/style/swatch-styles.js";
4
- import { createVNode, mergeProps } from "vue";
5
- import { _component, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
4
+ import { createVNode } from "vue";
5
+ import { _component, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
6
6
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
7
7
  //#region src/theme-customize/ThemeThumbnail.tsx
8
8
  /** 未声明的属性落到外层 span 上 */
@@ -62,7 +62,7 @@ var ThemeThumbnail = /*#__PURE__*/ _component((_props, _ctx) => {
62
62
  const rest = restProps(_props, _ctx, true);
63
63
  return () => {
64
64
  const { class: themeClass, style, "data-theme": name } = themeAttrs(theme.value);
65
- return createVNode("span", mergeProps(mergeAttrs({
65
+ return createVNode("span", mergeJsxProps(mergeAttrs({
66
66
  sx: [themeThumbnailStyles.root, swatchStyles.ring],
67
67
  class: themeClass,
68
68
  style
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeThumbnail.js","names":["_vtp_readonlyProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../src/theme-customize/ThemeThumbnail.tsx"],"sourcesContent":["/**\n * 主题缩略图(span):用这套主题画一个缩小的页面:底色上一张卡片,卡片里标题、正文两行字和一个品牌色按钮。\n * 主题选择器、主题列表里代替主题名旁边的色点,一眼看出底色、表面、文字与品牌色的搭配。\n *\n * <ThemeThumbnail theme={oceanTheme} />\n *\n * 颜色来自套在它上面的主题变量(themeAttrs),换主题不用重画;纯装饰,对读屏隐藏,名字由使用方写在旁边。\n * 尺寸用 em,随字号缩放。部件:Root(span)、Card(卡片)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { mergeAttrs, type PartProps } from '../utils/props';\nimport { swatchStyles } from '../utils/style/swatch-styles';\nimport { themeAttrs, type Theme } from '../config/theme/theme';\n\n/** 未声明的属性落到外层 span 上 */\nexport interface ThemeThumbnailProps extends PartProps<'span', 'aria-hidden'> {\n /** 画哪一套主题 */\n theme: Theme;\n /** 卡片的部件属性 */\n propsCard?: PartProps<'span'>;\n}\n\n/** ThemeThumbnail 的样式:root、card、title、line、button */\nexport const themeThumbnailStyles = css.create({\n root: {\n display: 'inline-flex',\n alignItems: 'flex-end',\n justifyContent: 'flex-end',\n flexShrink: 0,\n width: '6em',\n height: '3.75em',\n padding: '0.5em 0 0 0.75em',\n overflow: 'hidden',\n borderRadius: '_md',\n backgroundColor: '_background',\n },\n // 卡片从右下角探出来:像页面的一角\n card: {\n display: 'flex',\n flexDirection: 'column',\n gap: '0.3em',\n width: '100%',\n height: '100%',\n padding: '0.5em',\n borderStartStartRadius: '_sm',\n borderTopWidth: '_xs',\n borderInlineStartWidth: '_xs',\n borderTopStyle: 'solid',\n borderInlineStartStyle: 'solid',\n borderColor: '_border',\n backgroundColor: '_surfaceRaised',\n },\n title: { width: '70%', height: '0.35em', borderRadius: '_full', backgroundColor: '_text' },\n line: { width: '90%', height: '0.25em', borderRadius: '_full', backgroundColor: '_textMuted' },\n button: {\n width: '45%',\n height: '0.6em',\n marginBlockStart: 'auto',\n borderRadius: '_sm',\n backgroundColor: '_accent',\n },\n});\n\n/** 主题缩略图:缩小的页面一角,颜色取自这套主题 */\nexport const ThemeThumbnail = _component(({ theme, propsCard, ...rest }: ThemeThumbnailProps) => {\n return () => {\n const { class: themeClass, style, 'data-theme': name } = themeAttrs(theme);\n return (\n <span\n {...mergeAttrs<'span'>(\n { sx: [themeThumbnailStyles.root, swatchStyles.ring], class: themeClass, style },\n rest,\n { 'aria-hidden': true },\n )}\n data-theme={name}\n >\n <span {...mergeAttrs<'span'>({ sx: themeThumbnailStyles.card }, propsCard)}>\n <span {...css.attrs(themeThumbnailStyles.title)} />\n <span {...css.attrs(themeThumbnailStyles.line)} />\n <span {...css.attrs(themeThumbnailStyles.button)} />\n </span>\n </span>\n );\n };\n});\n"],"mappings":";;;;;;;;;AAwBA,IAAa,uBAAuB,IAAI,OAAO;CAC7C,MAAM;EACJ,SAAS;EACT,YAAY;EACZ,gBAAgB;EAChB,YAAY;EACZ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,UAAU;EACV,cAAc;EACd,iBAAiB;CACnB;CAEA,MAAM;EACJ,SAAS;EACT,eAAe;EACf,KAAK;EACL,OAAO;EACP,QAAQ;EACR,SAAS;EACT,wBAAwB;EACxB,gBAAgB;EAChB,wBAAwB;EACxB,gBAAgB;EAChB,wBAAwB;EACxB,aAAa;EACb,iBAAiB;CACnB;CACA,OAAO;EAAE,OAAO;EAAO,QAAQ;EAAU,cAAc;EAAS,iBAAiB;CAAQ;CACzF,MAAM;EAAE,OAAO;EAAO,QAAQ;EAAU,cAAc;EAAS,iBAAiB;CAAa;CAC7F,QAAQ;EACN,OAAO;EACP,QAAQ;EACR,kBAAkB;EAClB,cAAc;EACd,iBAAiB;CACnB;AACF,CAAC;;AAGD,IAAa,iBAAiB,0BAAW,QAAA,SAAwD;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,YAAAA,aAAA,QAAA,WAAA;CAAA,MAAhC,OAAIC,UAAA,QAAA,MAAA,IAAA;CACnE,aAAa;EACX,MAAM,EAAE,OAAO,YAAY,OAAO,cAAc,SAAS,WAAU,MAAA,KAAM;EACzE,OAAAC,YAAA,QAAAC,WAEQ,WACF;GAAE,IAAI,CAAC,qBAAqB,MAAM,aAAa,IAAI;GAAG,OAAO;GAAY;EAAM,GAC/E,MACA,EAAE,eAAe,KAAK,CACxB,GAAC,EAAA,cACW,KAAI,CAAA,GAAA,CAAAD,YAAA,QAEN,WAAmB,EAAE,IAAI,qBAAqB,KAAK,GAAC,UAAA,KAAW,GAAC;GAAAA,YAAA,QAC9D,IAAI,MAAM,qBAAqB,KAAK,GAAC,IAAA;GAAAA,YAAA,QACrC,IAAI,MAAM,qBAAqB,IAAI,GAAC,IAAA;GAAAA,YAAA,QACpC,IAAI,MAAM,qBAAqB,MAAM,GAAC,IAAA;EAAA,CAAA,CAAA,CAAA;CAIxD;AACF,GAAC;CAAA,MAAA;CAAA,OAAA,CAAA,SAAA,WAAA;AAAA,CAAA"}
1
+ {"version":3,"file":"ThemeThumbnail.js","names":["_vtp_readonlyProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../src/theme-customize/ThemeThumbnail.tsx"],"sourcesContent":["/**\n * 主题缩略图(span):用这套主题画一个缩小的页面:底色上一张卡片,卡片里标题、正文两行字和一个品牌色按钮。\n * 主题选择器、主题列表里代替主题名旁边的色点,一眼看出底色、表面、文字与品牌色的搭配。\n *\n * <ThemeThumbnail theme={oceanTheme} />\n *\n * 颜色来自套在它上面的主题变量(themeAttrs),换主题不用重画;纯装饰,对读屏隐藏,名字由使用方写在旁边。\n * 尺寸用 em,随字号缩放。部件:Root(span)、Card(卡片)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { mergeAttrs, type PartProps } from '../utils/props';\nimport { swatchStyles } from '../utils/style/swatch-styles';\nimport { themeAttrs, type Theme } from '../config/theme/theme';\n\n/** 未声明的属性落到外层 span 上 */\nexport interface ThemeThumbnailProps extends PartProps<'span', 'aria-hidden'> {\n /** 画哪一套主题 */\n theme: Theme;\n /** 卡片的部件属性 */\n propsCard?: PartProps<'span'>;\n}\n\n/** ThemeThumbnail 的样式:root、card、title、line、button */\nexport const themeThumbnailStyles = css.create({\n root: {\n display: 'inline-flex',\n alignItems: 'flex-end',\n justifyContent: 'flex-end',\n flexShrink: 0,\n width: '6em',\n height: '3.75em',\n padding: '0.5em 0 0 0.75em',\n overflow: 'hidden',\n borderRadius: '_md',\n backgroundColor: '_background',\n },\n // 卡片从右下角探出来:像页面的一角\n card: {\n display: 'flex',\n flexDirection: 'column',\n gap: '0.3em',\n width: '100%',\n height: '100%',\n padding: '0.5em',\n borderStartStartRadius: '_sm',\n borderTopWidth: '_xs',\n borderInlineStartWidth: '_xs',\n borderTopStyle: 'solid',\n borderInlineStartStyle: 'solid',\n borderColor: '_border',\n backgroundColor: '_surfaceRaised',\n },\n title: { width: '70%', height: '0.35em', borderRadius: '_full', backgroundColor: '_text' },\n line: { width: '90%', height: '0.25em', borderRadius: '_full', backgroundColor: '_textMuted' },\n button: {\n width: '45%',\n height: '0.6em',\n marginBlockStart: 'auto',\n borderRadius: '_sm',\n backgroundColor: '_accent',\n },\n});\n\n/** 主题缩略图:缩小的页面一角,颜色取自这套主题 */\nexport const ThemeThumbnail = _component(({ theme, propsCard, ...rest }: ThemeThumbnailProps) => {\n return () => {\n const { class: themeClass, style, 'data-theme': name } = themeAttrs(theme);\n return (\n <span\n {...mergeAttrs<'span'>(\n { sx: [themeThumbnailStyles.root, swatchStyles.ring], class: themeClass, style },\n rest,\n { 'aria-hidden': true },\n )}\n data-theme={name}\n >\n <span {...mergeAttrs<'span'>({ sx: themeThumbnailStyles.card }, propsCard)}>\n <span {...css.attrs(themeThumbnailStyles.title)} />\n <span {...css.attrs(themeThumbnailStyles.line)} />\n <span {...css.attrs(themeThumbnailStyles.button)} />\n </span>\n </span>\n );\n };\n});\n"],"mappings":";;;;;;;;;AAwBA,IAAa,uBAAuB,IAAI,OAAO;CAC7C,MAAM;EACJ,SAAS;EACT,YAAY;EACZ,gBAAgB;EAChB,YAAY;EACZ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,UAAU;EACV,cAAc;EACd,iBAAiB;CACnB;CAEA,MAAM;EACJ,SAAS;EACT,eAAe;EACf,KAAK;EACL,OAAO;EACP,QAAQ;EACR,SAAS;EACT,wBAAwB;EACxB,gBAAgB;EAChB,wBAAwB;EACxB,gBAAgB;EAChB,wBAAwB;EACxB,aAAa;EACb,iBAAiB;CACnB;CACA,OAAO;EAAE,OAAO;EAAO,QAAQ;EAAU,cAAc;EAAS,iBAAiB;CAAQ;CACzF,MAAM;EAAE,OAAO;EAAO,QAAQ;EAAU,cAAc;EAAS,iBAAiB;CAAa;CAC7F,QAAQ;EACN,OAAO;EACP,QAAQ;EACR,kBAAkB;EAClB,cAAc;EACd,iBAAiB;CACnB;AACF,CAAC;;AAGD,IAAa,iBAAiB,0BAAW,QAAA,SAAwD;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,YAAAA,aAAA,QAAA,WAAA;CAAA,MAAhC,OAAIC,UAAA,QAAA,MAAA,IAAA;CACnE,aAAa;EACX,MAAM,EAAE,OAAO,YAAY,OAAO,cAAc,SAAS,WAAU,MAAA,KAAM;EACzE,OAAAC,YAAA,QAAAC,cAEQ,WACF;GAAE,IAAI,CAAC,qBAAqB,MAAM,aAAa,IAAI;GAAG,OAAO;GAAY;EAAM,GAC/E,MACA,EAAE,eAAe,KAAK,CACxB,GAAC,EAAA,cACW,KAAI,CAAA,GAAA,CAAAD,YAAA,QAEN,WAAmB,EAAE,IAAI,qBAAqB,KAAK,GAAC,UAAA,KAAW,GAAC;GAAAA,YAAA,QAC9D,IAAI,MAAM,qBAAqB,KAAK,GAAC,IAAA;GAAAA,YAAA,QACrC,IAAI,MAAM,qBAAqB,IAAI,GAAC,IAAA;GAAAA,YAAA,QACpC,IAAI,MAAM,qBAAqB,MAAM,GAAC,IAAA;EAAA,CAAA,CAAA,CAAA;CAIxD;AACF,GAAC;CAAA,MAAA;CAAA,OAAA,CAAA,SAAA,WAAA;AAAA,CAAA"}
@@ -1,7 +1,7 @@
1
1
  import { colors } from "../../config/theme/tokens.js";
2
2
  import { ShaderBackground } from "./ShaderBackground.js";
3
- import { createVNode, mergeProps } from "vue";
4
- import { _component, effect, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
3
+ import { createVNode } from "vue";
4
+ import { _component, effect, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
5
5
  //#region src/three/background/AuroraBackground.tsx
6
6
  /** 极光的默认色板:绿、青、品牌色、紫 */
7
7
  var AURORA_PALETTE = [
@@ -55,7 +55,7 @@ var AuroraBackground = /*#__PURE__*/ _component((_props, _ctx) => {
55
55
  uniforms.uIntensity.value = intensity.value;
56
56
  uniforms.uHeight.value = height.value;
57
57
  }, "pre");
58
- return () => createVNode(ShaderBackground, mergeProps(rest, {
58
+ return () => createVNode(ShaderBackground, mergeJsxProps(rest, {
59
59
  "fragmentShader": AURORA_SHADER,
60
60
  "uniforms": uniforms,
61
61
  "palette": palette.value,
@@ -1 +1 @@
1
- {"version":3,"file":"AuroraBackground.js","names":["_vtp_readonlyProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../../src/three/background/AuroraBackground.tsx"],"sourcesContent":["/**\n * 极光(div):几层半透明的光幕在区域上方缓缓飘动,下缘清晰、向上渐隐,带细密的竖向光丝。\n * 背景是透明的,叠在页面底色上:暗色主题里像夜空的极光,亮色主题里是一层淡淡的彩色雾。\n *\n * <AuroraBackground sx={styles.hero}>\n * <h1>标题</h1>\n * </AuroraBackground>\n *\n * 默认色板绿、青、品牌色、紫(取自图表色板,跟随主题);指针左右移动时光幕跟着轻轻偏移。\n *\n * 部件:Root(div)、Canvas(ThreeCanvas)、Content(div)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { colors } from '../../config/theme/tokens';\nimport type { EffectProps } from '../core/EffectSurface';\nimport { ShaderBackground } from './ShaderBackground';\n\n/** 极光的默认色板:绿、青、品牌色、紫 */\nexport const AURORA_PALETTE: readonly string[] = [\n colors.chart7,\n colors.chart2,\n colors.accent,\n colors.chart5,\n];\n\n/** 未声明的属性落到外层 div 上 */\nexport interface AuroraBackgroundProps extends EffectProps {\n /** 色板(token 或 CSS 颜色,2–6 个),默认绿、青、品牌色、紫 */\n palette?: readonly string[];\n /**\n * 飘动速度\n * @default 1\n */\n speed?: number;\n /**\n * 亮度(0–1.5)\n * @default 1\n */\n intensity?: number;\n /**\n * 光幕下缘在区域里的高度(0 底部,1 顶部)\n * @default 0.55\n */\n height?: number;\n /**\n * 跟随指针\n * @default true\n */\n interactive?: boolean;\n}\n\nconst AURORA_SHADER = /* glsl */ `\nuniform float uIntensity;\nuniform float uHeight;\n\nvec4 shade(vec2 uv) {\n float aspect = uResolution.x / max(uResolution.y, 1.0);\n float x = uv.x * aspect + uPointer.x * 0.12 * uPointer.z;\n float t = uTime * 0.08;\n vec3 color = vec3(0.0);\n float alpha = 0.0;\n for (int band = 0; band < 3; band++) {\n float fb = float(band);\n float wave = fbm(vec3(x * (0.7 + fb * 0.25) + fb * 3.1, fb * 1.7, t * (1.0 + fb * 0.35)));\n float edge = uHeight + fb * 0.07 + wave * 0.2;\n float d = uv.y - edge;\n // 下缘清晰、向上指数渐隐\n float curtain = smoothstep(-0.025, 0.015, d) * exp(-max(d, 0.0) * (3.2 + fb * 1.6));\n float rays = 0.55 + 0.45 * snoise(vec3(x * 9.0 + fb * 11.0, t * 3.0, fb));\n float a = curtain * rays * (0.75 - fb * 0.18);\n color += themePalette(clamp(0.15 + fb * 0.3 + wave * 0.35, 0.0, 1.0)) * a;\n alpha += a;\n }\n // 暗色主题里光更亮,亮色主题里收敛成雾\n float strength = uIntensity * mix(0.55, 1.0, uDark);\n return vec4(color / max(alpha, 1e-4), clamp(alpha * strength, 0.0, 1.0));\n}\n`;\n\n/** 极光:透明背景上缓缓飘动的几层光幕 */\nexport const AuroraBackground = _component(\n ({\n palette = AURORA_PALETTE,\n speed = 1,\n intensity = 1,\n height = 0.55,\n interactive = true,\n resolution = 0.5,\n ...rest\n }: AuroraBackgroundProps) => {\n const uniforms = { uIntensity: { value: 0 }, uHeight: { value: 0 } };\n _effect.pre(() => {\n uniforms.uIntensity.value = intensity;\n uniforms.uHeight.value = height;\n });\n return () => (\n <ShaderBackground\n {...rest}\n fragmentShader={AURORA_SHADER}\n uniforms={uniforms}\n palette={palette}\n speed={speed}\n interactive={interactive}\n resolution={resolution}\n />\n );\n },\n);\n"],"mappings":";;;;;;AAkBA,IAAa,iBAAoC;CAC/C,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;AAAM;;AA6Bf,IAAM,gBAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BjC,IAAa,mBAAmB,0BAC9B,QAAA,SAQ6B;CAAA,MAAA,UAAAA,aAAA,QAAA,iBAPjB,cAAc;CAAA,MAAA,QAAAA,aAAA,QAAA,SAChB,CAAC;CAAA,MAAA,YAAAA,aAAA,QAAA,aACG,CAAC;CAAA,MAAA,SAAAA,aAAA,QAAA,UACJ,GAAI;CAAA,MAAA,cAAAA,aAAA,QAAA,eACC,IAAI;CAAA,MAAA,aAAAA,aAAA,QAAA,cACL,EAAG;CAAA,MACb,OAAIC,UAAA,QAAA,MAAA,IAAA;CAEP,MAAM,WAAW;EAAE,YAAY,EAAE,OAAO,EAAE;EAAG,SAAS,EAAE,OAAO,EAAE;CAAE;CACnE,aAAkB;EAChB,SAAS,WAAW,QAAK,UAAA;EACzB,SAAS,QAAQ,QAAK,OAAA;CACxB,GAAC,KAAA;CACD,aAAOC,YAAA,kBAAAC,WAEC,MAAI;EAAA,kBACQ;EAAa,YACnB;EAAQ,WAAA,QAAA;EAAA,SAAA,MAAA;EAAA,eAAA,YAAA;EAAA,cAAA,WAAA;CAAA,CAAA,GAAA,IAAA;AAOxB,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
1
+ {"version":3,"file":"AuroraBackground.js","names":["_vtp_readonlyProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../../src/three/background/AuroraBackground.tsx"],"sourcesContent":["/**\n * 极光(div):几层半透明的光幕在区域上方缓缓飘动,下缘清晰、向上渐隐,带细密的竖向光丝。\n * 背景是透明的,叠在页面底色上:暗色主题里像夜空的极光,亮色主题里是一层淡淡的彩色雾。\n *\n * <AuroraBackground sx={styles.hero}>\n * <h1>标题</h1>\n * </AuroraBackground>\n *\n * 默认色板绿、青、品牌色、紫(取自图表色板,跟随主题);指针左右移动时光幕跟着轻轻偏移。\n *\n * 部件:Root(div)、Canvas(ThreeCanvas)、Content(div)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { colors } from '../../config/theme/tokens';\nimport type { EffectProps } from '../core/EffectSurface';\nimport { ShaderBackground } from './ShaderBackground';\n\n/** 极光的默认色板:绿、青、品牌色、紫 */\nexport const AURORA_PALETTE: readonly string[] = [\n colors.chart7,\n colors.chart2,\n colors.accent,\n colors.chart5,\n];\n\n/** 未声明的属性落到外层 div 上 */\nexport interface AuroraBackgroundProps extends EffectProps {\n /** 色板(token 或 CSS 颜色,2–6 个),默认绿、青、品牌色、紫 */\n palette?: readonly string[];\n /**\n * 飘动速度\n * @default 1\n */\n speed?: number;\n /**\n * 亮度(0–1.5)\n * @default 1\n */\n intensity?: number;\n /**\n * 光幕下缘在区域里的高度(0 底部,1 顶部)\n * @default 0.55\n */\n height?: number;\n /**\n * 跟随指针\n * @default true\n */\n interactive?: boolean;\n}\n\nconst AURORA_SHADER = /* glsl */ `\nuniform float uIntensity;\nuniform float uHeight;\n\nvec4 shade(vec2 uv) {\n float aspect = uResolution.x / max(uResolution.y, 1.0);\n float x = uv.x * aspect + uPointer.x * 0.12 * uPointer.z;\n float t = uTime * 0.08;\n vec3 color = vec3(0.0);\n float alpha = 0.0;\n for (int band = 0; band < 3; band++) {\n float fb = float(band);\n float wave = fbm(vec3(x * (0.7 + fb * 0.25) + fb * 3.1, fb * 1.7, t * (1.0 + fb * 0.35)));\n float edge = uHeight + fb * 0.07 + wave * 0.2;\n float d = uv.y - edge;\n // 下缘清晰、向上指数渐隐\n float curtain = smoothstep(-0.025, 0.015, d) * exp(-max(d, 0.0) * (3.2 + fb * 1.6));\n float rays = 0.55 + 0.45 * snoise(vec3(x * 9.0 + fb * 11.0, t * 3.0, fb));\n float a = curtain * rays * (0.75 - fb * 0.18);\n color += themePalette(clamp(0.15 + fb * 0.3 + wave * 0.35, 0.0, 1.0)) * a;\n alpha += a;\n }\n // 暗色主题里光更亮,亮色主题里收敛成雾\n float strength = uIntensity * mix(0.55, 1.0, uDark);\n return vec4(color / max(alpha, 1e-4), clamp(alpha * strength, 0.0, 1.0));\n}\n`;\n\n/** 极光:透明背景上缓缓飘动的几层光幕 */\nexport const AuroraBackground = _component(\n ({\n palette = AURORA_PALETTE,\n speed = 1,\n intensity = 1,\n height = 0.55,\n interactive = true,\n resolution = 0.5,\n ...rest\n }: AuroraBackgroundProps) => {\n const uniforms = { uIntensity: { value: 0 }, uHeight: { value: 0 } };\n _effect.pre(() => {\n uniforms.uIntensity.value = intensity;\n uniforms.uHeight.value = height;\n });\n return () => (\n <ShaderBackground\n {...rest}\n fragmentShader={AURORA_SHADER}\n uniforms={uniforms}\n palette={palette}\n speed={speed}\n interactive={interactive}\n resolution={resolution}\n />\n );\n },\n);\n"],"mappings":";;;;;;AAkBA,IAAa,iBAAoC;CAC/C,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;AAAM;;AA6Bf,IAAM,gBAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BjC,IAAa,mBAAmB,0BAC9B,QAAA,SAQ6B;CAAA,MAAA,UAAAA,aAAA,QAAA,iBAPjB,cAAc;CAAA,MAAA,QAAAA,aAAA,QAAA,SAChB,CAAC;CAAA,MAAA,YAAAA,aAAA,QAAA,aACG,CAAC;CAAA,MAAA,SAAAA,aAAA,QAAA,UACJ,GAAI;CAAA,MAAA,cAAAA,aAAA,QAAA,eACC,IAAI;CAAA,MAAA,aAAAA,aAAA,QAAA,cACL,EAAG;CAAA,MACb,OAAIC,UAAA,QAAA,MAAA,IAAA;CAEP,MAAM,WAAW;EAAE,YAAY,EAAE,OAAO,EAAE;EAAG,SAAS,EAAE,OAAO,EAAE;CAAE;CACnE,aAAkB;EAChB,SAAS,WAAW,QAAK,UAAA;EACzB,SAAS,QAAQ,QAAK,OAAA;CACxB,GAAC,KAAA;CACD,aAAOC,YAAA,kBAAAC,cAEC,MAAI;EAAA,kBACQ;EAAa,YACnB;EAAQ,WAAA,QAAA;EAAA,SAAA,MAAA;EAAA,eAAA,YAAA;EAAA,cAAA,WAAA;CAAA,CAAA,GAAA,IAAA;AAOxB,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
@@ -1,6 +1,6 @@
1
1
  import { SHADER_PALETTE, ShaderBackground } from "./ShaderBackground.js";
2
- import { createVNode, mergeProps } from "vue";
3
- import { _component, effect, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
2
+ import { createVNode } from "vue";
3
+ import { _component, effect, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
4
4
  //#region src/three/background/MeshGradient.tsx
5
5
  /** 未声明的属性落到外层 div 上 */
6
6
  var MESH_GRADIENT_SHADER = `
@@ -51,7 +51,7 @@ var MeshGradient = /*#__PURE__*/ _component((_props, _ctx) => {
51
51
  uniforms.uDistortion.value = distortion.value;
52
52
  uniforms.uGrain.value = grain.value;
53
53
  }, "pre");
54
- return () => createVNode(ShaderBackground, mergeProps(rest, {
54
+ return () => createVNode(ShaderBackground, mergeJsxProps(rest, {
55
55
  "fragmentShader": MESH_GRADIENT_SHADER,
56
56
  "uniforms": uniforms,
57
57
  "palette": palette.value,
@@ -1 +1 @@
1
- {"version":3,"file":"MeshGradient.js","names":["_vtp_readonlyProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../../src/three/background/MeshGradient.tsx"],"sourcesContent":["/**\n * 流动的网格渐变(div):色板里的每个颜色是一团缓慢游走的光斑,彼此柔和地融合,再加一层噪声扭曲与细颗粒。\n * 适合首页标题区、登录页、卡片的封面。\n *\n * <MeshGradient sx={styles.hero}>\n * <h1>标题</h1>\n * </MeshGradient>\n *\n * 默认色板是品牌色加图表色板里的几个颜色,切换主题、改品牌色时原地过渡;指针靠近时品牌色那一团被轻轻吸过去。\n * 画面是不透明的:上面的文字自己保证对比度(如加一层半透明的底)。\n *\n * 部件:Root(div)、Canvas(ThreeCanvas)、Content(div)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { ShaderBackground, SHADER_PALETTE } from './ShaderBackground';\nimport type { EffectProps } from '../core/EffectSurface';\n\n/** 未声明的属性落到外层 div 上 */\nexport interface MeshGradientProps extends EffectProps {\n /** 色板(token 或 CSS 颜色,2–6 个),默认品牌色加图表色板 */\n palette?: readonly string[];\n /**\n * 流动速度\n * @default 1\n */\n speed?: number;\n /**\n * 噪声扭曲的程度(0 是圆润的光斑,1 起伏明显)\n * @default 0.6\n */\n distortion?: number;\n /**\n * 颗粒感(0 没有颗粒)\n * @default 0.04\n */\n grain?: number;\n /**\n * 指针靠近时品牌色被吸过去\n * @default true\n */\n interactive?: boolean;\n}\n\nconst MESH_GRADIENT_SHADER = /* glsl */ `\nuniform float uDistortion;\nuniform float uGrain;\n\nvec4 shade(vec2 uv) {\n float aspect = uResolution.x / max(uResolution.y, 1.0);\n vec2 p = (uv - 0.5) * vec2(aspect, 1.0);\n float t = uTime * 0.12;\n p += uDistortion * 0.3 * vec2(snoise(vec3(p * 1.3, t)), snoise(vec3(p * 1.3 + 7.3, t)));\n vec3 sum = vec3(0.0);\n float total = 0.0;\n for (int i = 0; i < THEME_PALETTE_SIZE; i++) {\n if (i >= uColorCount) break;\n float fi = float(i);\n vec2 center = vec2(\n sin(t * (0.9 + fi * 0.23) + fi * 2.4) * 0.42 * aspect,\n cos(t * (0.7 + fi * 0.31) + fi * 1.7) * 0.38\n );\n // 品牌色(第一个)被指针吸过去,其余跟着动一点\n float pull = (i == 0 ? 0.35 : 0.08) * uPointer.z;\n center = mix(center, uPointer.xy * 0.5 * vec2(aspect, 1.0), pull);\n float d = distance(p, center);\n float weight = exp(-d * d * 5.0) + 0.002;\n sum += uColors[i] * weight;\n total += weight;\n }\n vec3 color = sum / total;\n float noise = fract(sin(dot(uv * uResolution, vec2(12.9898, 78.233))) * 43758.5453) - 0.5;\n return vec4(color + noise * uGrain, 1.0);\n}\n`;\n\n/** 流动的网格渐变:主题色板的光斑缓慢游走、融合 */\nexport const MeshGradient = _component(\n ({\n palette = SHADER_PALETTE,\n speed = 1,\n distortion = 0.6,\n grain = 0.04,\n interactive = true,\n resolution = 0.5,\n ...rest\n }: MeshGradientProps) => {\n const uniforms = { uDistortion: { value: 0 }, uGrain: { value: 0 } };\n _effect.pre(() => {\n uniforms.uDistortion.value = distortion;\n uniforms.uGrain.value = grain;\n });\n return () => (\n <ShaderBackground\n {...rest}\n fragmentShader={MESH_GRADIENT_SHADER}\n uniforms={uniforms}\n palette={palette}\n speed={speed}\n interactive={interactive}\n resolution={resolution}\n />\n );\n },\n);\n"],"mappings":";;;;;AA2CA,IAAM,uBAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCxC,IAAa,eAAe,0BAC1B,QAAA,SAQyB;CAAA,MAAA,UAAAA,aAAA,QAAA,iBAPb,cAAc;CAAA,MAAA,QAAAA,aAAA,QAAA,SAChB,CAAC;CAAA,MAAA,aAAAA,aAAA,QAAA,cACI,EAAG;CAAA,MAAA,QAAAA,aAAA,QAAA,SACR,GAAI;CAAA,MAAA,cAAAA,aAAA,QAAA,eACE,IAAI;CAAA,MAAA,aAAAA,aAAA,QAAA,cACL,EAAG;CAAA,MACb,OAAIC,UAAA,QAAA,MAAA,IAAA;CAEP,MAAM,WAAW;EAAE,aAAa,EAAE,OAAO,EAAE;EAAG,QAAQ,EAAE,OAAO,EAAE;CAAE;CACnE,aAAkB;EAChB,SAAS,YAAY,QAAK,WAAA;EAC1B,SAAS,OAAO,QAAK,MAAA;CACvB,GAAC,KAAA;CACD,aAAOC,YAAA,kBAAAC,WAEC,MAAI;EAAA,kBACQ;EAAoB,YAC1B;EAAQ,WAAA,QAAA;EAAA,SAAA,MAAA;EAAA,eAAA,YAAA;EAAA,cAAA,WAAA;CAAA,CAAA,GAAA,IAAA;AAOxB,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
1
+ {"version":3,"file":"MeshGradient.js","names":["_vtp_readonlyProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../../src/three/background/MeshGradient.tsx"],"sourcesContent":["/**\n * 流动的网格渐变(div):色板里的每个颜色是一团缓慢游走的光斑,彼此柔和地融合,再加一层噪声扭曲与细颗粒。\n * 适合首页标题区、登录页、卡片的封面。\n *\n * <MeshGradient sx={styles.hero}>\n * <h1>标题</h1>\n * </MeshGradient>\n *\n * 默认色板是品牌色加图表色板里的几个颜色,切换主题、改品牌色时原地过渡;指针靠近时品牌色那一团被轻轻吸过去。\n * 画面是不透明的:上面的文字自己保证对比度(如加一层半透明的底)。\n *\n * 部件:Root(div)、Canvas(ThreeCanvas)、Content(div)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { ShaderBackground, SHADER_PALETTE } from './ShaderBackground';\nimport type { EffectProps } from '../core/EffectSurface';\n\n/** 未声明的属性落到外层 div 上 */\nexport interface MeshGradientProps extends EffectProps {\n /** 色板(token 或 CSS 颜色,2–6 个),默认品牌色加图表色板 */\n palette?: readonly string[];\n /**\n * 流动速度\n * @default 1\n */\n speed?: number;\n /**\n * 噪声扭曲的程度(0 是圆润的光斑,1 起伏明显)\n * @default 0.6\n */\n distortion?: number;\n /**\n * 颗粒感(0 没有颗粒)\n * @default 0.04\n */\n grain?: number;\n /**\n * 指针靠近时品牌色被吸过去\n * @default true\n */\n interactive?: boolean;\n}\n\nconst MESH_GRADIENT_SHADER = /* glsl */ `\nuniform float uDistortion;\nuniform float uGrain;\n\nvec4 shade(vec2 uv) {\n float aspect = uResolution.x / max(uResolution.y, 1.0);\n vec2 p = (uv - 0.5) * vec2(aspect, 1.0);\n float t = uTime * 0.12;\n p += uDistortion * 0.3 * vec2(snoise(vec3(p * 1.3, t)), snoise(vec3(p * 1.3 + 7.3, t)));\n vec3 sum = vec3(0.0);\n float total = 0.0;\n for (int i = 0; i < THEME_PALETTE_SIZE; i++) {\n if (i >= uColorCount) break;\n float fi = float(i);\n vec2 center = vec2(\n sin(t * (0.9 + fi * 0.23) + fi * 2.4) * 0.42 * aspect,\n cos(t * (0.7 + fi * 0.31) + fi * 1.7) * 0.38\n );\n // 品牌色(第一个)被指针吸过去,其余跟着动一点\n float pull = (i == 0 ? 0.35 : 0.08) * uPointer.z;\n center = mix(center, uPointer.xy * 0.5 * vec2(aspect, 1.0), pull);\n float d = distance(p, center);\n float weight = exp(-d * d * 5.0) + 0.002;\n sum += uColors[i] * weight;\n total += weight;\n }\n vec3 color = sum / total;\n float noise = fract(sin(dot(uv * uResolution, vec2(12.9898, 78.233))) * 43758.5453) - 0.5;\n return vec4(color + noise * uGrain, 1.0);\n}\n`;\n\n/** 流动的网格渐变:主题色板的光斑缓慢游走、融合 */\nexport const MeshGradient = _component(\n ({\n palette = SHADER_PALETTE,\n speed = 1,\n distortion = 0.6,\n grain = 0.04,\n interactive = true,\n resolution = 0.5,\n ...rest\n }: MeshGradientProps) => {\n const uniforms = { uDistortion: { value: 0 }, uGrain: { value: 0 } };\n _effect.pre(() => {\n uniforms.uDistortion.value = distortion;\n uniforms.uGrain.value = grain;\n });\n return () => (\n <ShaderBackground\n {...rest}\n fragmentShader={MESH_GRADIENT_SHADER}\n uniforms={uniforms}\n palette={palette}\n speed={speed}\n interactive={interactive}\n resolution={resolution}\n />\n );\n },\n);\n"],"mappings":";;;;;AA2CA,IAAM,uBAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCxC,IAAa,eAAe,0BAC1B,QAAA,SAQyB;CAAA,MAAA,UAAAA,aAAA,QAAA,iBAPb,cAAc;CAAA,MAAA,QAAAA,aAAA,QAAA,SAChB,CAAC;CAAA,MAAA,aAAAA,aAAA,QAAA,cACI,EAAG;CAAA,MAAA,QAAAA,aAAA,QAAA,SACR,GAAI;CAAA,MAAA,cAAAA,aAAA,QAAA,eACE,IAAI;CAAA,MAAA,aAAAA,aAAA,QAAA,cACL,EAAG;CAAA,MACb,OAAIC,UAAA,QAAA,MAAA,IAAA;CAEP,MAAM,WAAW;EAAE,aAAa,EAAE,OAAO,EAAE;EAAG,QAAQ,EAAE,OAAO,EAAE;CAAE;CACnE,aAAkB;EAChB,SAAS,YAAY,QAAK,WAAA;EAC1B,SAAS,OAAO,QAAK,MAAA;CACvB,GAAC,KAAA;CACD,aAAOC,YAAA,kBAAAC,cAEC,MAAI;EAAA,kBACQ;EAAoB,YAC1B;EAAQ,WAAA,QAAA;EAAA,SAAA,MAAA;EAAA,eAAA,YAAA;EAAA,cAAA,WAAA;CAAA,CAAA,GAAA,IAAA;AAOxB,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
@@ -3,8 +3,8 @@ import { colors } from "../../config/theme/tokens.js";
3
3
  import { useConfig } from "../../config/context.js";
4
4
  import { EffectSurface } from "../core/EffectSurface.js";
5
5
  import { shaderChunks } from "../core/shaders.js";
6
- import { createVNode, mergeProps } from "vue";
7
- import { _component, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
6
+ import { createVNode } from "vue";
7
+ import { _component, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
8
8
  import { Mesh, PlaneGeometry, ShaderMaterial, Vector2, Vector3 } from "three";
9
9
  //#region src/three/background/ShaderBackground.tsx
10
10
  /** 着色器背景的默认色板:品牌色加图表色板里的紫、粉、青 */
@@ -52,7 +52,7 @@ var ShaderBackground = /*#__PURE__*/ _component((_props, _ctx) => {
52
52
  const interactive = readonlyProp(_props, "interactive", true);
53
53
  const rest = restProps(_props, _ctx, true);
54
54
  const config = useConfig();
55
- return () => createVNode(EffectSurface, mergeProps(rest, {
55
+ return () => createVNode(EffectSurface, mergeJsxProps(rest, {
56
56
  "sceneKey": `${fragmentShader.value}|${palette.value.join(",")}`,
57
57
  "setup": _cache[0] || (_cache[0] = ({ scene, size, pointer, themeColors, themeColorList }) => {
58
58
  const { background } = themeColors({ background: colors.background });
@@ -1 +1 @@
1
- {"version":3,"file":"ShaderBackground.js","names":["_vtp_readonlyProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../../src/three/background/ShaderBackground.tsx"],"sourcesContent":["/**\n * 着色器背景:写一个片段着色器函数,主题色、时间、尺寸、指针自动作为 uniform 传入,画满整块区域。\n * MeshGradient、AuroraBackground 都建在它上面。\n *\n * <ShaderBackground\n * sx={styles.hero}\n * fragmentShader={`\n * vec4 shade(vec2 uv) {\n * float n = fbm(vec3(uv * 3.0, uTime * 0.2)) * 0.5 + 0.5;\n * return vec4(themePalette(n), 1.0);\n * }\n * `}\n * >\n * <h1>内容叠在上面</h1>\n * </ShaderBackground>\n *\n * 着色器只写 `vec4 shade(vec2 uv)`(uv 是 0–1,左下角为原点;返回不预乘的颜色与透明度),可以直接用:\n * - uTime(秒,已乘 speed)、uResolution(CSS 像素)、uPointer(xy 是 -1–1 的指针位置,z 是指针在区域内的程度 0–1)、\n * uDark(暗色主题为 1)、uBackground(主题背景色);\n * - palette 的颜色(uColors、uColorCount)与 themePalette(t)、snoise、fbm(shaderChunks)。\n * 颜色在线性空间里计算,输出时按渲染器的色彩空间转换。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { Mesh, PlaneGeometry, ShaderMaterial, Vector2, Vector3, type IUniform } from 'three';\nimport { useConfig } from '../../config/context';\nimport { colors } from '../../config/theme/tokens';\nimport { clamp } from '../../utils/data/number';\nimport { EffectSurface, type EffectProps } from '../core/EffectSurface';\nimport { shaderChunks, THEME_PALETTE_SIZE } from '../core/shaders';\n\n/** 着色器背景的默认色板:品牌色加图表色板里的紫、粉、青 */\nexport const SHADER_PALETTE: readonly string[] = [\n colors.accent,\n colors.chart5,\n colors.chart4,\n colors.chart6,\n];\n\n/** 未声明的属性落到外层 div 上 */\nexport interface ShaderBackgroundProps extends EffectProps {\n /** 片段着色器:定义 `vec4 shade(vec2 uv)`,可用的 uniform 见文件开头;变了会重建 */\n fragmentShader: string;\n /** 额外的 uniform:改它们的 value 就能实时生效 */\n uniforms?: Record<string, IUniform>;\n /** 色板(token 或 CSS 颜色,最多 6 个),传给 uColors 与 themePalette;默认品牌色加图表色板;变了会重建 */\n palette?: readonly string[];\n /**\n * 时间流速:uTime = 秒数 × speed\n * @default 1\n */\n speed?: number;\n /**\n * 跟随指针(uPointer);关掉时 uPointer.z 始终为 0\n * @default true\n */\n interactive?: boolean;\n}\n\nconst vertexShader = /* glsl */ `\nvarying vec2 vUv;\nvoid main() {\n vUv = uv;\n gl_Position = vec4(position.xy, 0.0, 1.0);\n}\n`;\n\n/** 把使用方的 shade 函数包成完整的片段着色器 */\nfunction fragment(source: string) {\n return /* glsl */ `\nuniform float uTime;\nuniform vec2 uResolution;\nuniform vec3 uPointer;\nuniform float uDark;\nuniform vec3 uBackground;\nvarying vec2 vUv;\n${shaderChunks.simplexNoise}\n${shaderChunks.fbm}\n${shaderChunks.themePalette}\n${source}\nvoid main() {\n gl_FragColor = shade(vUv);\n #include <colorspace_fragment>\n #include <premultiplied_alpha_fragment>\n}\n`;\n}\n\n/** 着色器背景:主题色、时间、指针自动传入的全屏片段着色器 */\nexport const ShaderBackground = _component(\n ({\n fragmentShader,\n uniforms,\n palette = SHADER_PALETTE,\n speed = 1,\n interactive = true,\n ...rest\n }: ShaderBackgroundProps) => {\n const config = useConfig();\n\n return () => (\n <EffectSurface\n {...rest}\n sceneKey={`${fragmentShader}|${palette.join(',')}`}\n setup={({ scene, size, pointer, themeColors, themeColorList }) => {\n const { background } = themeColors({ background: colors.background });\n // 没给颜色时色板全是背景色\n const list = themeColorList(\n palette.length > 0 ? palette : [colors.background],\n THEME_PALETTE_SIZE,\n );\n const builtin = {\n uTime: { value: 0 },\n uResolution: { value: new Vector2(size.width, size.height) },\n uPointer: { value: new Vector3() },\n uDark: { value: 0 },\n uBackground: { value: background },\n uColors: { value: list },\n uColorCount: { value: clamp(palette.length, 1, THEME_PALETTE_SIZE) },\n };\n const material = new ShaderMaterial({\n vertexShader,\n fragmentShader: fragment(fragmentShader),\n uniforms: { ...builtin, ...uniforms },\n transparent: true,\n premultipliedAlpha: true,\n depthTest: false,\n depthWrite: false,\n });\n const quad = new Mesh(new PlaneGeometry(2, 2), material);\n quad.frustumCulled = false;\n scene.add(quad);\n return {\n frame: ({ time }) => {\n builtin.uTime.value = time * speed;\n builtin.uPointer.value.set(pointer.x, pointer.y, interactive ? pointer.strength : 0);\n builtin.uDark.value = config.theme.colorScheme === 'dark' ? 1 : 0;\n },\n resize: (next) => builtin.uResolution.value.set(next.width, next.height),\n };\n }}\n />\n );\n },\n);\n"],"mappings":";;;;;;;;;;AA+BA,IAAa,iBAAoC;CAC/C,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;AAAM;;AAuBf,IAAM,eAA0B;;;;;;;;AAShC,SAAS,SAAS,QAAgB;CAChC,OAAkB;;;;;;;EAOlB,aAAa,aAAY;EACzB,aAAa,IAAG;EAChB,aAAa,aAAY;EACzB,OAAM;;;;;;;AAOR;;AAGA,IAAa,mBAAmB,0BAC9B,QAAA,SAO6B;CAAA,MAAA,SAAA,CAAA;CAAA,MAAA,iBAAAA,aAAA,QAAA,gBAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,UAAAA,aAAA,QAAA,iBAJjB,cAAc;CAAA,MAAA,QAAAA,aAAA,QAAA,SAChB,CAAC;CAAA,MAAA,cAAAA,aAAA,QAAA,eACK,IAAI;CAAA,MACf,OAAIC,UAAA,QAAA,MAAA,IAAA;CAEP,MAAM,SAAS,UAAU;CAEzB,aAAOC,YAAA,eAAAC,WAEC,MAAI;EAAA,YACE,GAAA,eAAA,MAAA,GAAqB,QAAA,MAAQ,KAAK,GAAG;EAAG,SAAA,OAAA,OAAA,OAAA,MAC1C,EAAE,OAAO,MAAM,SAAS,aAAa,qBAAqB;GAChE,MAAM,EAAE,eAAe,YAAY,EAAE,YAAY,OAAO,WAAW,CAAC;GAEpE,MAAM,OAAO,eACX,QAAA,MAAQ,SAAS,IAAC,QAAA,QAAa,CAAC,OAAO,UAAU,GAAA,CAEnD;GACA,MAAM,UAAU;IACd,OAAO,EAAE,OAAO,EAAE;IAClB,aAAa,EAAE,OAAO,IAAI,QAAQ,KAAK,OAAO,KAAK,MAAM,EAAE;IAC3D,UAAU,EAAE,OAAO,IAAI,QAAQ,EAAE;IACjC,OAAO,EAAE,OAAO,EAAE;IAClB,aAAa,EAAE,OAAO,WAAW;IACjC,SAAS,EAAE,OAAO,KAAK;IACvB,aAAa,EAAE,OAAO,MAAM,QAAA,MAAQ,QAAQ,GAAA,CAAqB,EAAE;GACrE;GACA,MAAM,WAAW,IAAI,eAAe;IAClC;IACA,gBAAgB,SAAQ,eAAA,KAAe;IACvC,UAAU;KAAE,GAAG;KAAS,GAAA,SAAA;IAAY;IACpC,aAAa;IACb,oBAAoB;IACpB,WAAW;IACX,YAAY;GACd,CAAC;GACD,MAAM,OAAO,IAAI,KAAK,IAAI,cAAc,GAAG,CAAC,GAAG,QAAQ;GACvD,KAAK,gBAAgB;GACrB,MAAM,IAAI,IAAI;GACd,OAAO;IACL,QAAQ,EAAE,WAAW;KACnB,QAAQ,MAAM,QAAQ,OAAI,MAAA;KAC1B,QAAQ,SAAS,MAAM,IAAI,QAAQ,GAAG,QAAQ,GAAG,YAAA,QAAc,QAAQ,WAAW,CAAC;KACnF,QAAQ,MAAM,QAAQ,OAAO,MAAM,gBAAgB,SAAS,IAAI;IAClE;IACA,SAAS,SAAS,QAAQ,YAAY,MAAM,IAAI,KAAK,OAAO,KAAK,MAAM;GACzE;EACF;CAAC,CAAA,GAAA,IAAA;AAGP,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
1
+ {"version":3,"file":"ShaderBackground.js","names":["_vtp_readonlyProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../../src/three/background/ShaderBackground.tsx"],"sourcesContent":["/**\n * 着色器背景:写一个片段着色器函数,主题色、时间、尺寸、指针自动作为 uniform 传入,画满整块区域。\n * MeshGradient、AuroraBackground 都建在它上面。\n *\n * <ShaderBackground\n * sx={styles.hero}\n * fragmentShader={`\n * vec4 shade(vec2 uv) {\n * float n = fbm(vec3(uv * 3.0, uTime * 0.2)) * 0.5 + 0.5;\n * return vec4(themePalette(n), 1.0);\n * }\n * `}\n * >\n * <h1>内容叠在上面</h1>\n * </ShaderBackground>\n *\n * 着色器只写 `vec4 shade(vec2 uv)`(uv 是 0–1,左下角为原点;返回不预乘的颜色与透明度),可以直接用:\n * - uTime(秒,已乘 speed)、uResolution(CSS 像素)、uPointer(xy 是 -1–1 的指针位置,z 是指针在区域内的程度 0–1)、\n * uDark(暗色主题为 1)、uBackground(主题背景色);\n * - palette 的颜色(uColors、uColorCount)与 themePalette(t)、snoise、fbm(shaderChunks)。\n * 颜色在线性空间里计算,输出时按渲染器的色彩空间转换。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { Mesh, PlaneGeometry, ShaderMaterial, Vector2, Vector3, type IUniform } from 'three';\nimport { useConfig } from '../../config/context';\nimport { colors } from '../../config/theme/tokens';\nimport { clamp } from '../../utils/data/number';\nimport { EffectSurface, type EffectProps } from '../core/EffectSurface';\nimport { shaderChunks, THEME_PALETTE_SIZE } from '../core/shaders';\n\n/** 着色器背景的默认色板:品牌色加图表色板里的紫、粉、青 */\nexport const SHADER_PALETTE: readonly string[] = [\n colors.accent,\n colors.chart5,\n colors.chart4,\n colors.chart6,\n];\n\n/** 未声明的属性落到外层 div 上 */\nexport interface ShaderBackgroundProps extends EffectProps {\n /** 片段着色器:定义 `vec4 shade(vec2 uv)`,可用的 uniform 见文件开头;变了会重建 */\n fragmentShader: string;\n /** 额外的 uniform:改它们的 value 就能实时生效 */\n uniforms?: Record<string, IUniform>;\n /** 色板(token 或 CSS 颜色,最多 6 个),传给 uColors 与 themePalette;默认品牌色加图表色板;变了会重建 */\n palette?: readonly string[];\n /**\n * 时间流速:uTime = 秒数 × speed\n * @default 1\n */\n speed?: number;\n /**\n * 跟随指针(uPointer);关掉时 uPointer.z 始终为 0\n * @default true\n */\n interactive?: boolean;\n}\n\nconst vertexShader = /* glsl */ `\nvarying vec2 vUv;\nvoid main() {\n vUv = uv;\n gl_Position = vec4(position.xy, 0.0, 1.0);\n}\n`;\n\n/** 把使用方的 shade 函数包成完整的片段着色器 */\nfunction fragment(source: string) {\n return /* glsl */ `\nuniform float uTime;\nuniform vec2 uResolution;\nuniform vec3 uPointer;\nuniform float uDark;\nuniform vec3 uBackground;\nvarying vec2 vUv;\n${shaderChunks.simplexNoise}\n${shaderChunks.fbm}\n${shaderChunks.themePalette}\n${source}\nvoid main() {\n gl_FragColor = shade(vUv);\n #include <colorspace_fragment>\n #include <premultiplied_alpha_fragment>\n}\n`;\n}\n\n/** 着色器背景:主题色、时间、指针自动传入的全屏片段着色器 */\nexport const ShaderBackground = _component(\n ({\n fragmentShader,\n uniforms,\n palette = SHADER_PALETTE,\n speed = 1,\n interactive = true,\n ...rest\n }: ShaderBackgroundProps) => {\n const config = useConfig();\n\n return () => (\n <EffectSurface\n {...rest}\n sceneKey={`${fragmentShader}|${palette.join(',')}`}\n setup={({ scene, size, pointer, themeColors, themeColorList }) => {\n const { background } = themeColors({ background: colors.background });\n // 没给颜色时色板全是背景色\n const list = themeColorList(\n palette.length > 0 ? palette : [colors.background],\n THEME_PALETTE_SIZE,\n );\n const builtin = {\n uTime: { value: 0 },\n uResolution: { value: new Vector2(size.width, size.height) },\n uPointer: { value: new Vector3() },\n uDark: { value: 0 },\n uBackground: { value: background },\n uColors: { value: list },\n uColorCount: { value: clamp(palette.length, 1, THEME_PALETTE_SIZE) },\n };\n const material = new ShaderMaterial({\n vertexShader,\n fragmentShader: fragment(fragmentShader),\n uniforms: { ...builtin, ...uniforms },\n transparent: true,\n premultipliedAlpha: true,\n depthTest: false,\n depthWrite: false,\n });\n const quad = new Mesh(new PlaneGeometry(2, 2), material);\n quad.frustumCulled = false;\n scene.add(quad);\n return {\n frame: ({ time }) => {\n builtin.uTime.value = time * speed;\n builtin.uPointer.value.set(pointer.x, pointer.y, interactive ? pointer.strength : 0);\n builtin.uDark.value = config.theme.colorScheme === 'dark' ? 1 : 0;\n },\n resize: (next) => builtin.uResolution.value.set(next.width, next.height),\n };\n }}\n />\n );\n },\n);\n"],"mappings":";;;;;;;;;;AA+BA,IAAa,iBAAoC;CAC/C,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;AAAM;;AAuBf,IAAM,eAA0B;;;;;;;;AAShC,SAAS,SAAS,QAAgB;CAChC,OAAkB;;;;;;;EAOlB,aAAa,aAAY;EACzB,aAAa,IAAG;EAChB,aAAa,aAAY;EACzB,OAAM;;;;;;;AAOR;;AAGA,IAAa,mBAAmB,0BAC9B,QAAA,SAO6B;CAAA,MAAA,SAAA,CAAA;CAAA,MAAA,iBAAAA,aAAA,QAAA,gBAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,UAAAA,aAAA,QAAA,iBAJjB,cAAc;CAAA,MAAA,QAAAA,aAAA,QAAA,SAChB,CAAC;CAAA,MAAA,cAAAA,aAAA,QAAA,eACK,IAAI;CAAA,MACf,OAAIC,UAAA,QAAA,MAAA,IAAA;CAEP,MAAM,SAAS,UAAU;CAEzB,aAAOC,YAAA,eAAAC,cAEC,MAAI;EAAA,YACE,GAAA,eAAA,MAAA,GAAqB,QAAA,MAAQ,KAAK,GAAG;EAAG,SAAA,OAAA,OAAA,OAAA,MAC1C,EAAE,OAAO,MAAM,SAAS,aAAa,qBAAqB;GAChE,MAAM,EAAE,eAAe,YAAY,EAAE,YAAY,OAAO,WAAW,CAAC;GAEpE,MAAM,OAAO,eACX,QAAA,MAAQ,SAAS,IAAC,QAAA,QAAa,CAAC,OAAO,UAAU,GAAA,CAEnD;GACA,MAAM,UAAU;IACd,OAAO,EAAE,OAAO,EAAE;IAClB,aAAa,EAAE,OAAO,IAAI,QAAQ,KAAK,OAAO,KAAK,MAAM,EAAE;IAC3D,UAAU,EAAE,OAAO,IAAI,QAAQ,EAAE;IACjC,OAAO,EAAE,OAAO,EAAE;IAClB,aAAa,EAAE,OAAO,WAAW;IACjC,SAAS,EAAE,OAAO,KAAK;IACvB,aAAa,EAAE,OAAO,MAAM,QAAA,MAAQ,QAAQ,GAAA,CAAqB,EAAE;GACrE;GACA,MAAM,WAAW,IAAI,eAAe;IAClC;IACA,gBAAgB,SAAQ,eAAA,KAAe;IACvC,UAAU;KAAE,GAAG;KAAS,GAAA,SAAA;IAAY;IACpC,aAAa;IACb,oBAAoB;IACpB,WAAW;IACX,YAAY;GACd,CAAC;GACD,MAAM,OAAO,IAAI,KAAK,IAAI,cAAc,GAAG,CAAC,GAAG,QAAQ;GACvD,KAAK,gBAAgB;GACrB,MAAM,IAAI,IAAI;GACd,OAAO;IACL,QAAQ,EAAE,WAAW;KACnB,QAAQ,MAAM,QAAQ,OAAI,MAAA;KAC1B,QAAQ,SAAS,MAAM,IAAI,QAAQ,GAAG,QAAQ,GAAG,YAAA,QAAc,QAAQ,WAAW,CAAC;KACnF,QAAQ,MAAM,QAAQ,OAAO,MAAM,gBAAgB,SAAS,IAAI;IAClE;IACA,SAAS,SAAS,QAAQ,YAAY,MAAM,IAAI,KAAK,OAAO,KAAK,MAAM;GACzE;EACF;CAAC,CAAA,GAAA,IAAA;AAGP,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
@@ -1,7 +1,7 @@
1
1
  import { hasContent, mergeAttrs, mergePartProps } from "../../utils/props.js";
2
2
  import { ThreeCanvas } from "./ThreeCanvas.js";
3
- import { createVNode, mergeProps } from "vue";
4
- import { _component, childrenProp, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
3
+ import { createVNode } from "vue";
4
+ import { _component, childrenProp, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
5
5
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
6
6
  //#region src/three/core/EffectSurface.tsx
7
7
  /** 各种效果共有的属性;未声明的属性落到外层 div 上 */
@@ -35,7 +35,7 @@ var EffectSurface = /*#__PURE__*/ _component((_props, _ctx) => {
35
35
  const propsContent = readonlyProp(_props, "propsContent");
36
36
  const children = childrenProp(_props);
37
37
  const rest = restProps(_props, _ctx, false);
38
- return () => createVNode("div", mergeAttrs({ sx: effectSurfaceStyles.root }, rest), [createVNode(ThreeCanvas, mergeProps({ "key": sceneKey.value }, mergePartProps({
38
+ return () => createVNode("div", mergeAttrs({ sx: effectSurfaceStyles.root }, rest), [createVNode(ThreeCanvas, mergeJsxProps({ "key": sceneKey.value }, mergePartProps({
39
39
  sx: effectSurfaceStyles.canvas,
40
40
  setup: setup.value,
41
41
  quality: quality.value,
@@ -1 +1 @@
1
- {"version":3,"file":"EffectSurface.js","names":["_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../../src/three/core/EffectSurface.tsx"],"sourcesContent":["/**\n * 效果的外层结构(ShaderBackground、ParticleField、WaveGrid 等共用):画布铺在底层,内容叠在上面。\n *\n * <MeshGradient sx={styles.hero}>\n * <h1>标题</h1> ← 内容照常排版、可以交互;画布在它下面,不接收指针\n * </MeshGradient>\n *\n * 根元素建立层叠上下文(isolation),画布层在内容下面、在根元素的背景上面;没有内容时只是一块效果。\n * 尺寸由使用方决定(sx 给高度,或由内容撑开)。画布是装饰,读屏跳过;要描述画面时给 propsCanvas 写 aria-label。\n *\n * 部件:Root(div)、Canvas(ThreeCanvas)、Content(div,有内容时才有)。\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 { hasContent, mergeAttrs, mergePartProps, type PartProps } from '../../utils/props';\nimport type { ThreeQuality } from './quality';\nimport type { ThreeContext, ThreeSceneHandle } from './renderer';\nimport { ThreeCanvas, type ThreeCanvasProps } from './ThreeCanvas';\n\n/** 各种效果共有的属性;未声明的属性落到外层 div 上 */\nexport interface EffectProps extends PartProps<'div'> {\n /**\n * 画质档位:像素比上限、粒子密度、抗锯齿;off 不渲染,显示 fallback\n * @default 'auto'\n */\n quality?: ThreeQuality;\n /** 暂停动画,停在当前画面 */\n paused?: boolean;\n /** 渲染分辨率相对像素比的倍数(0.1–1),见 ThreeCanvas;各效果有自己的默认值 */\n resolution?: number;\n /** 没有 WebGL(或 quality 为 off)时显示的内容,默认是主题色的柔和渐变 */\n fallback?: VNodeChild;\n /** 画布(ThreeCanvas)的部件属性 */\n propsCanvas?: Omit<Partial<ThreeCanvasProps>, 'setup'>;\n /** 内容外层的部件属性 */\n propsContent?: PartProps<'div'>;\n /** 叠在效果上面的内容 */\n children?: VNodeChild;\n}\n\n/** EffectSurface 的样式:root、canvas、content */\nexport const effectSurfaceStyles = css.create({\n root: { position: 'relative', isolation: 'isolate', overflow: 'hidden' },\n canvas: {\n position: 'absolute',\n inset: 0,\n zIndex: -1,\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n },\n content: { position: 'relative' },\n});\n\n/** EffectSurface 的属性:效果的公共属性加上搭场景的 setup */\nexport interface EffectSurfaceProps extends EffectProps {\n /** 搭场景,见 ThreeCanvas */\n setup: (context: ThreeContext) => ThreeSceneHandle | void;\n /** 变了就重建场景(着色器、色板这类建好后不再改的配置) */\n sceneKey?: string;\n}\n\n/** 效果的外层结构:底层画布 + 上层内容 */\nexport const EffectSurface = _component(\n ({\n setup,\n sceneKey,\n quality,\n paused,\n resolution,\n fallback,\n propsCanvas,\n propsContent,\n children,\n ...rest\n }: EffectSurfaceProps) => {\n return () => (\n <div {...mergeAttrs<'div'>({ sx: effectSurfaceStyles.root }, rest)}>\n <ThreeCanvas\n key={sceneKey}\n {...mergePartProps<ThreeCanvasProps>(\n { sx: effectSurfaceStyles.canvas, setup, quality, paused, resolution, fallback },\n propsCanvas,\n )}\n />\n {hasContent(children) && (\n <div {...mergeAttrs<'div'>({ sx: effectSurfaceStyles.content }, propsContent)}>\n {children}\n </div>\n )}\n </div>\n );\n },\n);\n"],"mappings":";;;;;;;;AA0CA,IAAa,sBAAsB,IAAI,OAAO;CAC5C,MAAM;EAAE,UAAU;EAAY,WAAW;EAAW,UAAU;CAAS;CACvE,QAAQ;EACN,UAAU;EACV,OAAO;EACP,QAAQ;EACR,OAAO;EACP,QAAQ;EACR,eAAe;CACjB;CACA,SAAS,EAAE,UAAU,WAAW;AAClC,CAAC;;;AAWD,IAAa,gBAAgB,0BAC3B,QAAA,SAW0B;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,UAAAA,aAAA,QAAA,SAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,aAAAA,aAAA,QAAA,YAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,eAAAA,aAAA,QAAA,cAAA;CAAA,MAAA,WAAAC,aAAA,MAAA;CAAA,MADrB,OAAIC,UAAA,QAAA,MAAA,KAAA;CAEP,aAAOC,YAAA,OACI,WAAkB,EAAE,IAAI,oBAAoB,KAAK,GAAG,IAAI,GAAC,CAAAA,YAAA,aAAAC,WAAA,EAAA,OAAA,SAAA,MAAA,GAG1D,eACF;EAAE,IAAI,oBAAoB;EAAQ,OAAK,MAAA;EAAE,SAAO,QAAA;EAAE,QAAM,OAAA;EAAE,YAAU,WAAA;EAAE,UAAQ,SAAA;CAAC,GAAC,YAAA,KAElF,CAAC,GAAA,IAAA,GAEF,WAAU,SAAA,KAAS,KAACD,YAAA,OACV,WAAkB,EAAE,IAAI,oBAAoB,QAAQ,GAAC,aAAA,KAAc,GAAC,CAAA,SAAA,KAAA,CAAA,CAG9E,CAAA;AAGP,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
1
+ {"version":3,"file":"EffectSurface.js","names":["_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../../src/three/core/EffectSurface.tsx"],"sourcesContent":["/**\n * 效果的外层结构(ShaderBackground、ParticleField、WaveGrid 等共用):画布铺在底层,内容叠在上面。\n *\n * <MeshGradient sx={styles.hero}>\n * <h1>标题</h1> ← 内容照常排版、可以交互;画布在它下面,不接收指针\n * </MeshGradient>\n *\n * 根元素建立层叠上下文(isolation),画布层在内容下面、在根元素的背景上面;没有内容时只是一块效果。\n * 尺寸由使用方决定(sx 给高度,或由内容撑开)。画布是装饰,读屏跳过;要描述画面时给 propsCanvas 写 aria-label。\n *\n * 部件:Root(div)、Canvas(ThreeCanvas)、Content(div,有内容时才有)。\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 { hasContent, mergeAttrs, mergePartProps, type PartProps } from '../../utils/props';\nimport type { ThreeQuality } from './quality';\nimport type { ThreeContext, ThreeSceneHandle } from './renderer';\nimport { ThreeCanvas, type ThreeCanvasProps } from './ThreeCanvas';\n\n/** 各种效果共有的属性;未声明的属性落到外层 div 上 */\nexport interface EffectProps extends PartProps<'div'> {\n /**\n * 画质档位:像素比上限、粒子密度、抗锯齿;off 不渲染,显示 fallback\n * @default 'auto'\n */\n quality?: ThreeQuality;\n /** 暂停动画,停在当前画面 */\n paused?: boolean;\n /** 渲染分辨率相对像素比的倍数(0.1–1),见 ThreeCanvas;各效果有自己的默认值 */\n resolution?: number;\n /** 没有 WebGL(或 quality 为 off)时显示的内容,默认是主题色的柔和渐变 */\n fallback?: VNodeChild;\n /** 画布(ThreeCanvas)的部件属性 */\n propsCanvas?: Omit<Partial<ThreeCanvasProps>, 'setup'>;\n /** 内容外层的部件属性 */\n propsContent?: PartProps<'div'>;\n /** 叠在效果上面的内容 */\n children?: VNodeChild;\n}\n\n/** EffectSurface 的样式:root、canvas、content */\nexport const effectSurfaceStyles = css.create({\n root: { position: 'relative', isolation: 'isolate', overflow: 'hidden' },\n canvas: {\n position: 'absolute',\n inset: 0,\n zIndex: -1,\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n },\n content: { position: 'relative' },\n});\n\n/** EffectSurface 的属性:效果的公共属性加上搭场景的 setup */\nexport interface EffectSurfaceProps extends EffectProps {\n /** 搭场景,见 ThreeCanvas */\n setup: (context: ThreeContext) => ThreeSceneHandle | void;\n /** 变了就重建场景(着色器、色板这类建好后不再改的配置) */\n sceneKey?: string;\n}\n\n/** 效果的外层结构:底层画布 + 上层内容 */\nexport const EffectSurface = _component(\n ({\n setup,\n sceneKey,\n quality,\n paused,\n resolution,\n fallback,\n propsCanvas,\n propsContent,\n children,\n ...rest\n }: EffectSurfaceProps) => {\n return () => (\n <div {...mergeAttrs<'div'>({ sx: effectSurfaceStyles.root }, rest)}>\n <ThreeCanvas\n key={sceneKey}\n {...mergePartProps<ThreeCanvasProps>(\n { sx: effectSurfaceStyles.canvas, setup, quality, paused, resolution, fallback },\n propsCanvas,\n )}\n />\n {hasContent(children) && (\n <div {...mergeAttrs<'div'>({ sx: effectSurfaceStyles.content }, propsContent)}>\n {children}\n </div>\n )}\n </div>\n );\n },\n);\n"],"mappings":";;;;;;;;AA0CA,IAAa,sBAAsB,IAAI,OAAO;CAC5C,MAAM;EAAE,UAAU;EAAY,WAAW;EAAW,UAAU;CAAS;CACvE,QAAQ;EACN,UAAU;EACV,OAAO;EACP,QAAQ;EACR,OAAO;EACP,QAAQ;EACR,eAAe;CACjB;CACA,SAAS,EAAE,UAAU,WAAW;AAClC,CAAC;;;AAWD,IAAa,gBAAgB,0BAC3B,QAAA,SAW0B;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,UAAAA,aAAA,QAAA,SAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,aAAAA,aAAA,QAAA,YAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,eAAAA,aAAA,QAAA,cAAA;CAAA,MAAA,WAAAC,aAAA,MAAA;CAAA,MADrB,OAAIC,UAAA,QAAA,MAAA,KAAA;CAEP,aAAOC,YAAA,OACI,WAAkB,EAAE,IAAI,oBAAoB,KAAK,GAAG,IAAI,GAAC,CAAAA,YAAA,aAAAC,cAAA,EAAA,OAAA,SAAA,MAAA,GAG1D,eACF;EAAE,IAAI,oBAAoB;EAAQ,OAAK,MAAA;EAAE,SAAO,QAAA;EAAE,QAAM,OAAA;EAAE,YAAU,WAAA;EAAE,UAAQ,SAAA;CAAC,GAAC,YAAA,KAElF,CAAC,GAAA,IAAA,GAEF,WAAU,SAAA,KAAS,KAACD,YAAA,OACV,WAAkB,EAAE,IAAI,oBAAoB,QAAQ,GAAC,aAAA,KAAc,GAAC,CAAA,SAAA,KAAA,CAAA,CAG9E,CAAA;AAGP,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}