@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,8 +1,8 @@
1
1
  import { t } from "../../config/theme/tokens.js";
2
2
  import { mergeAttrs } from "../../utils/props.js";
3
3
  import { useThree } from "./renderer.js";
4
- import { createVNode, mergeProps, shallowRef, watch } from "vue";
5
- import { _component, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
4
+ import { createVNode, shallowRef, watch } 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/three/core/ThreeCanvas.tsx
8
8
  /** 未声明的属性落到外层 div 上 */
@@ -50,10 +50,10 @@ var ThreeCanvas = /*#__PURE__*/ _component((_props, _ctx) => {
50
50
  watch(() => three.status, (status) => onStatusChange.value?.(status), { immediate: true });
51
51
  return () => {
52
52
  const labelled = rest["aria-label"] != null || rest["aria-labelledby"] != null;
53
- return createVNode("div", mergeProps(mergeAttrs({
53
+ return createVNode("div", mergeJsxProps(mergeAttrs({
54
54
  sx: threeCanvasStyles.root,
55
55
  "aria-hidden": labelled ? void 0 : true
56
- }, rest, { role: labelled ? "img" : void 0 }), { "data-state": three.status }), [three.status === "fallback" ? createVNode("div", mergeAttrs({ sx: [threeCanvasStyles.fallback, fallback.value == null && threeCanvasStyles.fallbackGradient] }, propsFallback.value, { "aria-hidden": true }), [fallback.value]) : createVNode("canvas", mergeProps({ "key": three.generation }, mergeAttrs({ sx: threeCanvasStyles.canvas }, propsCanvas.value, {
56
+ }, rest, { role: labelled ? "img" : void 0 }), { "data-state": three.status }), [three.status === "fallback" ? createVNode("div", mergeAttrs({ sx: [threeCanvasStyles.fallback, fallback.value == null && threeCanvasStyles.fallbackGradient] }, propsFallback.value, { "aria-hidden": true }), [fallback.value]) : createVNode("canvas", mergeJsxProps({ "key": three.generation }, mergeAttrs({ sx: threeCanvasStyles.canvas }, propsCanvas.value, {
57
57
  "aria-hidden": true,
58
58
  ref: canvas
59
59
  })), null)]);
@@ -1 +1 @@
1
- {"version":3,"file":"ThreeCanvas.js","names":["_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../../src/three/core/ThreeCanvas.tsx"],"sourcesContent":["/**\n * three.js 画布(div > canvas):渲染器的生命周期交给 useThree,这里只负责外层结构、降级与无障碍。\n *\n * <ThreeCanvas\n * sx={styles.hero}\n * setup={(context) => {\n * const mesh = new Mesh(new IcosahedronGeometry(1, 4), new MeshNormalMaterial());\n * context.scene.add(mesh);\n * return { frame: ({ time }) => (mesh.rotation.y = time) };\n * }}\n * />\n *\n * - 尺寸由外层 div 决定(默认占满父元素),canvas 铺满它,背景透明;\n * - 没有 WebGL、或 quality=\"off\" 时显示 fallback,默认是一层主题色的柔和渐变;\n * - 默认是装饰(aria-hidden);传了 aria-label 时是一张图(role=\"img\");\n * - 渲染状态写在根元素的 data-state 上(idle / running / paused / still / fallback)。\n *\n * 部件:Root(div)、Canvas(canvas,重建时换新的一块)、Fallback(div,降级内容)。\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 { mergeAttrs, type PartProps } from '../../utils/props';\nimport type { ThreeQuality } from './quality';\nimport { useThree, type ThreeContext, type ThreeSceneHandle, type ThreeStatus } from './renderer';\nimport { t } from '../../config/theme/tokens';\n\n/** 未声明的属性落到外层 div 上 */\nexport interface ThreeCanvasProps extends PartProps<'div', 'role' | 'data-state'> {\n /** 搭场景:每次创建渲染器时调用一次(被回收、上下文丢失后会重新调用),返回每帧、尺寸变化、释放的回调 */\n setup: (context: ThreeContext) => ThreeSceneHandle | void;\n /**\n * 画质档位:像素比上限、粒子密度、抗锯齿;变了会重建。off 不创建 WebGL,显示 fallback\n * @default 'auto'\n */\n quality?: ThreeQuality;\n /** 暂停动画,停在当前画面 */\n paused?: boolean;\n /**\n * 渲染分辨率相对像素比的倍数(0.1–1):平滑的渐变、模糊的效果降低它能大幅省下 GPU 开销\n * @default 1\n */\n resolution?: number;\n /** 没有 WebGL(或 quality 为 off)时显示的内容,默认是主题色的柔和渐变 */\n fallback?: VNodeChild;\n /** 渲染状态变化时调用(同根元素的 data-state),挂载时先调用一次:比如降级时改放一张静态图,或一次性的效果直接收尾 */\n onStatusChange?: (status: ThreeStatus) => void;\n /** canvas 的部件属性 */\n propsCanvas?: PartProps<'canvas', 'aria-hidden'>;\n /** 降级内容外层的部件属性 */\n propsFallback?: PartProps<'div', 'aria-hidden'>;\n}\n\n/** ThreeCanvas 的样式:root、canvas、fallback、fallbackGradient(默认的降级渐变) */\nexport const threeCanvasStyles = css.create({\n root: {\n position: 'relative',\n display: 'block',\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n },\n canvas: {\n position: 'absolute',\n inset: 0,\n display: 'block',\n width: '100%',\n height: '100%',\n },\n fallback: { position: 'absolute', inset: 0 },\n fallbackGradient: {\n backgroundImage: `radial-gradient(circle at 20% 25%, color-mix(in oklab, ${t.colors.accent} 28%, transparent), transparent 55%), radial-gradient(circle at 80% 70%, color-mix(in oklab, ${t.colors.chart3} 24%, transparent), transparent 55%), radial-gradient(circle at 60% 15%, color-mix(in oklab, ${t.colors.chart5} 18%, transparent), transparent 50%)`,\n },\n});\n\n/** three.js 画布:生命周期、降级、无障碍,场景由 setup 搭建 */\nexport const ThreeCanvas = _component(\n ({\n setup,\n quality = 'auto',\n paused = false,\n resolution = 1,\n fallback,\n onStatusChange,\n propsCanvas,\n propsFallback,\n ...rest\n }: ThreeCanvasProps) => {\n let canvas = _state.raw<HTMLCanvasElement | null>(null);\n const three = useThree({\n canvas: () => canvas,\n setup: (context) => setup(context),\n quality: () => quality,\n paused: () => paused,\n resolution: () => resolution,\n });\n // 挂载时先报告一次:quality=\"off\" 一开始就是 fallback,之后不再变\n watch(\n () => three.status,\n (status) => onStatusChange?.(status),\n { immediate: true },\n );\n\n return () => {\n const labelled = rest['aria-label'] != null || rest['aria-labelledby'] != null;\n return (\n <div\n {...mergeAttrs<'div'>(\n { sx: threeCanvasStyles.root, 'aria-hidden': labelled ? undefined : true },\n rest,\n { role: labelled ? 'img' : undefined },\n )}\n data-state={three.status}\n >\n {three.status === 'fallback' ? (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n threeCanvasStyles.fallback,\n fallback == null && threeCanvasStyles.fallbackGradient,\n ],\n },\n propsFallback,\n { 'aria-hidden': true },\n )}\n >\n {fallback}\n </div>\n ) : (\n <canvas\n key={three.generation}\n {...mergeAttrs<'canvas'>({ sx: threeCanvasStyles.canvas }, propsCanvas, {\n 'aria-hidden': true,\n ref: _toRef(canvas),\n })}\n />\n )}\n </div>\n );\n };\n },\n);\n"],"mappings":";;;;;;;;;AAsDA,IAAa,oBAAoB,IAAI,OAAO;CAC1C,MAAM;EACJ,UAAU;EACV,SAAS;EACT,OAAO;EACP,QAAQ;EACR,UAAU;CACZ;CACA,QAAQ;EACN,UAAU;EACV,OAAO;EACP,SAAS;EACT,OAAO;EACP,QAAQ;CACV;CACA,UAAU;EAAE,UAAU;EAAY,OAAO;CAAE;CAC3C,kBAAkB,EAChB,iBAAiB,0DAA0D,EAAE,OAAO,OAAM,+FAAgG,EAAE,OAAO,OAAM,+FAAgG,EAAE,OAAO,OAAM,sCAC1T;AACF,CAAC;;AAGD,IAAa,cAAc,0BACzB,QAAA,SAUwB;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,UAAAA,aAAA,QAAA,WARZ,MAAM;CAAA,MAAA,SAAAA,aAAA,QAAA,UACP,KAAK;CAAA,MAAA,aAAAA,aAAA,QAAA,cACD,CAAC;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,iBAAAA,aAAA,QAAA,gBAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,gBAAAA,aAAA,QAAA,eAAA;CAAA,MAKX,OAAIC,UAAA,QAAA,MAAA,IAAA;CAEP,IAAI,SAAMC,WAAwC,IAAI;CACtD,MAAM,QAAQ,SAAS;EACrB,cAAQ,OAAA;EACR,QAAQ,YAAY,MAAA,MAAM,OAAO;EACjC,eAAS,QAAA;EACT,cAAQ,OAAA;EACR,kBAAY,WAAA;CACd,CAAC;CAED,YACQ,MAAM,SACX,WAAW,eAAA,QAAiB,MAAM,GACnC,EAAE,WAAW,KAAK,CACpB;CAEA,aAAa;EACX,MAAM,WAAW,KAAK,iBAAiB,QAAQ,KAAK,sBAAsB;EAC1E,OAAAC,YAAA,OAAAC,WAEQ,WACF;GAAE,IAAI,kBAAkB;GAAM,eAAe,WAAW,KAAA,IAAY;EAAK,GACzE,MACA,EAAE,MAAM,WAAW,QAAQ,KAAA,EAAU,CACvC,GAAC,EAAA,cACW,MAAM,OAAM,CAAA,GAAA,CAEvB,MAAM,WAAW,aAAUD,YAAA,OAEpB,WACF,EACE,IAAI,CACF,kBAAkB,UAClB,SAAA,SAAY,QAAQ,kBAAkB,gBAAgB,EAE1D,GAAC,cAAA,OAED,EAAE,eAAe,KAAK,CACxB,GAAC,CAAA,SAAA,KAAA,CAAA,IAAAA,YAAA,UAAAC,WAAA,EAAA,OAMI,MAAM,WAAU,GACjB,WAAqB,EAAE,IAAI,kBAAkB,OAAO,GAAC,YAAA,OAAe;GACtE,eAAe;GACf,KAAG;EACL,CAAC,CAAC,GAAA,IAAA,CAEL,CAAA;CAGP;AACF,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
1
+ {"version":3,"file":"ThreeCanvas.js","names":["_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../../src/three/core/ThreeCanvas.tsx"],"sourcesContent":["/**\n * three.js 画布(div > canvas):渲染器的生命周期交给 useThree,这里只负责外层结构、降级与无障碍。\n *\n * <ThreeCanvas\n * sx={styles.hero}\n * setup={(context) => {\n * const mesh = new Mesh(new IcosahedronGeometry(1, 4), new MeshNormalMaterial());\n * context.scene.add(mesh);\n * return { frame: ({ time }) => (mesh.rotation.y = time) };\n * }}\n * />\n *\n * - 尺寸由外层 div 决定(默认占满父元素),canvas 铺满它,背景透明;\n * - 没有 WebGL、或 quality=\"off\" 时显示 fallback,默认是一层主题色的柔和渐变;\n * - 默认是装饰(aria-hidden);传了 aria-label 时是一张图(role=\"img\");\n * - 渲染状态写在根元素的 data-state 上(idle / running / paused / still / fallback)。\n *\n * 部件:Root(div)、Canvas(canvas,重建时换新的一块)、Fallback(div,降级内容)。\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 { mergeAttrs, type PartProps } from '../../utils/props';\nimport type { ThreeQuality } from './quality';\nimport { useThree, type ThreeContext, type ThreeSceneHandle, type ThreeStatus } from './renderer';\nimport { t } from '../../config/theme/tokens';\n\n/** 未声明的属性落到外层 div 上 */\nexport interface ThreeCanvasProps extends PartProps<'div', 'role' | 'data-state'> {\n /** 搭场景:每次创建渲染器时调用一次(被回收、上下文丢失后会重新调用),返回每帧、尺寸变化、释放的回调 */\n setup: (context: ThreeContext) => ThreeSceneHandle | void;\n /**\n * 画质档位:像素比上限、粒子密度、抗锯齿;变了会重建。off 不创建 WebGL,显示 fallback\n * @default 'auto'\n */\n quality?: ThreeQuality;\n /** 暂停动画,停在当前画面 */\n paused?: boolean;\n /**\n * 渲染分辨率相对像素比的倍数(0.1–1):平滑的渐变、模糊的效果降低它能大幅省下 GPU 开销\n * @default 1\n */\n resolution?: number;\n /** 没有 WebGL(或 quality 为 off)时显示的内容,默认是主题色的柔和渐变 */\n fallback?: VNodeChild;\n /** 渲染状态变化时调用(同根元素的 data-state),挂载时先调用一次:比如降级时改放一张静态图,或一次性的效果直接收尾 */\n onStatusChange?: (status: ThreeStatus) => void;\n /** canvas 的部件属性 */\n propsCanvas?: PartProps<'canvas', 'aria-hidden'>;\n /** 降级内容外层的部件属性 */\n propsFallback?: PartProps<'div', 'aria-hidden'>;\n}\n\n/** ThreeCanvas 的样式:root、canvas、fallback、fallbackGradient(默认的降级渐变) */\nexport const threeCanvasStyles = css.create({\n root: {\n position: 'relative',\n display: 'block',\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n },\n canvas: {\n position: 'absolute',\n inset: 0,\n display: 'block',\n width: '100%',\n height: '100%',\n },\n fallback: { position: 'absolute', inset: 0 },\n fallbackGradient: {\n backgroundImage: `radial-gradient(circle at 20% 25%, color-mix(in oklab, ${t.colors.accent} 28%, transparent), transparent 55%), radial-gradient(circle at 80% 70%, color-mix(in oklab, ${t.colors.chart3} 24%, transparent), transparent 55%), radial-gradient(circle at 60% 15%, color-mix(in oklab, ${t.colors.chart5} 18%, transparent), transparent 50%)`,\n },\n});\n\n/** three.js 画布:生命周期、降级、无障碍,场景由 setup 搭建 */\nexport const ThreeCanvas = _component(\n ({\n setup,\n quality = 'auto',\n paused = false,\n resolution = 1,\n fallback,\n onStatusChange,\n propsCanvas,\n propsFallback,\n ...rest\n }: ThreeCanvasProps) => {\n let canvas = _state.raw<HTMLCanvasElement | null>(null);\n const three = useThree({\n canvas: () => canvas,\n setup: (context) => setup(context),\n quality: () => quality,\n paused: () => paused,\n resolution: () => resolution,\n });\n // 挂载时先报告一次:quality=\"off\" 一开始就是 fallback,之后不再变\n watch(\n () => three.status,\n (status) => onStatusChange?.(status),\n { immediate: true },\n );\n\n return () => {\n const labelled = rest['aria-label'] != null || rest['aria-labelledby'] != null;\n return (\n <div\n {...mergeAttrs<'div'>(\n { sx: threeCanvasStyles.root, 'aria-hidden': labelled ? undefined : true },\n rest,\n { role: labelled ? 'img' : undefined },\n )}\n data-state={three.status}\n >\n {three.status === 'fallback' ? (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n threeCanvasStyles.fallback,\n fallback == null && threeCanvasStyles.fallbackGradient,\n ],\n },\n propsFallback,\n { 'aria-hidden': true },\n )}\n >\n {fallback}\n </div>\n ) : (\n <canvas\n key={three.generation}\n {...mergeAttrs<'canvas'>({ sx: threeCanvasStyles.canvas }, propsCanvas, {\n 'aria-hidden': true,\n ref: _toRef(canvas),\n })}\n />\n )}\n </div>\n );\n };\n },\n);\n"],"mappings":";;;;;;;;;AAsDA,IAAa,oBAAoB,IAAI,OAAO;CAC1C,MAAM;EACJ,UAAU;EACV,SAAS;EACT,OAAO;EACP,QAAQ;EACR,UAAU;CACZ;CACA,QAAQ;EACN,UAAU;EACV,OAAO;EACP,SAAS;EACT,OAAO;EACP,QAAQ;CACV;CACA,UAAU;EAAE,UAAU;EAAY,OAAO;CAAE;CAC3C,kBAAkB,EAChB,iBAAiB,0DAA0D,EAAE,OAAO,OAAM,+FAAgG,EAAE,OAAO,OAAM,+FAAgG,EAAE,OAAO,OAAM,sCAC1T;AACF,CAAC;;AAGD,IAAa,cAAc,0BACzB,QAAA,SAUwB;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,UAAAA,aAAA,QAAA,WARZ,MAAM;CAAA,MAAA,SAAAA,aAAA,QAAA,UACP,KAAK;CAAA,MAAA,aAAAA,aAAA,QAAA,cACD,CAAC;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,iBAAAA,aAAA,QAAA,gBAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,gBAAAA,aAAA,QAAA,eAAA;CAAA,MAKX,OAAIC,UAAA,QAAA,MAAA,IAAA;CAEP,IAAI,SAAMC,WAAwC,IAAI;CACtD,MAAM,QAAQ,SAAS;EACrB,cAAQ,OAAA;EACR,QAAQ,YAAY,MAAA,MAAM,OAAO;EACjC,eAAS,QAAA;EACT,cAAQ,OAAA;EACR,kBAAY,WAAA;CACd,CAAC;CAED,YACQ,MAAM,SACX,WAAW,eAAA,QAAiB,MAAM,GACnC,EAAE,WAAW,KAAK,CACpB;CAEA,aAAa;EACX,MAAM,WAAW,KAAK,iBAAiB,QAAQ,KAAK,sBAAsB;EAC1E,OAAAC,YAAA,OAAAC,cAEQ,WACF;GAAE,IAAI,kBAAkB;GAAM,eAAe,WAAW,KAAA,IAAY;EAAK,GACzE,MACA,EAAE,MAAM,WAAW,QAAQ,KAAA,EAAU,CACvC,GAAC,EAAA,cACW,MAAM,OAAM,CAAA,GAAA,CAEvB,MAAM,WAAW,aAAUD,YAAA,OAEpB,WACF,EACE,IAAI,CACF,kBAAkB,UAClB,SAAA,SAAY,QAAQ,kBAAkB,gBAAgB,EAE1D,GAAC,cAAA,OAED,EAAE,eAAe,KAAK,CACxB,GAAC,CAAA,SAAA,KAAA,CAAA,IAAAA,YAAA,UAAAC,cAAA,EAAA,OAMI,MAAM,WAAU,GACjB,WAAqB,EAAE,IAAI,kBAAkB,OAAO,GAAC,YAAA,OAAe;GACtE,eAAe;GACf,KAAG;EACL,CAAC,CAAC,GAAA,IAAA,CAEL,CAAA;CAGP;AACF,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
@@ -2,8 +2,8 @@ import { colors } from "../../config/theme/tokens.js";
2
2
  import { mergePartProps } from "../../utils/props.js";
3
3
  import { toElement } from "../../utils/dom/element.js";
4
4
  import { EffectSurface } from "../core/EffectSurface.js";
5
- import { createVNode, mergeProps, ref, watch } from "vue";
6
- import { _component, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
5
+ import { createVNode, ref, watch } from "vue";
6
+ import { _component, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
7
7
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
8
8
  import { Color, DoubleSide, InstancedMesh, Matrix4, MeshBasicMaterial, OrthographicCamera, PlaneGeometry, Quaternion, Vector3 } from "three";
9
9
  //#region src/three/effects/Confetti.tsx
@@ -93,7 +93,7 @@ var Confetti = /*#__PURE__*/ _component((_props, _ctx) => {
93
93
  if (root.isConnected && !root.matches(":popover-open")) root.showPopover();
94
94
  });
95
95
  }
96
- return () => active.value && createVNode(EffectSurface, mergeProps(rest, { ref: showOnTop }, {
96
+ return () => active.value && createVNode(EffectSurface, mergeJsxProps(rest, { ref: showOnTop }, {
97
97
  "sx": [
98
98
  confettiStyles.root,
99
99
  fullscreen.value && confettiStyles.fullscreen,
@@ -1 +1 @@
1
- {"version":3,"file":"Confetti.js","names":["_vtp_readonlyProp","_vtp_restProps","_vue_ref","_createVNode","_mergeProps"],"sources":["../../../src/three/effects/Confetti.tsx"],"sourcesContent":["/**\n * 彩纸(庆祝):trigger 每变一次放一批,彩纸从 origin 喷出,翻转着飘落后消失。参考 canvas-confetti 的 origin、angle、spread。\n *\n * <Confetti trigger={paidCount} /> // 铺满视口,从中间偏下向上喷\n * <Confetti trigger={n} origin={{ x: 0, y: 1 }} angle={60} /> // 从左下角斜着喷\n * <div style=\"position: relative\"><Confetti fullscreen={false} trigger={n} /></div>\n *\n * 只在彩纸还在飘的时候才有画布:不放的时候不占 WebGL 上下文。默认铺满视口、放在顶层(原生 popover,\n * 盖得住打开着的对话框),指针穿透;fullscreen 为 false 时铺满最近的定位父元素。\n * 颜色取主题的图表色板,换主题时跟着变;系统或主题要求减少动态效果时不放(onDone 照常调用)。画面是装饰,读屏跳过。\n *\n * 部件:Root(div)、Canvas(ThreeCanvas)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport {\n Color,\n DoubleSide,\n InstancedMesh,\n Matrix4,\n MeshBasicMaterial,\n OrthographicCamera,\n PlaneGeometry,\n Quaternion,\n Vector3,\n} from 'three';\nimport { watch } from 'vue';\nimport { colors } from '../../config/theme/tokens';\nimport { toElement } from '../../utils/dom/element';\nimport { mergePartProps } from '../../utils/props';\nimport { EffectSurface, type EffectProps } from '../core/EffectSurface';\nimport type { ThreeCanvasProps } from '../core/ThreeCanvas';\n\n/** 彩纸的默认色板:图表色板的前六个 */\nexport const CONFETTI_PALETTE: readonly string[] = [\n colors.chart1,\n colors.chart2,\n colors.chart3,\n colors.chart4,\n colors.chart5,\n colors.chart6,\n];\n\n/** 喷出的位置:相对区域的比例,x 从左到右、y 从上到下(0–1) */\nexport interface ConfettiOrigin {\n /** 从左(0)到右(1) */\n x: number;\n /** 从上(0)到下(1) */\n y: number;\n}\n\n/** 未声明的属性落到外层 div 上 */\nexport interface ConfettiProps extends Omit<EffectProps, 'children' | 'fallback' | 'paused'> {\n /** 每变一次放一批(挂载时的初始值不放):写成计数、时间戳或任何会变的值 */\n trigger?: unknown;\n /**\n * 喷出的位置\n * @default { x: 0.5, y: 0.6 }\n */\n origin?: ConfettiOrigin;\n /**\n * 喷出的方向(度),90 是正上方,0 向右\n * @default 90\n */\n angle?: number;\n /**\n * 散开的角度(度)\n * @default 70\n */\n spread?: number;\n /**\n * 每批的数量\n * @default 160\n */\n count?: number;\n /**\n * 初速度的倍数\n * @default 1\n */\n velocity?: number;\n /**\n * 重力的倍数\n * @default 1\n */\n gravity?: number;\n /** 色板(token 或 CSS 颜色);变了下一次放时生效 */\n palette?: readonly string[];\n /**\n * 铺满视口,放在顶层;false 时铺满最近的定位父元素\n * @default true\n */\n fullscreen?: boolean;\n /** 这几批彩纸都落完(或减少动态效果时没有放)后调用 */\n onDone?: () => void;\n}\n\n/** Confetti 的样式:root、fullscreen */\nexport const confettiStyles = css.create({\n root: { position: 'absolute', inset: 0, pointerEvents: 'none' },\n // 原生 popover 的默认样式(居中、边框、底色)改成铺满视口的透明层\n fullscreen: {\n position: 'fixed',\n inset: 0,\n width: '100vw',\n height: '100vh',\n maxWidth: 'none',\n maxHeight: 'none',\n margin: 0,\n padding: 0,\n borderWidth: 0,\n backgroundColor: 'transparent',\n overflow: 'hidden',\n },\n});\n\n/** 同时在飘的彩纸上限 */\nconst MAX_PIECES = 900;\n/** 空气阻力(每秒速度剩下 e^-DRAG):喷出后很快慢下来,落得轻飘 */\nconst DRAG = 2.6;\n/** 一片彩纸飘多久(秒),最后一段缩小消失 */\nconst LIFETIME = [3.2, 4.6] as const;\nconst SHRINK = 0.6;\n/** 重力:每秒加速多少个区域高度 */\nconst GRAVITY = 1.1;\n\n/** 一批:放的那一刻的参数 */\ninterface Burst {\n origin: ConfettiOrigin;\n angle: number;\n spread: number;\n count: number;\n velocity: number;\n gravity: number;\n}\n\nconst random = (min: number, max: number) => min + Math.random() * (max - min);\n\n/** 彩纸 */\nexport const Confetti = _component(\n ({\n trigger,\n origin = { x: 0.5, y: 0.6 },\n angle = 90,\n spread = 70,\n count = 160,\n velocity = 1,\n gravity = 1,\n palette = CONFETTI_PALETTE,\n fullscreen = true,\n onDone,\n ...rest\n }: ConfettiProps) => {\n // 还没放出去的批次:画布建好后在下一帧里放\n const pending: Burst[] = [];\n let active = _state(false);\n\n watch(\n () => trigger,\n () => {\n pending.push({ origin, angle, spread, count, velocity, gravity });\n active = true;\n },\n );\n\n function finish() {\n // 在帧回调里:等这一帧结束再卸载画布\n queueMicrotask(() => {\n if (pending.length) return;\n active = false;\n onDone?.();\n });\n }\n\n /** 顶层显示:卸载时元素随之移除,不用手动收起 */\n function showOnTop(element: unknown) {\n const root = toElement(element);\n if (!fullscreen || !root || !('showPopover' in root)) return;\n // 顶层里后进的在上面:同一刻打开的对话框(支付成功)会盖住彩纸,等这一帧过去再进顶层\n requestAnimationFrame(() => {\n if (root.isConnected && !root.matches(':popover-open')) root.showPopover();\n });\n }\n\n return () =>\n active && (\n <EffectSurface\n {...rest}\n {...{ ref: showOnTop }}\n sx={[confettiStyles.root, fullscreen && confettiStyles.fullscreen, rest.sx]}\n popover={fullscreen ? 'manual' : undefined}\n aria-hidden=\"true\"\n // 没有 WebGL:什么也不画(不要默认的渐变铺满屏幕),直接收尾\n fallback={false}\n propsCanvas={mergePartProps<Partial<ThreeCanvasProps>>({}, rest.propsCanvas, {\n onStatusChange: (status) => {\n if (status !== 'fallback') return;\n pending.length = 0;\n finish();\n },\n })}\n sceneKey={palette.join(',')}\n setup={({ scene, size: area, still, themeColorList }) => {\n if (still) {\n pending.length = 0;\n finish();\n return;\n }\n const camera = new OrthographicCamera(0, 1, 1, 0, -500, 500);\n const tints = themeColorList(palette);\n\n const mesh = new InstancedMesh(\n new PlaneGeometry(1, 1),\n new MeshBasicMaterial({ side: DoubleSide }),\n MAX_PIECES,\n );\n mesh.frustumCulled = false;\n mesh.count = 0;\n scene.add(mesh);\n\n // 每片的状态:位置、速度、尺寸、翻转轴与角度、摆动、寿命、颜色\n const position = new Float32Array(MAX_PIECES * 2);\n const speed = new Float32Array(MAX_PIECES * 2);\n const shape = new Float32Array(MAX_PIECES * 2);\n const axis = new Float32Array(MAX_PIECES * 3);\n const turn = new Float32Array(MAX_PIECES * 2);\n const sway = new Float32Array(MAX_PIECES * 2);\n const life = new Float32Array(MAX_PIECES * 2);\n const fall = new Float32Array(MAX_PIECES);\n const tint = new Uint8Array(MAX_PIECES);\n let alive = 0;\n\n function launch(burst: Burst) {\n const x0 = burst.origin.x * area.width;\n const y0 = (1 - burst.origin.y) * area.height;\n // 初速度与重力都按区域高度(H):大小不同的区域里看起来一样,最快的升到 0.9H 左右、最慢的 0.3H\n const base = area.height * 3.2 * burst.velocity;\n for (let n = 0; n < burst.count && alive < MAX_PIECES; n++, alive++) {\n const i = alive;\n const direction =\n ((burst.angle + random(-burst.spread / 2, burst.spread / 2)) * Math.PI) / 180;\n const v = base * random(0.45, 1);\n position[i * 2] = x0;\n position[i * 2 + 1] = y0;\n speed[i * 2] = Math.cos(direction) * v;\n speed[i * 2 + 1] = Math.sin(direction) * v;\n const width = random(7, 12);\n shape[i * 2] = width;\n shape[i * 2 + 1] = width * random(0.45, 0.8);\n const a = new Vector3(random(-1, 1), random(-1, 1), random(-1, 1)).normalize();\n axis.set([a.x, a.y, a.z], i * 3);\n turn[i * 2] = random(0, Math.PI * 2);\n turn[i * 2 + 1] = random(6, 14) * (Math.random() < 0.5 ? -1 : 1);\n sway[i * 2] = random(0, Math.PI * 2);\n sway[i * 2 + 1] = random(20, 60);\n life[i * 2] = 0;\n life[i * 2 + 1] = random(...LIFETIME);\n fall[i] = burst.gravity;\n tint[i] = Math.floor(Math.random() * tints.length);\n }\n }\n\n /** 把第 to 片换成第 from 片(落完的那片用最后一片补上,活着的始终在前面) */\n function move(from: number, to: number) {\n for (const [array, size] of [\n [position, 2],\n [speed, 2],\n [shape, 2],\n [axis, 3],\n [turn, 2],\n [sway, 2],\n [life, 2],\n ] as const) {\n array.copyWithin(to * size, from * size, from * size + size);\n }\n fall[to] = fall[from]!;\n tint[to] = tint[from]!;\n }\n\n const matrix = new Matrix4();\n const rotation = new Quaternion();\n const scale = new Vector3();\n const at = new Vector3();\n const normal = new Vector3();\n const shade = new Color();\n\n return {\n resize: (next, context) => {\n camera.right = next.width;\n camera.top = next.height;\n camera.updateProjectionMatrix();\n context.camera = camera;\n },\n frame: ({ delta }) => {\n // 画布刚建好的第一帧可能还没量到尺寸:量到了再放\n while (pending.length && area.height > 0) launch(pending.shift()!);\n const damping = Math.exp(-DRAG * delta);\n for (let i = 0; i < alive; i++) {\n life[i * 2]! += delta;\n const age = life[i * 2]!;\n const lifetime = life[i * 2 + 1]!;\n if (age >= lifetime || position[i * 2 + 1]! < -40) {\n move(--alive, i--);\n continue;\n }\n speed[i * 2]! *= damping;\n speed[i * 2 + 1] =\n speed[i * 2 + 1]! * damping - area.height * GRAVITY * fall[i]! * delta;\n // 左右摆动:像纸片在空气里飘\n sway[i * 2]! += delta * 4;\n position[i * 2]! +=\n (speed[i * 2]! + Math.sin(sway[i * 2]!) * sway[i * 2 + 1]!) * delta;\n position[i * 2 + 1]! += speed[i * 2 + 1]! * delta;\n turn[i * 2]! += turn[i * 2 + 1]! * delta;\n\n rotation.setFromAxisAngle(\n at.set(axis[i * 3]!, axis[i * 3 + 1]!, axis[i * 3 + 2]!),\n turn[i * 2]!,\n );\n const fade = Math.min(1, (lifetime - age) / SHRINK);\n scale.set(shape[i * 2]! * fade, shape[i * 2 + 1]! * fade, 1);\n matrix.compose(\n at.set(position[i * 2]!, position[i * 2 + 1]!, 0),\n rotation,\n scale,\n );\n mesh.setMatrixAt(i, matrix);\n // 翻到侧面时暗一些:正对屏幕最亮,看起来是在翻转的纸片\n const facing = Math.abs(normal.set(0, 0, 1).applyQuaternion(rotation).z);\n mesh.setColorAt(\n i,\n shade.copy(tints[tint[i]!]!).multiplyScalar(0.55 + 0.45 * facing),\n );\n }\n mesh.count = alive;\n mesh.instanceMatrix.needsUpdate = true;\n if (mesh.instanceColor) mesh.instanceColor.needsUpdate = true;\n if (alive === 0) finish();\n },\n };\n }}\n />\n );\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"Confetti.js","names":["_vtp_readonlyProp","_vtp_restProps","_vue_ref","_createVNode","_mergeProps"],"sources":["../../../src/three/effects/Confetti.tsx"],"sourcesContent":["/**\n * 彩纸(庆祝):trigger 每变一次放一批,彩纸从 origin 喷出,翻转着飘落后消失。参考 canvas-confetti 的 origin、angle、spread。\n *\n * <Confetti trigger={paidCount} /> // 铺满视口,从中间偏下向上喷\n * <Confetti trigger={n} origin={{ x: 0, y: 1 }} angle={60} /> // 从左下角斜着喷\n * <div style=\"position: relative\"><Confetti fullscreen={false} trigger={n} /></div>\n *\n * 只在彩纸还在飘的时候才有画布:不放的时候不占 WebGL 上下文。默认铺满视口、放在顶层(原生 popover,\n * 盖得住打开着的对话框),指针穿透;fullscreen 为 false 时铺满最近的定位父元素。\n * 颜色取主题的图表色板,换主题时跟着变;系统或主题要求减少动态效果时不放(onDone 照常调用)。画面是装饰,读屏跳过。\n *\n * 部件:Root(div)、Canvas(ThreeCanvas)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport {\n Color,\n DoubleSide,\n InstancedMesh,\n Matrix4,\n MeshBasicMaterial,\n OrthographicCamera,\n PlaneGeometry,\n Quaternion,\n Vector3,\n} from 'three';\nimport { watch } from 'vue';\nimport { colors } from '../../config/theme/tokens';\nimport { toElement } from '../../utils/dom/element';\nimport { mergePartProps } from '../../utils/props';\nimport { EffectSurface, type EffectProps } from '../core/EffectSurface';\nimport type { ThreeCanvasProps } from '../core/ThreeCanvas';\n\n/** 彩纸的默认色板:图表色板的前六个 */\nexport const CONFETTI_PALETTE: readonly string[] = [\n colors.chart1,\n colors.chart2,\n colors.chart3,\n colors.chart4,\n colors.chart5,\n colors.chart6,\n];\n\n/** 喷出的位置:相对区域的比例,x 从左到右、y 从上到下(0–1) */\nexport interface ConfettiOrigin {\n /** 从左(0)到右(1) */\n x: number;\n /** 从上(0)到下(1) */\n y: number;\n}\n\n/** 未声明的属性落到外层 div 上 */\nexport interface ConfettiProps extends Omit<EffectProps, 'children' | 'fallback' | 'paused'> {\n /** 每变一次放一批(挂载时的初始值不放):写成计数、时间戳或任何会变的值 */\n trigger?: unknown;\n /**\n * 喷出的位置\n * @default { x: 0.5, y: 0.6 }\n */\n origin?: ConfettiOrigin;\n /**\n * 喷出的方向(度),90 是正上方,0 向右\n * @default 90\n */\n angle?: number;\n /**\n * 散开的角度(度)\n * @default 70\n */\n spread?: number;\n /**\n * 每批的数量\n * @default 160\n */\n count?: number;\n /**\n * 初速度的倍数\n * @default 1\n */\n velocity?: number;\n /**\n * 重力的倍数\n * @default 1\n */\n gravity?: number;\n /** 色板(token 或 CSS 颜色);变了下一次放时生效 */\n palette?: readonly string[];\n /**\n * 铺满视口,放在顶层;false 时铺满最近的定位父元素\n * @default true\n */\n fullscreen?: boolean;\n /** 这几批彩纸都落完(或减少动态效果时没有放)后调用 */\n onDone?: () => void;\n}\n\n/** Confetti 的样式:root、fullscreen */\nexport const confettiStyles = css.create({\n root: { position: 'absolute', inset: 0, pointerEvents: 'none' },\n // 原生 popover 的默认样式(居中、边框、底色)改成铺满视口的透明层\n fullscreen: {\n position: 'fixed',\n inset: 0,\n width: '100vw',\n height: '100vh',\n maxWidth: 'none',\n maxHeight: 'none',\n margin: 0,\n padding: 0,\n borderWidth: 0,\n backgroundColor: 'transparent',\n overflow: 'hidden',\n },\n});\n\n/** 同时在飘的彩纸上限 */\nconst MAX_PIECES = 900;\n/** 空气阻力(每秒速度剩下 e^-DRAG):喷出后很快慢下来,落得轻飘 */\nconst DRAG = 2.6;\n/** 一片彩纸飘多久(秒),最后一段缩小消失 */\nconst LIFETIME = [3.2, 4.6] as const;\nconst SHRINK = 0.6;\n/** 重力:每秒加速多少个区域高度 */\nconst GRAVITY = 1.1;\n\n/** 一批:放的那一刻的参数 */\ninterface Burst {\n origin: ConfettiOrigin;\n angle: number;\n spread: number;\n count: number;\n velocity: number;\n gravity: number;\n}\n\nconst random = (min: number, max: number) => min + Math.random() * (max - min);\n\n/** 彩纸 */\nexport const Confetti = _component(\n ({\n trigger,\n origin = { x: 0.5, y: 0.6 },\n angle = 90,\n spread = 70,\n count = 160,\n velocity = 1,\n gravity = 1,\n palette = CONFETTI_PALETTE,\n fullscreen = true,\n onDone,\n ...rest\n }: ConfettiProps) => {\n // 还没放出去的批次:画布建好后在下一帧里放\n const pending: Burst[] = [];\n let active = _state(false);\n\n watch(\n () => trigger,\n () => {\n pending.push({ origin, angle, spread, count, velocity, gravity });\n active = true;\n },\n );\n\n function finish() {\n // 在帧回调里:等这一帧结束再卸载画布\n queueMicrotask(() => {\n if (pending.length) return;\n active = false;\n onDone?.();\n });\n }\n\n /** 顶层显示:卸载时元素随之移除,不用手动收起 */\n function showOnTop(element: unknown) {\n const root = toElement(element);\n if (!fullscreen || !root || !('showPopover' in root)) return;\n // 顶层里后进的在上面:同一刻打开的对话框(支付成功)会盖住彩纸,等这一帧过去再进顶层\n requestAnimationFrame(() => {\n if (root.isConnected && !root.matches(':popover-open')) root.showPopover();\n });\n }\n\n return () =>\n active && (\n <EffectSurface\n {...rest}\n {...{ ref: showOnTop }}\n sx={[confettiStyles.root, fullscreen && confettiStyles.fullscreen, rest.sx]}\n popover={fullscreen ? 'manual' : undefined}\n aria-hidden=\"true\"\n // 没有 WebGL:什么也不画(不要默认的渐变铺满屏幕),直接收尾\n fallback={false}\n propsCanvas={mergePartProps<Partial<ThreeCanvasProps>>({}, rest.propsCanvas, {\n onStatusChange: (status) => {\n if (status !== 'fallback') return;\n pending.length = 0;\n finish();\n },\n })}\n sceneKey={palette.join(',')}\n setup={({ scene, size: area, still, themeColorList }) => {\n if (still) {\n pending.length = 0;\n finish();\n return;\n }\n const camera = new OrthographicCamera(0, 1, 1, 0, -500, 500);\n const tints = themeColorList(palette);\n\n const mesh = new InstancedMesh(\n new PlaneGeometry(1, 1),\n new MeshBasicMaterial({ side: DoubleSide }),\n MAX_PIECES,\n );\n mesh.frustumCulled = false;\n mesh.count = 0;\n scene.add(mesh);\n\n // 每片的状态:位置、速度、尺寸、翻转轴与角度、摆动、寿命、颜色\n const position = new Float32Array(MAX_PIECES * 2);\n const speed = new Float32Array(MAX_PIECES * 2);\n const shape = new Float32Array(MAX_PIECES * 2);\n const axis = new Float32Array(MAX_PIECES * 3);\n const turn = new Float32Array(MAX_PIECES * 2);\n const sway = new Float32Array(MAX_PIECES * 2);\n const life = new Float32Array(MAX_PIECES * 2);\n const fall = new Float32Array(MAX_PIECES);\n const tint = new Uint8Array(MAX_PIECES);\n let alive = 0;\n\n function launch(burst: Burst) {\n const x0 = burst.origin.x * area.width;\n const y0 = (1 - burst.origin.y) * area.height;\n // 初速度与重力都按区域高度(H):大小不同的区域里看起来一样,最快的升到 0.9H 左右、最慢的 0.3H\n const base = area.height * 3.2 * burst.velocity;\n for (let n = 0; n < burst.count && alive < MAX_PIECES; n++, alive++) {\n const i = alive;\n const direction =\n ((burst.angle + random(-burst.spread / 2, burst.spread / 2)) * Math.PI) / 180;\n const v = base * random(0.45, 1);\n position[i * 2] = x0;\n position[i * 2 + 1] = y0;\n speed[i * 2] = Math.cos(direction) * v;\n speed[i * 2 + 1] = Math.sin(direction) * v;\n const width = random(7, 12);\n shape[i * 2] = width;\n shape[i * 2 + 1] = width * random(0.45, 0.8);\n const a = new Vector3(random(-1, 1), random(-1, 1), random(-1, 1)).normalize();\n axis.set([a.x, a.y, a.z], i * 3);\n turn[i * 2] = random(0, Math.PI * 2);\n turn[i * 2 + 1] = random(6, 14) * (Math.random() < 0.5 ? -1 : 1);\n sway[i * 2] = random(0, Math.PI * 2);\n sway[i * 2 + 1] = random(20, 60);\n life[i * 2] = 0;\n life[i * 2 + 1] = random(...LIFETIME);\n fall[i] = burst.gravity;\n tint[i] = Math.floor(Math.random() * tints.length);\n }\n }\n\n /** 把第 to 片换成第 from 片(落完的那片用最后一片补上,活着的始终在前面) */\n function move(from: number, to: number) {\n for (const [array, size] of [\n [position, 2],\n [speed, 2],\n [shape, 2],\n [axis, 3],\n [turn, 2],\n [sway, 2],\n [life, 2],\n ] as const) {\n array.copyWithin(to * size, from * size, from * size + size);\n }\n fall[to] = fall[from]!;\n tint[to] = tint[from]!;\n }\n\n const matrix = new Matrix4();\n const rotation = new Quaternion();\n const scale = new Vector3();\n const at = new Vector3();\n const normal = new Vector3();\n const shade = new Color();\n\n return {\n resize: (next, context) => {\n camera.right = next.width;\n camera.top = next.height;\n camera.updateProjectionMatrix();\n context.camera = camera;\n },\n frame: ({ delta }) => {\n // 画布刚建好的第一帧可能还没量到尺寸:量到了再放\n while (pending.length && area.height > 0) launch(pending.shift()!);\n const damping = Math.exp(-DRAG * delta);\n for (let i = 0; i < alive; i++) {\n life[i * 2]! += delta;\n const age = life[i * 2]!;\n const lifetime = life[i * 2 + 1]!;\n if (age >= lifetime || position[i * 2 + 1]! < -40) {\n move(--alive, i--);\n continue;\n }\n speed[i * 2]! *= damping;\n speed[i * 2 + 1] =\n speed[i * 2 + 1]! * damping - area.height * GRAVITY * fall[i]! * delta;\n // 左右摆动:像纸片在空气里飘\n sway[i * 2]! += delta * 4;\n position[i * 2]! +=\n (speed[i * 2]! + Math.sin(sway[i * 2]!) * sway[i * 2 + 1]!) * delta;\n position[i * 2 + 1]! += speed[i * 2 + 1]! * delta;\n turn[i * 2]! += turn[i * 2 + 1]! * delta;\n\n rotation.setFromAxisAngle(\n at.set(axis[i * 3]!, axis[i * 3 + 1]!, axis[i * 3 + 2]!),\n turn[i * 2]!,\n );\n const fade = Math.min(1, (lifetime - age) / SHRINK);\n scale.set(shape[i * 2]! * fade, shape[i * 2 + 1]! * fade, 1);\n matrix.compose(\n at.set(position[i * 2]!, position[i * 2 + 1]!, 0),\n rotation,\n scale,\n );\n mesh.setMatrixAt(i, matrix);\n // 翻到侧面时暗一些:正对屏幕最亮,看起来是在翻转的纸片\n const facing = Math.abs(normal.set(0, 0, 1).applyQuaternion(rotation).z);\n mesh.setColorAt(\n i,\n shade.copy(tints[tint[i]!]!).multiplyScalar(0.55 + 0.45 * facing),\n );\n }\n mesh.count = alive;\n mesh.instanceMatrix.needsUpdate = true;\n if (mesh.instanceColor) mesh.instanceColor.needsUpdate = true;\n if (alive === 0) finish();\n },\n };\n }}\n />\n );\n },\n);\n"],"mappings":";;;;;;;;;;AAkCA,IAAa,mBAAsC;CACjD,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;AAAM;;;;AAyDf,IAAa,iBAAiB,IAAI,OAAO;CACvC,MAAM;EAAE,UAAU;EAAY,OAAO;EAAG,eAAe;CAAO;CAE9D,YAAY;EACV,UAAU;EACV,OAAO;EACP,OAAO;EACP,QAAQ;EACR,UAAU;EACV,WAAW;EACX,QAAQ;EACR,SAAS;EACT,aAAa;EACb,iBAAiB;EACjB,UAAU;CACZ;AACF,CAAC;;AAGD,IAAM,aAAa;;AAInB,IAAM,WAAW,CAAC,KAAK,GAAG;AAC1B,IAAM,SAAS;;AAEf,IAAM,UAAU;;AAYhB,IAAM,UAAU,KAAa,QAAgB,MAAM,KAAK,OAAO,KAAK,MAAM;;AAG1E,IAAa,WAAW,0BACtB,QAAA,SAYqB;CAAA,MAAA,SAAA,CAAA;CAAA,MAAA,UAAAA,aAAA,QAAA,SAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,iBAVV;EAAE,GAAG;EAAK,GAAG;CAAI,EAAC;CAAA,MAAA,QAAAA,aAAA,QAAA,SACnB,EAAE;CAAA,MAAA,SAAAA,aAAA,QAAA,UACD,EAAE;CAAA,MAAA,QAAAA,aAAA,QAAA,SACH,GAAG;CAAA,MAAA,WAAAA,aAAA,QAAA,YACA,CAAC;CAAA,MAAA,UAAAA,aAAA,QAAA,WACF,CAAC;CAAA,MAAA,UAAAA,aAAA,QAAA,iBACD,gBAAgB;CAAA,MAAA,aAAAA,aAAA,QAAA,cACb,IAAI;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAEd,OAAIC,UAAA,QAAA,MAAA,IAAA;CAGP,MAAM,UAAmB,CAAA;CACzB,IAAI,SAAMC,IAAU,KAAK;CAEzB,YACE,QAAA,aACM;EACJ,QAAQ,KAAK;GAAE,QAAM,OAAA;GAAE,OAAK,MAAA;GAAE,QAAM,OAAA;GAAE,OAAK,MAAA;GAAE,UAAQ,SAAA;GAAE,SAAO,QAAA;EAAC,CAAC;EAChE,OAAA,QAAS;CACX,CACF;CAEA,SAAS,SAAS;EAEhB,qBAAqB;GACnB,IAAI,QAAQ,QAAQ;GACpB,OAAA,QAAS;GACT,OAAA,QAAS;EACX,CAAC;CACH;;CAGA,SAAS,UAAU,SAAkB;EACnC,MAAM,OAAO,UAAU,OAAO;EAC9B,IAAI,CAAA,WAAA,SAAe,CAAC,QAAQ,EAAE,iBAAiB,OAAO;EAEtD,4BAA4B;GAC1B,IAAI,KAAK,eAAe,CAAC,KAAK,QAAQ,eAAe,GAAG,KAAK,YAAY;EAC3E,CAAC;CACH;CAEA,aACE,OAAA,SAAAC,YAAA,eAAAC,cAEQ,MAAI,EACF,KAAK,UAAS,GAAA;EAAA,MAChB;GAAC,eAAe;GAAM,WAAA,SAAc,eAAe;GAAY,KAAK;EAAE;EAAC,WAClE,WAAA,QAAa,WAAW,KAAA;EAAS,eAAA;EAAA,YAGhC;EAAK,eACF,eAA0C,CAAC,GAAG,KAAK,aAAa,EAC3E,iBAAiB,WAAW;GAC1B,IAAI,WAAW,YAAY;GAC3B,QAAQ,SAAS;GACjB,OAAO;EACT,EACF,CAAC;EAAC,YACQ,QAAA,MAAQ,KAAK,GAAG;EAAC,SAAA,OAAA,OAAA,OAAA,MACnB,EAAE,OAAO,MAAM,MAAM,OAAO,qBAAqB;GACvD,IAAI,OAAO;IACT,QAAQ,SAAS;IACjB,OAAO;IACP;GACF;GACA,MAAM,SAAS,IAAI,mBAAmB,GAAG,GAAG,GAAG,GAAG,MAAM,GAAG;GAC3D,MAAM,QAAQ,eAAc,QAAA,KAAQ;GAEpC,MAAM,OAAO,IAAI,cACf,IAAI,cAAc,GAAG,CAAC,GACtB,IAAI,kBAAkB,EAAE,MAAM,WAAW,CAAC,GAC1C,UACF;GACA,KAAK,gBAAgB;GACrB,KAAK,QAAQ;GACb,MAAM,IAAI,IAAI;GAGd,MAAM,WAAW,IAAI,aAAa,aAAa,CAAC;GAChD,MAAM,QAAQ,IAAI,aAAa,aAAa,CAAC;GAC7C,MAAM,QAAQ,IAAI,aAAa,aAAa,CAAC;GAC7C,MAAM,OAAO,IAAI,aAAa,aAAa,CAAC;GAC5C,MAAM,OAAO,IAAI,aAAa,aAAa,CAAC;GAC5C,MAAM,OAAO,IAAI,aAAa,aAAa,CAAC;GAC5C,MAAM,OAAO,IAAI,aAAa,aAAa,CAAC;GAC5C,MAAM,OAAO,IAAI,aAAa,UAAU;GACxC,MAAM,OAAO,IAAI,WAAW,UAAU;GACtC,IAAI,QAAQ;GAEZ,SAAS,OAAO,OAAc;IAC5B,MAAM,KAAK,MAAM,OAAO,IAAI,KAAK;IACjC,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK,KAAK;IAEvC,MAAM,OAAO,KAAK,SAAS,MAAM,MAAM;IACvC,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,SAAS,QAAQ,YAAY,KAAK,SAAS;KACnE,MAAM,IAAI;KACV,MAAM,aACF,MAAM,QAAQ,OAAO,CAAC,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,KAAK,KAAK,KAAM;KAC5E,MAAM,IAAI,OAAO,OAAO,KAAM,CAAC;KAC/B,SAAS,IAAI,KAAK;KAClB,SAAS,IAAI,IAAI,KAAK;KACtB,MAAM,IAAI,KAAK,KAAK,IAAI,SAAS,IAAI;KACrC,MAAM,IAAI,IAAI,KAAK,KAAK,IAAI,SAAS,IAAI;KACzC,MAAM,QAAQ,OAAO,GAAG,EAAE;KAC1B,MAAM,IAAI,KAAK;KACf,MAAM,IAAI,IAAI,KAAK,QAAQ,OAAO,KAAM,EAAG;KAC3C,MAAM,IAAI,IAAI,QAAQ,OAAO,IAAI,CAAC,GAAG,OAAO,IAAI,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU;KAC7E,KAAK,IAAI;MAAC,EAAE;MAAG,EAAE;MAAG,EAAE;KAAC,GAAG,IAAI,CAAC;KAC/B,KAAK,IAAI,KAAK,OAAO,GAAG,KAAK,KAAK,CAAC;KACnC,KAAK,IAAI,IAAI,KAAK,OAAO,GAAG,EAAE,KAAK,KAAK,OAAO,IAAI,KAAM,KAAK;KAC9D,KAAK,IAAI,KAAK,OAAO,GAAG,KAAK,KAAK,CAAC;KACnC,KAAK,IAAI,IAAI,KAAK,OAAO,IAAI,EAAE;KAC/B,KAAK,IAAI,KAAK;KACd,KAAK,IAAI,IAAI,KAAK,OAAO,GAAG,QAAQ;KACpC,KAAK,KAAK,MAAM;KAChB,KAAK,KAAK,KAAK,MAAM,KAAK,OAAO,IAAI,MAAM,MAAM;IACnD;GACF;;GAGA,SAAS,KAAK,MAAc,IAAY;IACtC,KAAK,MAAM,CAAC,OAAO,SAAS;KAC1B,CAAC,UAAU,CAAC;KACZ,CAAC,OAAO,CAAC;KACT,CAAC,OAAO,CAAC;KACT,CAAC,MAAM,CAAC;KACR,CAAC,MAAM,CAAC;KACR,CAAC,MAAM,CAAC;KACR,CAAC,MAAM,CAAC;IAAC,GAET,MAAM,WAAW,KAAK,MAAM,OAAO,MAAM,OAAO,OAAO,IAAI;IAE7D,KAAK,MAAM,KAAK;IAChB,KAAK,MAAM,KAAK;GAClB;GAEA,MAAM,SAAS,IAAI,QAAQ;GAC3B,MAAM,WAAW,IAAI,WAAW;GAChC,MAAM,QAAQ,IAAI,QAAQ;GAC1B,MAAM,KAAK,IAAI,QAAQ;GACvB,MAAM,SAAS,IAAI,QAAQ;GAC3B,MAAM,QAAQ,IAAI,MAAM;GAExB,OAAO;IACL,SAAS,MAAM,YAAY;KACzB,OAAO,QAAQ,KAAK;KACpB,OAAO,MAAM,KAAK;KAClB,OAAO,uBAAuB;KAC9B,QAAQ,SAAS;IACnB;IACA,QAAQ,EAAE,YAAY;KAEpB,OAAO,QAAQ,UAAU,KAAK,SAAS,GAAG,OAAO,QAAQ,MAAM,CAAE;KACjE,MAAM,UAAU,KAAK,IAAI,OAAQ,KAAK;KACtC,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK;MAC9B,KAAK,IAAI,MAAO;MAChB,MAAM,MAAM,KAAK,IAAI;MACrB,MAAM,WAAW,KAAK,IAAI,IAAI;MAC9B,IAAI,OAAO,YAAY,SAAS,IAAI,IAAI,KAAM,KAAK;OACjD,KAAK,EAAE,OAAO,GAAG;OACjB;MACF;MACA,MAAM,IAAI,MAAO;MACjB,MAAM,IAAI,IAAI,KACZ,MAAM,IAAI,IAAI,KAAM,UAAU,KAAK,SAAS,UAAU,KAAK,KAAM;MAEnE,KAAK,IAAI,MAAO,QAAQ;MACxB,SAAS,IAAI,OACV,MAAM,IAAI,KAAM,KAAK,IAAI,KAAK,IAAI,EAAG,IAAI,KAAK,IAAI,IAAI,MAAO;MAChE,SAAS,IAAI,IAAI,MAAO,MAAM,IAAI,IAAI,KAAM;MAC5C,KAAK,IAAI,MAAO,KAAK,IAAI,IAAI,KAAM;MAEnC,SAAS,iBACP,GAAG,IAAI,KAAK,IAAI,IAAK,KAAK,IAAI,IAAI,IAAK,KAAK,IAAI,IAAI,EAAG,GACvD,KAAK,IAAI,EACX;MACA,MAAM,OAAO,KAAK,IAAI,IAAI,WAAW,OAAO,MAAM;MAClD,MAAM,IAAI,MAAM,IAAI,KAAM,MAAM,MAAM,IAAI,IAAI,KAAM,MAAM,CAAC;MAC3D,OAAO,QACL,GAAG,IAAI,SAAS,IAAI,IAAK,SAAS,IAAI,IAAI,IAAK,CAAC,GAChD,UACA,KACF;MACA,KAAK,YAAY,GAAG,MAAM;MAE1B,MAAM,SAAS,KAAK,IAAI,OAAO,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,gBAAgB,QAAQ,CAAC,CAAC,CAAC;MACvE,KAAK,WACH,GACA,MAAM,KAAK,MAAM,KAAK,GAAK,CAAC,CAAC,eAAe,MAAO,MAAO,MAAM,CAClE;KACF;KACA,KAAK,QAAQ;KACb,KAAK,eAAe,cAAc;KAClC,IAAI,KAAK,eAAe,KAAK,cAAc,cAAc;KACzD,IAAI,UAAU,GAAG,OAAO;IAC1B;GACF;EACF;CAAC,CAAA,GAAA,IAAA;AAGT,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
@@ -2,8 +2,8 @@ import { clamp } from "../../utils/data/number.js";
2
2
  import { colors } from "../../config/theme/tokens.js";
3
3
  import { EffectSurface } from "../core/EffectSurface.js";
4
4
  import "../core/shaders.js";
5
- import { createVNode, mergeProps } from "vue";
6
- import { _component, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
5
+ import { createVNode } from "vue";
6
+ import { _component, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
7
7
  import { BufferAttribute, BufferGeometry, LineSegments, OrthographicCamera, Points, ShaderMaterial } from "three";
8
8
  //#region src/three/effects/ParticleField.tsx
9
9
  /** 粒子场的默认色板:品牌色、紫、青 */
@@ -78,7 +78,7 @@ var ParticleField = /*#__PURE__*/ _component((_props, _ctx) => {
78
78
  const interactive = readonlyProp(_props, "interactive", true);
79
79
  const repelRadius = readonlyProp(_props, "repelRadius", 140);
80
80
  const rest = restProps(_props, _ctx, true);
81
- return () => createVNode(EffectSurface, mergeProps(rest, {
81
+ return () => createVNode(EffectSurface, mergeJsxProps(rest, {
82
82
  "sceneKey": `${palette.value.join(",")}|${links.value}`,
83
83
  "setup": _cache[0] || (_cache[0] = ({ scene, size: area, quality, pointer, themeColorList }) => {
84
84
  const camera = new OrthographicCamera(0, 1, 1, 0, -1, 1);
@@ -1 +1 @@
1
- {"version":3,"file":"ParticleField.js","names":["_vtp_readonlyProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../../src/three/effects/ParticleField.tsx"],"sourcesContent":["/**\n * 粒子场(div):柔和的光点在区域里缓缓漂移,指针靠近时向四周排开、离开后回到原来的漂移;\n * links 打开时相近的粒子连成星座般的细线,越近越清楚。\n *\n * <ParticleField links sx={styles.hero}>\n * <h1>标题</h1>\n * </ParticleField>\n *\n * 粒子数默认按面积与画质档位决定(连线时更稀疏),尺寸变化时增减;颜色从色板里随机分配,连线用色板的第一个颜色,\n * 都跟随主题原地过渡。背景透明,叠在页面底色或别的效果(MeshGradient)上。\n *\n * 部件:Root(div)、Canvas(ThreeCanvas)、Content(div)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport {\n BufferAttribute,\n BufferGeometry,\n LineSegments,\n OrthographicCamera,\n Points,\n ShaderMaterial,\n} from 'three';\nimport { colors } from '../../config/theme/tokens';\nimport { clamp } from '../../utils/data/number';\nimport { EffectSurface, type EffectProps } from '../core/EffectSurface';\nimport { THEME_PALETTE_SIZE } from '../core/shaders';\n\n/** 粒子场的默认色板:品牌色、紫、青 */\nexport const PARTICLE_PALETTE: readonly string[] = [colors.accent, colors.chart5, colors.chart6];\n\n/** 未声明的属性落到外层 div 上 */\nexport interface ParticleFieldProps extends EffectProps {\n /** 粒子数;不写时按面积与画质档位决定 */\n count?: number;\n /** 色板(token 或 CSS 颜色,最多 6 个):粒子随机取色,连线用第一个;变了会重建 */\n palette?: readonly string[];\n /**\n * 粒子的直径(CSS 像素,各粒子在它的 0.6–1.4 倍之间)\n * @default 3\n */\n size?: number;\n /**\n * 漂移速度\n * @default 1\n */\n speed?: number;\n /** 相近的粒子连线(星座) */\n links?: boolean;\n /**\n * 连线的最大距离(CSS 像素)\n * @default 120\n */\n linkDistance?: number;\n /**\n * 指针靠近时排开粒子\n * @default true\n */\n interactive?: boolean;\n /**\n * 排开的范围(CSS 像素)\n * @default 140\n */\n repelRadius?: number;\n}\n\n/** 粒子数上限(不连线 / 连线):连线的计算量随粒子数增长 */\nconst MAX_PARTICLES = 3000;\nconst MAX_LINKED = 420;\n/** 每个粒子最多画几条线 */\nconst LINKS_PER_PARTICLE = 6;\n\nconst pointsVertex = /* glsl */ `\nuniform vec3 uColors[${THEME_PALETTE_SIZE}];\nuniform float uPixelRatio;\nattribute float aSize;\nattribute float aColor;\nvarying vec3 vColor;\nvoid main() {\n vColor = uColors[int(aColor)];\n gl_PointSize = aSize * uPixelRatio;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}\n`;\n\nconst pointsFragment = /* glsl */ `\nvarying vec3 vColor;\nvoid main() {\n float d = length(gl_PointCoord - 0.5);\n gl_FragColor = vec4(vColor, smoothstep(0.5, 0.1, d));\n #include <colorspace_fragment>\n #include <premultiplied_alpha_fragment>\n}\n`;\n\nconst linesVertex = /* glsl */ `\nattribute float aAlpha;\nvarying float vAlpha;\nvoid main() {\n vAlpha = aAlpha;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}\n`;\n\nconst linesFragment = /* glsl */ `\nuniform vec3 uColor;\nvarying float vAlpha;\nvoid main() {\n gl_FragColor = vec4(uColor, vAlpha);\n #include <colorspace_fragment>\n #include <premultiplied_alpha_fragment>\n}\n`;\n\n/** 透明叠加的着色器材质 */\nfunction overlayMaterial(params: ConstructorParameters<typeof ShaderMaterial>[0]) {\n return new ShaderMaterial({\n ...params,\n transparent: true,\n premultipliedAlpha: true,\n depthTest: false,\n depthWrite: false,\n });\n}\n\n/** 粒子场:漂移的光点,指针排开,可选星座连线 */\nexport const ParticleField = _component(\n ({\n count,\n palette = PARTICLE_PALETTE,\n size = 3,\n speed = 1,\n links = false,\n linkDistance = 120,\n interactive = true,\n repelRadius = 140,\n ...rest\n }: ParticleFieldProps) => {\n return () => (\n <EffectSurface\n {...rest}\n sceneKey={`${palette.join(',')}|${links}`}\n setup={({ scene, size: area, quality, pointer, themeColorList }) => {\n const camera = new OrthographicCamera(0, 1, 1, 0, -1, 1);\n const max = links ? MAX_LINKED : MAX_PARTICLES;\n const sources = palette.slice(0, THEME_PALETTE_SIZE);\n const list = themeColorList(sources, THEME_PALETTE_SIZE);\n\n // 粒子状态:位置、速度、各自的漂移速度\n const position = new Float32Array(max * 3);\n const velocity = new Float32Array(max * 2);\n const drift = new Float32Array(max * 2);\n const sizes = new Float32Array(max);\n const tints = new Float32Array(max);\n let active = 0;\n const seed = (index: number) => {\n position[index * 3] = Math.random() * area.width;\n position[index * 3 + 1] = Math.random() * area.height;\n const angle = Math.random() * Math.PI * 2;\n const pace = 6 + Math.random() * 14;\n drift[index * 2] = Math.cos(angle) * pace;\n drift[index * 2 + 1] = Math.sin(angle) * pace;\n velocity[index * 2] = drift[index * 2]!;\n velocity[index * 2 + 1] = drift[index * 2 + 1]!;\n sizes[index] = size * (0.6 + Math.random() * 0.8);\n tints[index] = Math.floor(Math.random() * sources.length);\n };\n\n const geometry = new BufferGeometry();\n const positionAttribute = new BufferAttribute(position, 3);\n geometry.setAttribute('position', positionAttribute);\n geometry.setAttribute('aSize', new BufferAttribute(sizes, 1));\n geometry.setAttribute('aColor', new BufferAttribute(tints, 1));\n const pointsUniforms = { uColors: { value: list }, uPixelRatio: { value: 1 } };\n const points = new Points(\n geometry,\n overlayMaterial({\n vertexShader: pointsVertex,\n fragmentShader: pointsFragment,\n uniforms: pointsUniforms,\n }),\n );\n points.frustumCulled = false;\n scene.add(points);\n\n const maxSegments = links ? max * LINKS_PER_PARTICLE : 0;\n const linePositions = new Float32Array(maxSegments * 6);\n const lineAlphas = new Float32Array(maxSegments * 2);\n const lineGeometry = new BufferGeometry();\n const linePositionAttribute = new BufferAttribute(linePositions, 3);\n const lineAlphaAttribute = new BufferAttribute(lineAlphas, 1);\n lineGeometry.setAttribute('position', linePositionAttribute);\n lineGeometry.setAttribute('aAlpha', lineAlphaAttribute);\n if (links) {\n const lines = new LineSegments(\n lineGeometry,\n overlayMaterial({\n vertexShader: linesVertex,\n fragmentShader: linesFragment,\n uniforms: { uColor: { value: list[0] } },\n }),\n );\n lines.frustumCulled = false;\n scene.add(lines);\n }\n\n // 按连线距离分格,只比较相邻的格子;格子里的粒子串成链表(head 是每格第一个,next 是同格的下一个,-1 结束),\n // 每帧都要算,不分配新内存\n const next = new Int32Array(max);\n let head = new Int32Array(0);\n function connect() {\n const cell = linkDistance;\n const columns = Math.ceil(area.width / cell) + 1;\n const rows = Math.ceil(area.height / cell) + 1;\n if (head.length < columns * rows) head = new Int32Array(columns * rows);\n head.fill(-1, 0, columns * rows);\n // 漂出边界的粒子归到最近的格子\n const cellOf = (value: number, count: number) =>\n clamp(Math.floor(value / cell), 0, count - 1);\n for (let index = 0; index < active; index++) {\n const key =\n cellOf(position[index * 3 + 1]!, rows) * columns +\n cellOf(position[index * 3]!, columns);\n next[index] = head[key]!;\n head[key] = index;\n }\n let segments = 0;\n for (let index = 0; index < active && segments < maxSegments; index++) {\n const x = position[index * 3]!;\n const y = position[index * 3 + 1]!;\n const column = cellOf(x, columns);\n const row = cellOf(y, rows);\n let own = 0;\n for (let dy = -1; dy <= 1; dy++) {\n for (let dx = -1; dx <= 1; dx++) {\n const r = row + dy;\n const c = column + dx;\n if (r < 0 || r >= rows || c < 0 || c >= columns) continue;\n for (let other = head[r * columns + c]!; other !== -1; other = next[other]!) {\n if (other <= index || own >= LINKS_PER_PARTICLE || segments >= maxSegments)\n continue;\n const ox = position[other * 3]!;\n const oy = position[other * 3 + 1]!;\n const distance = Math.hypot(ox - x, oy - y);\n if (distance > linkDistance) continue;\n const offset = segments * 6;\n linePositions[offset] = x;\n linePositions[offset + 1] = y;\n linePositions[offset + 3] = ox;\n linePositions[offset + 4] = oy;\n const alpha = (1 - distance / linkDistance) * 0.45;\n lineAlphas[segments * 2] = alpha;\n lineAlphas[segments * 2 + 1] = alpha;\n segments++;\n own++;\n }\n }\n }\n }\n lineGeometry.setDrawRange(0, segments * 2);\n linePositionAttribute.needsUpdate = true;\n lineAlphaAttribute.needsUpdate = true;\n }\n\n return {\n resize: (next, context) => {\n camera.right = next.width;\n camera.top = next.height;\n camera.updateProjectionMatrix();\n context.camera = camera;\n pointsUniforms.uPixelRatio.value = next.pixelRatio;\n const perParticle = links ? 9000 : 2600;\n const wanted =\n count ?? Math.round(((next.width * next.height) / perParticle) * quality.density);\n const target = clamp(wanted, 0, max);\n // 新增的粒子撒在整个区域;已有的粒子落在区域外时重新撒\n for (let index = 0; index < target; index++) {\n const outside =\n position[index * 3]! > next.width || position[index * 3 + 1]! > next.height;\n if (index >= active || outside) seed(index);\n }\n active = target;\n geometry.setDrawRange(0, active);\n positionAttribute.needsUpdate = true;\n geometry.attributes.aSize!.needsUpdate = true;\n geometry.attributes.aColor!.needsUpdate = true;\n if (links) connect();\n },\n frame: ({ delta }) => {\n if (delta === 0) return;\n const step = delta * speed;\n const mx = ((pointer.x + 1) / 2) * area.width;\n const my = ((pointer.y + 1) / 2) * area.height;\n const push = interactive ? pointer.strength : 0;\n const margin = size * 2;\n for (let index = 0; index < active; index++) {\n let x = position[index * 3]!;\n let y = position[index * 3 + 1]!;\n let vx = velocity[index * 2]!;\n let vy = velocity[index * 2 + 1]!;\n if (push > 0.01) {\n const dx = x - mx;\n const dy = y - my;\n const distance = Math.hypot(dx, dy) || 1;\n if (distance < repelRadius) {\n const force = (1 - distance / repelRadius) ** 2 * 1400 * push * delta;\n vx += (dx / distance) * force;\n vy += (dy / distance) * force;\n }\n }\n // 排开后慢慢回到自己的漂移速度\n const settle = Math.min(1, delta * 1.6);\n vx += (drift[index * 2]! - vx) * settle;\n vy += (drift[index * 2 + 1]! - vy) * settle;\n x += vx * step;\n y += vy * step;\n // 出了边界从对边回来\n if (x < -margin) x = area.width + margin;\n else if (x > area.width + margin) x = -margin;\n if (y < -margin) y = area.height + margin;\n else if (y > area.height + margin) y = -margin;\n position[index * 3] = x;\n position[index * 3 + 1] = y;\n velocity[index * 2] = vx;\n velocity[index * 2 + 1] = vy;\n }\n positionAttribute.needsUpdate = true;\n if (links) connect();\n },\n };\n }}\n />\n );\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"ParticleField.js","names":["_vtp_readonlyProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../../src/three/effects/ParticleField.tsx"],"sourcesContent":["/**\n * 粒子场(div):柔和的光点在区域里缓缓漂移,指针靠近时向四周排开、离开后回到原来的漂移;\n * links 打开时相近的粒子连成星座般的细线,越近越清楚。\n *\n * <ParticleField links sx={styles.hero}>\n * <h1>标题</h1>\n * </ParticleField>\n *\n * 粒子数默认按面积与画质档位决定(连线时更稀疏),尺寸变化时增减;颜色从色板里随机分配,连线用色板的第一个颜色,\n * 都跟随主题原地过渡。背景透明,叠在页面底色或别的效果(MeshGradient)上。\n *\n * 部件:Root(div)、Canvas(ThreeCanvas)、Content(div)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport {\n BufferAttribute,\n BufferGeometry,\n LineSegments,\n OrthographicCamera,\n Points,\n ShaderMaterial,\n} from 'three';\nimport { colors } from '../../config/theme/tokens';\nimport { clamp } from '../../utils/data/number';\nimport { EffectSurface, type EffectProps } from '../core/EffectSurface';\nimport { THEME_PALETTE_SIZE } from '../core/shaders';\n\n/** 粒子场的默认色板:品牌色、紫、青 */\nexport const PARTICLE_PALETTE: readonly string[] = [colors.accent, colors.chart5, colors.chart6];\n\n/** 未声明的属性落到外层 div 上 */\nexport interface ParticleFieldProps extends EffectProps {\n /** 粒子数;不写时按面积与画质档位决定 */\n count?: number;\n /** 色板(token 或 CSS 颜色,最多 6 个):粒子随机取色,连线用第一个;变了会重建 */\n palette?: readonly string[];\n /**\n * 粒子的直径(CSS 像素,各粒子在它的 0.6–1.4 倍之间)\n * @default 3\n */\n size?: number;\n /**\n * 漂移速度\n * @default 1\n */\n speed?: number;\n /** 相近的粒子连线(星座) */\n links?: boolean;\n /**\n * 连线的最大距离(CSS 像素)\n * @default 120\n */\n linkDistance?: number;\n /**\n * 指针靠近时排开粒子\n * @default true\n */\n interactive?: boolean;\n /**\n * 排开的范围(CSS 像素)\n * @default 140\n */\n repelRadius?: number;\n}\n\n/** 粒子数上限(不连线 / 连线):连线的计算量随粒子数增长 */\nconst MAX_PARTICLES = 3000;\nconst MAX_LINKED = 420;\n/** 每个粒子最多画几条线 */\nconst LINKS_PER_PARTICLE = 6;\n\nconst pointsVertex = /* glsl */ `\nuniform vec3 uColors[${THEME_PALETTE_SIZE}];\nuniform float uPixelRatio;\nattribute float aSize;\nattribute float aColor;\nvarying vec3 vColor;\nvoid main() {\n vColor = uColors[int(aColor)];\n gl_PointSize = aSize * uPixelRatio;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}\n`;\n\nconst pointsFragment = /* glsl */ `\nvarying vec3 vColor;\nvoid main() {\n float d = length(gl_PointCoord - 0.5);\n gl_FragColor = vec4(vColor, smoothstep(0.5, 0.1, d));\n #include <colorspace_fragment>\n #include <premultiplied_alpha_fragment>\n}\n`;\n\nconst linesVertex = /* glsl */ `\nattribute float aAlpha;\nvarying float vAlpha;\nvoid main() {\n vAlpha = aAlpha;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}\n`;\n\nconst linesFragment = /* glsl */ `\nuniform vec3 uColor;\nvarying float vAlpha;\nvoid main() {\n gl_FragColor = vec4(uColor, vAlpha);\n #include <colorspace_fragment>\n #include <premultiplied_alpha_fragment>\n}\n`;\n\n/** 透明叠加的着色器材质 */\nfunction overlayMaterial(params: ConstructorParameters<typeof ShaderMaterial>[0]) {\n return new ShaderMaterial({\n ...params,\n transparent: true,\n premultipliedAlpha: true,\n depthTest: false,\n depthWrite: false,\n });\n}\n\n/** 粒子场:漂移的光点,指针排开,可选星座连线 */\nexport const ParticleField = _component(\n ({\n count,\n palette = PARTICLE_PALETTE,\n size = 3,\n speed = 1,\n links = false,\n linkDistance = 120,\n interactive = true,\n repelRadius = 140,\n ...rest\n }: ParticleFieldProps) => {\n return () => (\n <EffectSurface\n {...rest}\n sceneKey={`${palette.join(',')}|${links}`}\n setup={({ scene, size: area, quality, pointer, themeColorList }) => {\n const camera = new OrthographicCamera(0, 1, 1, 0, -1, 1);\n const max = links ? MAX_LINKED : MAX_PARTICLES;\n const sources = palette.slice(0, THEME_PALETTE_SIZE);\n const list = themeColorList(sources, THEME_PALETTE_SIZE);\n\n // 粒子状态:位置、速度、各自的漂移速度\n const position = new Float32Array(max * 3);\n const velocity = new Float32Array(max * 2);\n const drift = new Float32Array(max * 2);\n const sizes = new Float32Array(max);\n const tints = new Float32Array(max);\n let active = 0;\n const seed = (index: number) => {\n position[index * 3] = Math.random() * area.width;\n position[index * 3 + 1] = Math.random() * area.height;\n const angle = Math.random() * Math.PI * 2;\n const pace = 6 + Math.random() * 14;\n drift[index * 2] = Math.cos(angle) * pace;\n drift[index * 2 + 1] = Math.sin(angle) * pace;\n velocity[index * 2] = drift[index * 2]!;\n velocity[index * 2 + 1] = drift[index * 2 + 1]!;\n sizes[index] = size * (0.6 + Math.random() * 0.8);\n tints[index] = Math.floor(Math.random() * sources.length);\n };\n\n const geometry = new BufferGeometry();\n const positionAttribute = new BufferAttribute(position, 3);\n geometry.setAttribute('position', positionAttribute);\n geometry.setAttribute('aSize', new BufferAttribute(sizes, 1));\n geometry.setAttribute('aColor', new BufferAttribute(tints, 1));\n const pointsUniforms = { uColors: { value: list }, uPixelRatio: { value: 1 } };\n const points = new Points(\n geometry,\n overlayMaterial({\n vertexShader: pointsVertex,\n fragmentShader: pointsFragment,\n uniforms: pointsUniforms,\n }),\n );\n points.frustumCulled = false;\n scene.add(points);\n\n const maxSegments = links ? max * LINKS_PER_PARTICLE : 0;\n const linePositions = new Float32Array(maxSegments * 6);\n const lineAlphas = new Float32Array(maxSegments * 2);\n const lineGeometry = new BufferGeometry();\n const linePositionAttribute = new BufferAttribute(linePositions, 3);\n const lineAlphaAttribute = new BufferAttribute(lineAlphas, 1);\n lineGeometry.setAttribute('position', linePositionAttribute);\n lineGeometry.setAttribute('aAlpha', lineAlphaAttribute);\n if (links) {\n const lines = new LineSegments(\n lineGeometry,\n overlayMaterial({\n vertexShader: linesVertex,\n fragmentShader: linesFragment,\n uniforms: { uColor: { value: list[0] } },\n }),\n );\n lines.frustumCulled = false;\n scene.add(lines);\n }\n\n // 按连线距离分格,只比较相邻的格子;格子里的粒子串成链表(head 是每格第一个,next 是同格的下一个,-1 结束),\n // 每帧都要算,不分配新内存\n const next = new Int32Array(max);\n let head = new Int32Array(0);\n function connect() {\n const cell = linkDistance;\n const columns = Math.ceil(area.width / cell) + 1;\n const rows = Math.ceil(area.height / cell) + 1;\n if (head.length < columns * rows) head = new Int32Array(columns * rows);\n head.fill(-1, 0, columns * rows);\n // 漂出边界的粒子归到最近的格子\n const cellOf = (value: number, count: number) =>\n clamp(Math.floor(value / cell), 0, count - 1);\n for (let index = 0; index < active; index++) {\n const key =\n cellOf(position[index * 3 + 1]!, rows) * columns +\n cellOf(position[index * 3]!, columns);\n next[index] = head[key]!;\n head[key] = index;\n }\n let segments = 0;\n for (let index = 0; index < active && segments < maxSegments; index++) {\n const x = position[index * 3]!;\n const y = position[index * 3 + 1]!;\n const column = cellOf(x, columns);\n const row = cellOf(y, rows);\n let own = 0;\n for (let dy = -1; dy <= 1; dy++) {\n for (let dx = -1; dx <= 1; dx++) {\n const r = row + dy;\n const c = column + dx;\n if (r < 0 || r >= rows || c < 0 || c >= columns) continue;\n for (let other = head[r * columns + c]!; other !== -1; other = next[other]!) {\n if (other <= index || own >= LINKS_PER_PARTICLE || segments >= maxSegments)\n continue;\n const ox = position[other * 3]!;\n const oy = position[other * 3 + 1]!;\n const distance = Math.hypot(ox - x, oy - y);\n if (distance > linkDistance) continue;\n const offset = segments * 6;\n linePositions[offset] = x;\n linePositions[offset + 1] = y;\n linePositions[offset + 3] = ox;\n linePositions[offset + 4] = oy;\n const alpha = (1 - distance / linkDistance) * 0.45;\n lineAlphas[segments * 2] = alpha;\n lineAlphas[segments * 2 + 1] = alpha;\n segments++;\n own++;\n }\n }\n }\n }\n lineGeometry.setDrawRange(0, segments * 2);\n linePositionAttribute.needsUpdate = true;\n lineAlphaAttribute.needsUpdate = true;\n }\n\n return {\n resize: (next, context) => {\n camera.right = next.width;\n camera.top = next.height;\n camera.updateProjectionMatrix();\n context.camera = camera;\n pointsUniforms.uPixelRatio.value = next.pixelRatio;\n const perParticle = links ? 9000 : 2600;\n const wanted =\n count ?? Math.round(((next.width * next.height) / perParticle) * quality.density);\n const target = clamp(wanted, 0, max);\n // 新增的粒子撒在整个区域;已有的粒子落在区域外时重新撒\n for (let index = 0; index < target; index++) {\n const outside =\n position[index * 3]! > next.width || position[index * 3 + 1]! > next.height;\n if (index >= active || outside) seed(index);\n }\n active = target;\n geometry.setDrawRange(0, active);\n positionAttribute.needsUpdate = true;\n geometry.attributes.aSize!.needsUpdate = true;\n geometry.attributes.aColor!.needsUpdate = true;\n if (links) connect();\n },\n frame: ({ delta }) => {\n if (delta === 0) return;\n const step = delta * speed;\n const mx = ((pointer.x + 1) / 2) * area.width;\n const my = ((pointer.y + 1) / 2) * area.height;\n const push = interactive ? pointer.strength : 0;\n const margin = size * 2;\n for (let index = 0; index < active; index++) {\n let x = position[index * 3]!;\n let y = position[index * 3 + 1]!;\n let vx = velocity[index * 2]!;\n let vy = velocity[index * 2 + 1]!;\n if (push > 0.01) {\n const dx = x - mx;\n const dy = y - my;\n const distance = Math.hypot(dx, dy) || 1;\n if (distance < repelRadius) {\n const force = (1 - distance / repelRadius) ** 2 * 1400 * push * delta;\n vx += (dx / distance) * force;\n vy += (dy / distance) * force;\n }\n }\n // 排开后慢慢回到自己的漂移速度\n const settle = Math.min(1, delta * 1.6);\n vx += (drift[index * 2]! - vx) * settle;\n vy += (drift[index * 2 + 1]! - vy) * settle;\n x += vx * step;\n y += vy * step;\n // 出了边界从对边回来\n if (x < -margin) x = area.width + margin;\n else if (x > area.width + margin) x = -margin;\n if (y < -margin) y = area.height + margin;\n else if (y > area.height + margin) y = -margin;\n position[index * 3] = x;\n position[index * 3 + 1] = y;\n velocity[index * 2] = vx;\n velocity[index * 2 + 1] = vy;\n }\n positionAttribute.needsUpdate = true;\n if (links) connect();\n },\n };\n }}\n />\n );\n },\n);\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { colors } from "../../config/theme/tokens.js";
2
2
  import { EffectSurface } from "../core/EffectSurface.js";
3
3
  import { shaderChunks } from "../core/shaders.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 { BufferAttribute, BufferGeometry, LineSegments, Points, ShaderMaterial, Vector3 } from "three";
7
7
  //#region src/three/effects/WaveGrid.tsx
8
8
  /** 线框地形的默认色板:低处青、高处品牌色 */
@@ -76,7 +76,7 @@ var WaveGrid = /*#__PURE__*/ _component((_props, _ctx) => {
76
76
  const amplitude = readonlyProp(_props, "amplitude", 1);
77
77
  const interactive = readonlyProp(_props, "interactive", true);
78
78
  const rest = restProps(_props, _ctx, true);
79
- return () => createVNode(EffectSurface, mergeProps(rest, {
79
+ return () => createVNode(EffectSurface, mergeJsxProps(rest, {
80
80
  "sceneKey": `${variant.value}|${palette.value.join(",")}`,
81
81
  "setup": _cache[0] || (_cache[0] = ({ scene, camera, quality, size, pointer, themeColorList }) => {
82
82
  const sources = palette.value.slice(0, 6);
@@ -1 +1 @@
1
- {"version":3,"file":"WaveGrid.js","names":["_vtp_readonlyProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../../src/three/effects/WaveGrid.tsx"],"sourcesContent":["/**\n * 线框地形(div):一张向远处延伸的网格随噪声起伏,像缓慢呼吸的山丘;指针所在的位置隆起。\n * 颜色按高度在色板里取(低处第一个颜色、高处最后一个),远处渐隐到透明。\n *\n * <WaveGrid sx={styles.banner} />\n * <WaveGrid variant=\"dots\" palette={[colors.chart2, colors.accent]} />\n *\n * 背景透明;细分程度随画质档位变化。\n *\n * 部件:Root(div)、Canvas(ThreeCanvas)、Content(div)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport {\n BufferAttribute,\n BufferGeometry,\n LineSegments,\n Points,\n ShaderMaterial,\n Vector3,\n} from 'three';\nimport { colors } from '../../config/theme/tokens';\nimport { EffectSurface, type EffectProps } from '../core/EffectSurface';\nimport { shaderChunks, THEME_PALETTE_SIZE } from '../core/shaders';\n\n/** 线框地形的默认色板:低处青、高处品牌色 */\nexport const WAVE_GRID_PALETTE: readonly string[] = [colors.chart6, colors.accent, colors.chart5];\n\n/** 网格的画法 */\nexport interface WaveGridVariants {\n /** 网格线 */\n grid: unknown;\n /** 只画交点 */\n dots: unknown;\n}\n\n/** 未声明的属性落到外层 div 上 */\nexport interface WaveGridProps extends EffectProps {\n /**\n * 画法:网格线或只画交点;变了会重建\n * @default 'grid'\n */\n variant?: keyof WaveGridVariants;\n /** 色板(token 或 CSS 颜色,2–6 个),按高度取色;变了会重建 */\n palette?: readonly string[];\n /**\n * 起伏的速度\n * @default 1\n */\n speed?: number;\n /**\n * 起伏的高度\n * @default 1\n */\n amplitude?: number;\n /**\n * 指针所在的位置隆起\n * @default true\n */\n interactive?: boolean;\n}\n\n/** 网格的大小(世界单位)与最高画质下每边的格数 */\nconst WIDTH = 16;\nconst DEPTH = 12;\nconst CELLS = 72;\n\nconst vertexShader = /* glsl */ `\nuniform float uTime;\nuniform float uAmplitude;\nuniform vec3 uPointer;\nuniform float uPointSize;\nvarying float vHeight;\nvarying float vDepth;\n${shaderChunks.simplexNoise}\n${shaderChunks.fbm}\nvoid main() {\n vec3 p = position;\n float wave = fbm(vec3(p.x * 0.18, p.y * 0.22 - uTime * 0.15, uTime * 0.05));\n float bump = exp(-distance(p.xy, uPointer.xy) * 0.6) * uPointer.z * 1.4;\n p.z = (wave * 1.6 + bump) * uAmplitude;\n vHeight = clamp(wave * 0.9 + 0.5 + bump * 0.4, 0.0, 1.0);\n vec4 view = modelViewMatrix * vec4(p, 1.0);\n vDepth = -view.z;\n gl_PointSize = uPointSize * (8.0 / vDepth);\n gl_Position = projectionMatrix * view;\n}\n`;\n\nconst fragmentShader = /* glsl */ `\nvarying float vHeight;\nvarying float vDepth;\n${shaderChunks.themePalette}\nvoid main() {\n float fade = 1.0 - smoothstep(9.0, 17.0, vDepth);\n gl_FragColor = vec4(themePalette(vHeight), fade * (0.35 + vHeight * 0.65));\n #include <colorspace_fragment>\n #include <premultiplied_alpha_fragment>\n}\n`;\n\n/** 网格的顶点:dots 时是交点,grid 时是横竖两组线段 */\nfunction gridGeometry(cells: number, variant: keyof WaveGridVariants) {\n const columns = Math.round(cells * (WIDTH / DEPTH));\n const at = (column: number, row: number) => [\n (column / columns - 0.5) * WIDTH,\n (row / cells - 0.5) * DEPTH,\n 0,\n ];\n const vertices: number[] = [];\n for (let row = 0; row <= cells; row++) {\n for (let column = 0; column <= columns; column++) {\n if (variant === 'dots') vertices.push(...at(column, row));\n else {\n if (column < columns) vertices.push(...at(column, row), ...at(column + 1, row));\n if (row < cells) vertices.push(...at(column, row), ...at(column, row + 1));\n }\n }\n }\n const geometry = new BufferGeometry();\n geometry.setAttribute('position', new BufferAttribute(new Float32Array(vertices), 3));\n return geometry;\n}\n\n/** 线框地形:随噪声起伏的网格,指针处隆起 */\nexport const WaveGrid = _component(\n ({\n variant = 'grid',\n palette = WAVE_GRID_PALETTE,\n speed = 1,\n amplitude = 1,\n interactive = true,\n ...rest\n }: WaveGridProps) => {\n return () => (\n <EffectSurface\n {...rest}\n sceneKey={`${variant}|${palette.join(',')}`}\n setup={({ scene, camera, quality, size, pointer, themeColorList }) => {\n const sources = palette.slice(0, THEME_PALETTE_SIZE);\n const list = themeColorList(sources, THEME_PALETTE_SIZE);\n const uniforms = {\n uTime: { value: 0 },\n uAmplitude: { value: amplitude },\n uPointer: { value: new Vector3() },\n uPointSize: { value: 2 },\n uColors: { value: list },\n uColorCount: { value: Math.max(1, sources.length) },\n };\n const material = new ShaderMaterial({\n vertexShader,\n fragmentShader,\n uniforms,\n transparent: true,\n premultipliedAlpha: true,\n depthWrite: false,\n });\n const geometry = gridGeometry(Math.round(CELLS * quality.density), variant);\n const mesh =\n variant === 'dots'\n ? new Points(geometry, material)\n : new LineSegments(geometry, material);\n mesh.rotation.x = -Math.PI * 0.42;\n mesh.position.y = -0.6;\n scene.add(mesh);\n camera.position.set(0, 1.4, 6.5);\n camera.lookAt(0, -0.4, 0);\n // 指针在网格平面上的落点:近似为按屏幕位置映射到网格的范围\n return {\n frame: ({ time }) => {\n uniforms.uTime.value = time * speed;\n uniforms.uAmplitude.value = amplitude;\n uniforms.uPointer.value.set(\n pointer.x * WIDTH * 0.35,\n (pointer.y + 0.3) * DEPTH * 0.45,\n interactive ? pointer.strength : 0,\n );\n },\n resize: (next) =>\n (uniforms.uPointSize.value = 2.2 * next.pixelRatio * (size.height / 400 || 1)),\n };\n }}\n />\n );\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"WaveGrid.js","names":["_vtp_readonlyProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../../src/three/effects/WaveGrid.tsx"],"sourcesContent":["/**\n * 线框地形(div):一张向远处延伸的网格随噪声起伏,像缓慢呼吸的山丘;指针所在的位置隆起。\n * 颜色按高度在色板里取(低处第一个颜色、高处最后一个),远处渐隐到透明。\n *\n * <WaveGrid sx={styles.banner} />\n * <WaveGrid variant=\"dots\" palette={[colors.chart2, colors.accent]} />\n *\n * 背景透明;细分程度随画质档位变化。\n *\n * 部件:Root(div)、Canvas(ThreeCanvas)、Content(div)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport {\n BufferAttribute,\n BufferGeometry,\n LineSegments,\n Points,\n ShaderMaterial,\n Vector3,\n} from 'three';\nimport { colors } from '../../config/theme/tokens';\nimport { EffectSurface, type EffectProps } from '../core/EffectSurface';\nimport { shaderChunks, THEME_PALETTE_SIZE } from '../core/shaders';\n\n/** 线框地形的默认色板:低处青、高处品牌色 */\nexport const WAVE_GRID_PALETTE: readonly string[] = [colors.chart6, colors.accent, colors.chart5];\n\n/** 网格的画法 */\nexport interface WaveGridVariants {\n /** 网格线 */\n grid: unknown;\n /** 只画交点 */\n dots: unknown;\n}\n\n/** 未声明的属性落到外层 div 上 */\nexport interface WaveGridProps extends EffectProps {\n /**\n * 画法:网格线或只画交点;变了会重建\n * @default 'grid'\n */\n variant?: keyof WaveGridVariants;\n /** 色板(token 或 CSS 颜色,2–6 个),按高度取色;变了会重建 */\n palette?: readonly string[];\n /**\n * 起伏的速度\n * @default 1\n */\n speed?: number;\n /**\n * 起伏的高度\n * @default 1\n */\n amplitude?: number;\n /**\n * 指针所在的位置隆起\n * @default true\n */\n interactive?: boolean;\n}\n\n/** 网格的大小(世界单位)与最高画质下每边的格数 */\nconst WIDTH = 16;\nconst DEPTH = 12;\nconst CELLS = 72;\n\nconst vertexShader = /* glsl */ `\nuniform float uTime;\nuniform float uAmplitude;\nuniform vec3 uPointer;\nuniform float uPointSize;\nvarying float vHeight;\nvarying float vDepth;\n${shaderChunks.simplexNoise}\n${shaderChunks.fbm}\nvoid main() {\n vec3 p = position;\n float wave = fbm(vec3(p.x * 0.18, p.y * 0.22 - uTime * 0.15, uTime * 0.05));\n float bump = exp(-distance(p.xy, uPointer.xy) * 0.6) * uPointer.z * 1.4;\n p.z = (wave * 1.6 + bump) * uAmplitude;\n vHeight = clamp(wave * 0.9 + 0.5 + bump * 0.4, 0.0, 1.0);\n vec4 view = modelViewMatrix * vec4(p, 1.0);\n vDepth = -view.z;\n gl_PointSize = uPointSize * (8.0 / vDepth);\n gl_Position = projectionMatrix * view;\n}\n`;\n\nconst fragmentShader = /* glsl */ `\nvarying float vHeight;\nvarying float vDepth;\n${shaderChunks.themePalette}\nvoid main() {\n float fade = 1.0 - smoothstep(9.0, 17.0, vDepth);\n gl_FragColor = vec4(themePalette(vHeight), fade * (0.35 + vHeight * 0.65));\n #include <colorspace_fragment>\n #include <premultiplied_alpha_fragment>\n}\n`;\n\n/** 网格的顶点:dots 时是交点,grid 时是横竖两组线段 */\nfunction gridGeometry(cells: number, variant: keyof WaveGridVariants) {\n const columns = Math.round(cells * (WIDTH / DEPTH));\n const at = (column: number, row: number) => [\n (column / columns - 0.5) * WIDTH,\n (row / cells - 0.5) * DEPTH,\n 0,\n ];\n const vertices: number[] = [];\n for (let row = 0; row <= cells; row++) {\n for (let column = 0; column <= columns; column++) {\n if (variant === 'dots') vertices.push(...at(column, row));\n else {\n if (column < columns) vertices.push(...at(column, row), ...at(column + 1, row));\n if (row < cells) vertices.push(...at(column, row), ...at(column, row + 1));\n }\n }\n }\n const geometry = new BufferGeometry();\n geometry.setAttribute('position', new BufferAttribute(new Float32Array(vertices), 3));\n return geometry;\n}\n\n/** 线框地形:随噪声起伏的网格,指针处隆起 */\nexport const WaveGrid = _component(\n ({\n variant = 'grid',\n palette = WAVE_GRID_PALETTE,\n speed = 1,\n amplitude = 1,\n interactive = true,\n ...rest\n }: WaveGridProps) => {\n return () => (\n <EffectSurface\n {...rest}\n sceneKey={`${variant}|${palette.join(',')}`}\n setup={({ scene, camera, quality, size, pointer, themeColorList }) => {\n const sources = palette.slice(0, THEME_PALETTE_SIZE);\n const list = themeColorList(sources, THEME_PALETTE_SIZE);\n const uniforms = {\n uTime: { value: 0 },\n uAmplitude: { value: amplitude },\n uPointer: { value: new Vector3() },\n uPointSize: { value: 2 },\n uColors: { value: list },\n uColorCount: { value: Math.max(1, sources.length) },\n };\n const material = new ShaderMaterial({\n vertexShader,\n fragmentShader,\n uniforms,\n transparent: true,\n premultipliedAlpha: true,\n depthWrite: false,\n });\n const geometry = gridGeometry(Math.round(CELLS * quality.density), variant);\n const mesh =\n variant === 'dots'\n ? new Points(geometry, material)\n : new LineSegments(geometry, material);\n mesh.rotation.x = -Math.PI * 0.42;\n mesh.position.y = -0.6;\n scene.add(mesh);\n camera.position.set(0, 1.4, 6.5);\n camera.lookAt(0, -0.4, 0);\n // 指针在网格平面上的落点:近似为按屏幕位置映射到网格的范围\n return {\n frame: ({ time }) => {\n uniforms.uTime.value = time * speed;\n uniforms.uAmplitude.value = amplitude;\n uniforms.uPointer.value.set(\n pointer.x * WIDTH * 0.35,\n (pointer.y + 0.3) * DEPTH * 0.45,\n interactive ? pointer.strength : 0,\n );\n },\n resize: (next) =>\n (uniforms.uPointSize.value = 2.2 * next.pixelRatio * (size.height / 400 || 1)),\n };\n }}\n />\n );\n },\n);\n"],"mappings":"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"}
@@ -3,8 +3,8 @@ import { colors } from "../../config/theme/tokens.js";
3
3
  import { EffectSurface } from "../core/EffectSurface.js";
4
4
  import { createOrbit } from "../core/orbit.js";
5
5
  import { LAND_BITS } from "./land.js";
6
- import { createVNode, mergeProps } from "vue";
7
- import { _component, readonlyProp, restProps, untrack } from "@zerodep-dev/vue-tsx-pro-tsx";
6
+ import { createVNode } from "vue";
7
+ import { _component, mergeJsxProps, readonlyProp, restProps, untrack } from "@zerodep-dev/vue-tsx-pro-tsx";
8
8
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
9
9
  import { BufferAttribute, BufferGeometry, Group, LineSegments, Mesh, PerspectiveCamera, PlaneGeometry, Points, ShaderMaterial, Vector3 } from "three";
10
10
  //#region src/three/globe/Globe.tsx
@@ -183,7 +183,7 @@ var Globe = /*#__PURE__*/ _component((_props, _ctx) => {
183
183
  yaw: -start.lng * DEG,
184
184
  pitch: start.lat * DEG
185
185
  });
186
- return () => createVNode(EffectSurface, mergeProps(rest, { "sx": [
186
+ return () => createVNode(EffectSurface, mergeJsxProps(rest, { "sx": [
187
187
  globeStyles.root,
188
188
  draggable.value && globeStyles.draggable,
189
189
  css.select(() => orbit.dragging && globeStyles.dragging, true),
@@ -1 +1 @@
1
- {"version":3,"file":"Globe.js","names":["_vtp_readonlyProp","_vtp_restProps","_vtp_untrack","_createVNode","_mergeProps"],"sources":["../../../src/three/globe/Globe.tsx"],"sourcesContent":["/**\n * 点阵地球(div):陆地画成一层细密的点,可以标注地点(markers,向外扩散的光圈),两地之间画弧线(arcs,光点沿弧线流动);\n * 缓缓自转,可以拖动转动(松手后带惯性)。参考 GitHub 首页的地球、cobe。\n *\n * <Globe markers={[{ lat: 31.23, lng: 121.47 }]} arcs={[{ from: [31.23, 121.47], to: [37.77, -122.42] }]} />\n * <Globe center={{ lat: 30, lng: 110 }} rotationSpeed={0} sx={styles.globe} />\n *\n * 陆地来自 Natural Earth 1:110m 的世界地图(1° 的位图,见 land.ts);点的疏密按画质档位。颜色跟随主题:\n * 陆地用次要文字色,标注、弧线与大气光晕用品牌色(可以单独给 color)。默认是正方形,尺寸由使用方决定。\n * 减少动态效果时停在一帧,不自转、弧线不流动。画面是装饰;要让读屏知道内容时给 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 {\n BufferAttribute,\n BufferGeometry,\n Group,\n LineSegments,\n Mesh,\n PerspectiveCamera,\n Points,\n ShaderMaterial,\n PlaneGeometry,\n Vector3,\n type Color,\n} from 'three';\nimport { colors } from '../../config/theme/tokens';\nimport { clamp } from '../../utils/data/number';\nimport { EffectSurface, type EffectProps } from '../core/EffectSurface';\nimport { createOrbit } from '../core/orbit';\nimport { LAND_BITS, LAND_HEIGHT, LAND_WIDTH } from './land';\n\n/** 地图上的一个点:纬度(北正南负)、经度(东正西负),单位度 */\nexport interface GeoPoint {\n /** 纬度:北纬为正,-90 到 90 */\n lat: number;\n /** 经度:东经为正,-180 到 180 */\n lng: number;\n}\n\n/** 标注的地点 */\nexport interface GlobeMarker extends GeoPoint {\n /** 大小的倍数,默认 1 */\n size?: number;\n /** 颜色(token 或 CSS 颜色);不写时用 markerColor */\n color?: string;\n}\n\n/** 两地之间的弧线:[纬度, 经度] */\nexport interface GlobeArc {\n /** 起点 [纬度, 经度] */\n from: readonly [number, number];\n /** 终点 [纬度, 经度] */\n to: readonly [number, number];\n}\n\n/** 未声明的属性落到外层 div 上 */\nexport interface GlobeProps extends EffectProps {\n /** 标注的地点 */\n markers?: readonly GlobeMarker[];\n /** 弧线 */\n arcs?: readonly GlobeArc[];\n /**\n * 一开始正对着的地方\n * @default { lat: 20, lng: 100 }\n */\n center?: GeoPoint;\n /**\n * 自转速度(度 / 秒,向东为正);0 时不自转\n * @default 6\n */\n rotationSpeed?: number;\n /**\n * 可以拖动转动\n * @default true\n */\n draggable?: boolean;\n /**\n * 陆地的点有多密(1 约一万个点,按画质档位再缩放)\n * @default 1\n */\n density?: number;\n /** 陆地点的颜色,默认次要文字色 */\n landColor?: string;\n /** 标注与弧线的颜色,默认品牌色 */\n markerColor?: string;\n /**\n * 大气光晕\n * @default true\n */\n glow?: boolean;\n}\n\n/** Globe 的样式:root、draggable、dragging */\nexport const globeStyles = css.create({\n root: { aspectRatio: '1', width: '100%' },\n draggable: { cursor: 'grab', touchAction: 'pan-y' },\n dragging: { cursor: 'grabbing' },\n});\n\nconst DEG = Math.PI / 180;\n/** 地球的轮廓占画面短边的比例:外面留给大气光晕 */\nconst FIT = 0.8;\nconst FOV = 40;\n\n/** 经纬度 → 球面上的点(半径 radius):经度 0 朝向 +z(正对相机),北极朝 +y */\nexport function latLngToVector(lat: number, lng: number, radius = 1, target = new Vector3()) {\n const phi = lat * DEG;\n const theta = lng * DEG;\n return target.set(\n radius * Math.cos(phi) * Math.sin(theta),\n radius * Math.sin(phi),\n radius * Math.cos(phi) * Math.cos(theta),\n );\n}\n\n/** 陆地位图:某个经纬度是不是陆地 */\nconst landBits = (() => {\n let bytes: Uint8Array | undefined;\n return (lat: number, lng: number) => {\n bytes ??= Uint8Array.from(atob(LAND_BITS), (char) => char.charCodeAt(0));\n const row = clamp(Math.floor(90 - lat), 0, LAND_HEIGHT - 1);\n const column = (((Math.floor(lng + 180) % LAND_WIDTH) + LAND_WIDTH) % LAND_WIDTH) | 0;\n const index = row * LAND_WIDTH + column;\n return (bytes[index >> 3]! & (1 << (index & 7))) !== 0;\n };\n})();\n\n// 点:正面清楚、转到背面淡出;大小随透视缩放\nconst dotVertex = /* glsl */ `\nuniform float uPixelRatio;\nuniform float uScale;\nattribute float aSize;\nattribute float aPhase;\nvarying float vFacing;\nvarying float vPhase;\nvoid main() {\n vec4 world = modelMatrix * vec4(position, 1.0);\n vFacing = dot(normalize(world.xyz), normalize(cameraPosition - world.xyz));\n vPhase = aPhase;\n vec4 view = viewMatrix * world;\n gl_PointSize = aSize * uScale * uPixelRatio / -view.z;\n gl_Position = projectionMatrix * view;\n}\n`;\n\nconst landFragment = /* glsl */ `\nuniform vec3 uColor;\nvarying float vFacing;\nvoid main() {\n float d = length(gl_PointCoord - 0.5);\n float alpha = smoothstep(0.5, 0.3, d) * smoothstep(-0.05, 0.35, vFacing) * 0.85;\n gl_FragColor = vec4(uColor, alpha);\n #include <colorspace_fragment>\n #include <premultiplied_alpha_fragment>\n}\n`;\n\n// 标注:实心的点加一圈向外扩散、渐淡的光圈\nconst markerFragment = /* glsl */ `\nuniform vec3 uColor;\nuniform float uTime;\nvarying float vFacing;\nvarying float vPhase;\nvoid main() {\n float d = length(gl_PointCoord - 0.5) * 2.0;\n float core = smoothstep(0.3, 0.2, d);\n float wave = fract(uTime * 0.6 + vPhase);\n float ring = smoothstep(0.08, 0.0, abs(d - wave)) * (1.0 - wave);\n float alpha = max(core, ring * 0.9) * smoothstep(-0.1, 0.25, vFacing);\n gl_FragColor = vec4(uColor, alpha);\n #include <colorspace_fragment>\n #include <premultiplied_alpha_fragment>\n}\n`;\n\n// 弧线:整条淡淡的底色,加一段从起点流向终点的亮光\nconst arcVertex = /* glsl */ `\nattribute float aT;\nattribute float aPhase;\nvarying float vT;\nvarying float vPhase;\nvarying float vFacing;\nvoid main() {\n vec4 world = modelMatrix * vec4(position, 1.0);\n vFacing = dot(normalize(world.xyz), normalize(cameraPosition - world.xyz));\n vT = aT;\n vPhase = aPhase;\n gl_Position = projectionMatrix * viewMatrix * world;\n}\n`;\n\nconst arcFragment = /* glsl */ `\nuniform vec3 uColor;\nuniform float uTime;\nvarying float vT;\nvarying float vPhase;\nvarying float vFacing;\nvoid main() {\n float head = fract(uTime * 0.35 + vPhase) * 1.4 - 0.2;\n float glow = exp(-pow((vT - head) * 7.0, 2.0));\n float alpha = (0.18 + 0.82 * glow) * smoothstep(-0.25, 0.2, vFacing);\n gl_FragColor = vec4(uColor, alpha);\n #include <colorspace_fragment>\n #include <premultiplied_alpha_fragment>\n}\n`;\n\n// 大气:正对相机的一块方形,按到球心的距离画径向的光(单位是地球半径,uEdge 是轮廓所在的半径):\n// 球面里只有一层淡淡的雾,轮廓外一圈亮边向外淡出\nconst glowVertex = /* glsl */ `\nvarying vec2 vPosition;\nvoid main() {\n vPosition = position.xy;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}\n`;\n\nconst glowFragment = /* glsl */ `\nuniform vec3 uColor;\nuniform float uEdge;\nuniform float uLimit;\nvarying vec2 vPosition;\nvoid main() {\n float r = length(vPosition) / uEdge;\n float inner = smoothstep(0.55, 1.0, r) * 0.22;\n // 到画布边缘(短边方向在 uLimit 处)之前淡完,不留方形的边\n float outer = exp(-(r - 1.0) * 9.0) * smoothstep(uLimit, uLimit - 0.12, r);\n float intensity = r < 1.0 ? inner : outer * 0.75;\n // 先转色彩空间再乘强度(预乘):反过来的话,sRGB 会把很淡的颜色提亮,方形的边缘就露出来了\n gl_FragColor = vec4(uColor, 1.0);\n #include <colorspace_fragment>\n gl_FragColor = vec4(gl_FragColor.rgb, 1.0) * intensity;\n}\n`;\n\n/** 透明叠加的着色器材质 */\nconst overlay = (params: ConstructorParameters<typeof ShaderMaterial>[0]) =>\n new ShaderMaterial({\n ...params,\n transparent: true,\n premultipliedAlpha: true,\n depthWrite: false,\n });\n\n/** 两地之间的大圆弧,抬离地面(越远抬得越高),采样成 segments 段 */\nfunction arcPoints({ from, to }: GlobeArc, segments: number): Vector3[] {\n const a = latLngToVector(from[0], from[1]);\n const b = latLngToVector(to[0], to[1]);\n const angle = a.angleTo(b);\n const lift = 0.06 + angle * 0.22;\n const points: Vector3[] = [];\n for (let i = 0; i <= segments; i++) {\n const t = i / segments;\n // 球面线性插值(slerp),再按 sin 抬高\n const point =\n angle < 1e-6\n ? a.clone()\n : a\n .clone()\n .multiplyScalar(Math.sin((1 - t) * angle) / Math.sin(angle))\n .add(b.clone().multiplyScalar(Math.sin(t * angle) / Math.sin(angle)));\n points.push(point.normalize().multiplyScalar(1 + lift * Math.sin(Math.PI * t)));\n }\n return points;\n}\n\n/** 点阵地球 */\nexport const Globe = _component(\n ({\n markers = [],\n arcs = [],\n center = { lat: 20, lng: 100 },\n rotationSpeed = 6,\n draggable = true,\n density = 1,\n landColor = colors.textMuted,\n markerColor = colors.accent,\n glow = true,\n ...rest\n }: GlobeProps) => {\n // 朝向:一开始正对 center;拖动左右改 yaw、上下改 pitch,松手后带惯性回到自转\n const start = _untrack(center);\n const orbit = createOrbit({ yaw: -start.lng * DEG, pitch: start.lat * DEG });\n\n return () => (\n <EffectSurface\n {...rest}\n sx={[\n globeStyles.root,\n draggable && globeStyles.draggable,\n orbit.dragging && globeStyles.dragging,\n rest.sx,\n ]}\n {...(draggable ? orbit.handlers : {})}\n // 颜色也在键里:改了 landColor、markerColor 要重建场景(颜色在 setup 里读一次)\n sceneKey={`${density}|${glow}|${landColor}|${markerColor}|${JSON.stringify(markers)}|${JSON.stringify(arcs)}`}\n setup={({ scene, quality, still, themeColors }) => {\n const camera = new PerspectiveCamera(FOV, 1, 0.1, 100);\n const palette = themeColors({ land: landColor, marker: markerColor }) as {\n land: Color;\n marker: Color;\n };\n // 标注按颜色分组:同色的一次画完\n const byColor = new Map<string, GlobeMarker[]>();\n for (const marker of markers) {\n const color = marker.color ?? markerColor;\n byColor.set(color, [...(byColor.get(color) ?? []), marker]);\n }\n const markerTints = themeColors(\n Object.fromEntries([...byColor.keys()].map((color, index) => [index, color])),\n ) as Record<string, Color>;\n\n const globe = new Group();\n scene.add(globe);\n const uniforms = {\n uPixelRatio: { value: 1 },\n uScale: { value: 1 },\n uTime: { value: 0 },\n };\n\n // 陆地:斐波那契球面上均匀撒点,落在陆地上的留下\n const candidates = Math.round(24_000 * density * Math.min(1, quality.density));\n const land: number[] = [];\n const golden = Math.PI * (3 - Math.sqrt(5));\n const at = new Vector3();\n for (let i = 0; i < candidates; i++) {\n const y = 1 - (2 * (i + 0.5)) / candidates;\n const lat = Math.asin(y) / DEG;\n const lng = (((((i * golden) / DEG) % 360) + 360) % 360) - 180;\n if (!landBits(lat, lng)) continue;\n latLngToVector(lat, lng, 1, at);\n land.push(at.x, at.y, at.z);\n }\n const landGeometry = new BufferGeometry();\n landGeometry.setAttribute('position', new BufferAttribute(new Float32Array(land), 3));\n const landCount = land.length / 3;\n landGeometry.setAttribute(\n 'aSize',\n new BufferAttribute(new Float32Array(landCount).fill(2.2), 1),\n );\n landGeometry.setAttribute('aPhase', new BufferAttribute(new Float32Array(landCount), 1));\n globe.add(\n new Points(\n landGeometry,\n overlay({\n vertexShader: dotVertex,\n fragmentShader: landFragment,\n uniforms: { ...uniforms, uColor: { value: palette.land } },\n }),\n ),\n );\n\n // 标注:实心点加扩散的光圈\n [...byColor.values()].forEach((list, group) => {\n const positions = new Float32Array(list.length * 3);\n list.forEach((marker, i) => {\n latLngToVector(marker.lat, marker.lng, 1.005, at).toArray(positions, i * 3);\n });\n const geometry = new BufferGeometry();\n geometry.setAttribute('position', new BufferAttribute(positions, 3));\n geometry.setAttribute(\n 'aSize',\n new BufferAttribute(\n Float32Array.from(list, (marker) => 22 * (marker.size ?? 1)),\n 1,\n ),\n );\n geometry.setAttribute(\n 'aPhase',\n new BufferAttribute(\n Float32Array.from(list, (_, i) => (i * 0.37) % 1),\n 1,\n ),\n );\n globe.add(\n new Points(\n geometry,\n overlay({\n vertexShader: dotVertex,\n fragmentShader: markerFragment,\n uniforms: { ...uniforms, uColor: { value: markerTints[group] } },\n }),\n ),\n );\n });\n\n // 弧线:所有弧线放在同一组线段里,一次画完\n if (arcs.length) {\n const SEGMENTS = 64;\n const positions: number[] = [];\n const ts: number[] = [];\n const phases: number[] = [];\n arcs.forEach((arc, index) => {\n const points = arcPoints(arc, SEGMENTS);\n const phase = (index * 0.29) % 1;\n for (let i = 0; i < SEGMENTS; i++) {\n positions.push(...points[i]!.toArray(), ...points[i + 1]!.toArray());\n ts.push(i / SEGMENTS, (i + 1) / SEGMENTS);\n phases.push(phase, phase);\n }\n });\n const geometry = new BufferGeometry();\n geometry.setAttribute('position', new BufferAttribute(new Float32Array(positions), 3));\n geometry.setAttribute('aT', new BufferAttribute(new Float32Array(ts), 1));\n geometry.setAttribute('aPhase', new BufferAttribute(new Float32Array(phases), 1));\n globe.add(\n new LineSegments(\n geometry,\n overlay({\n vertexShader: arcVertex,\n fragmentShader: arcFragment,\n uniforms: { uColor: { value: palette.marker }, uTime: uniforms.uTime },\n }),\n ),\n );\n }\n\n // 透视下球的轮廓比半径大一点:相机距离 d 时在 z = 0 平面上是 d / √(d² − 1)\n const edge = { value: 1 };\n if (glow) {\n // 不随地球转:相机在 z 轴上,xy 平面上的方形总是正对相机\n const atmosphere = new Mesh(\n new PlaneGeometry(3, 3),\n overlay({\n vertexShader: glowVertex,\n fragmentShader: glowFragment,\n uniforms: {\n uColor: { value: palette.marker },\n uEdge: edge,\n uLimit: { value: 1 / FIT },\n },\n }),\n );\n atmosphere.renderOrder = -1;\n scene.add(atmosphere);\n }\n\n const apply = () => globe.rotation.set(orbit.pitch, orbit.yaw, 0, 'XYZ');\n apply();\n\n return {\n resize: (size, context) => {\n camera.aspect = size.width / Math.max(size.height, 1);\n // 轮廓的直径占短边的 FIT:相机距离 d 处的轮廓半径是 d / √(d² − 1),\n // 要它等于 FIT · d · tan(fov / 2),解出 d(宽比高窄时再拉远)\n const t = FIT * Math.tan((FOV * DEG) / 2);\n const fitHeight = Math.sqrt(1 + 1 / (t * t));\n camera.position.z = fitHeight * Math.max(1, 1 / camera.aspect);\n camera.updateProjectionMatrix();\n context.camera = camera;\n const d = camera.position.z;\n edge.value = d / Math.sqrt(d * d - 1);\n uniforms.uPixelRatio.value = size.pixelRatio;\n // 点的大小(CSS 像素)在 z = 相机距离处不变:/ -view.z 的透视缩放乘回来,再按画布大小缩放\n uniforms.uScale.value = (camera.position.z * Math.min(size.width, size.height)) / 360;\n },\n frame: ({ time, delta }) => {\n uniforms.uTime.value = time;\n if (still) return;\n orbit.step(delta, rotationSpeed * DEG);\n apply();\n },\n };\n }}\n />\n );\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"Globe.js","names":["_vtp_readonlyProp","_vtp_restProps","_vtp_untrack","_createVNode","_mergeProps"],"sources":["../../../src/three/globe/Globe.tsx"],"sourcesContent":["/**\n * 点阵地球(div):陆地画成一层细密的点,可以标注地点(markers,向外扩散的光圈),两地之间画弧线(arcs,光点沿弧线流动);\n * 缓缓自转,可以拖动转动(松手后带惯性)。参考 GitHub 首页的地球、cobe。\n *\n * <Globe markers={[{ lat: 31.23, lng: 121.47 }]} arcs={[{ from: [31.23, 121.47], to: [37.77, -122.42] }]} />\n * <Globe center={{ lat: 30, lng: 110 }} rotationSpeed={0} sx={styles.globe} />\n *\n * 陆地来自 Natural Earth 1:110m 的世界地图(1° 的位图,见 land.ts);点的疏密按画质档位。颜色跟随主题:\n * 陆地用次要文字色,标注、弧线与大气光晕用品牌色(可以单独给 color)。默认是正方形,尺寸由使用方决定。\n * 减少动态效果时停在一帧,不自转、弧线不流动。画面是装饰;要让读屏知道内容时给 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 {\n BufferAttribute,\n BufferGeometry,\n Group,\n LineSegments,\n Mesh,\n PerspectiveCamera,\n Points,\n ShaderMaterial,\n PlaneGeometry,\n Vector3,\n type Color,\n} from 'three';\nimport { colors } from '../../config/theme/tokens';\nimport { clamp } from '../../utils/data/number';\nimport { EffectSurface, type EffectProps } from '../core/EffectSurface';\nimport { createOrbit } from '../core/orbit';\nimport { LAND_BITS, LAND_HEIGHT, LAND_WIDTH } from './land';\n\n/** 地图上的一个点:纬度(北正南负)、经度(东正西负),单位度 */\nexport interface GeoPoint {\n /** 纬度:北纬为正,-90 到 90 */\n lat: number;\n /** 经度:东经为正,-180 到 180 */\n lng: number;\n}\n\n/** 标注的地点 */\nexport interface GlobeMarker extends GeoPoint {\n /** 大小的倍数,默认 1 */\n size?: number;\n /** 颜色(token 或 CSS 颜色);不写时用 markerColor */\n color?: string;\n}\n\n/** 两地之间的弧线:[纬度, 经度] */\nexport interface GlobeArc {\n /** 起点 [纬度, 经度] */\n from: readonly [number, number];\n /** 终点 [纬度, 经度] */\n to: readonly [number, number];\n}\n\n/** 未声明的属性落到外层 div 上 */\nexport interface GlobeProps extends EffectProps {\n /** 标注的地点 */\n markers?: readonly GlobeMarker[];\n /** 弧线 */\n arcs?: readonly GlobeArc[];\n /**\n * 一开始正对着的地方\n * @default { lat: 20, lng: 100 }\n */\n center?: GeoPoint;\n /**\n * 自转速度(度 / 秒,向东为正);0 时不自转\n * @default 6\n */\n rotationSpeed?: number;\n /**\n * 可以拖动转动\n * @default true\n */\n draggable?: boolean;\n /**\n * 陆地的点有多密(1 约一万个点,按画质档位再缩放)\n * @default 1\n */\n density?: number;\n /** 陆地点的颜色,默认次要文字色 */\n landColor?: string;\n /** 标注与弧线的颜色,默认品牌色 */\n markerColor?: string;\n /**\n * 大气光晕\n * @default true\n */\n glow?: boolean;\n}\n\n/** Globe 的样式:root、draggable、dragging */\nexport const globeStyles = css.create({\n root: { aspectRatio: '1', width: '100%' },\n draggable: { cursor: 'grab', touchAction: 'pan-y' },\n dragging: { cursor: 'grabbing' },\n});\n\nconst DEG = Math.PI / 180;\n/** 地球的轮廓占画面短边的比例:外面留给大气光晕 */\nconst FIT = 0.8;\nconst FOV = 40;\n\n/** 经纬度 → 球面上的点(半径 radius):经度 0 朝向 +z(正对相机),北极朝 +y */\nexport function latLngToVector(lat: number, lng: number, radius = 1, target = new Vector3()) {\n const phi = lat * DEG;\n const theta = lng * DEG;\n return target.set(\n radius * Math.cos(phi) * Math.sin(theta),\n radius * Math.sin(phi),\n radius * Math.cos(phi) * Math.cos(theta),\n );\n}\n\n/** 陆地位图:某个经纬度是不是陆地 */\nconst landBits = (() => {\n let bytes: Uint8Array | undefined;\n return (lat: number, lng: number) => {\n bytes ??= Uint8Array.from(atob(LAND_BITS), (char) => char.charCodeAt(0));\n const row = clamp(Math.floor(90 - lat), 0, LAND_HEIGHT - 1);\n const column = (((Math.floor(lng + 180) % LAND_WIDTH) + LAND_WIDTH) % LAND_WIDTH) | 0;\n const index = row * LAND_WIDTH + column;\n return (bytes[index >> 3]! & (1 << (index & 7))) !== 0;\n };\n})();\n\n// 点:正面清楚、转到背面淡出;大小随透视缩放\nconst dotVertex = /* glsl */ `\nuniform float uPixelRatio;\nuniform float uScale;\nattribute float aSize;\nattribute float aPhase;\nvarying float vFacing;\nvarying float vPhase;\nvoid main() {\n vec4 world = modelMatrix * vec4(position, 1.0);\n vFacing = dot(normalize(world.xyz), normalize(cameraPosition - world.xyz));\n vPhase = aPhase;\n vec4 view = viewMatrix * world;\n gl_PointSize = aSize * uScale * uPixelRatio / -view.z;\n gl_Position = projectionMatrix * view;\n}\n`;\n\nconst landFragment = /* glsl */ `\nuniform vec3 uColor;\nvarying float vFacing;\nvoid main() {\n float d = length(gl_PointCoord - 0.5);\n float alpha = smoothstep(0.5, 0.3, d) * smoothstep(-0.05, 0.35, vFacing) * 0.85;\n gl_FragColor = vec4(uColor, alpha);\n #include <colorspace_fragment>\n #include <premultiplied_alpha_fragment>\n}\n`;\n\n// 标注:实心的点加一圈向外扩散、渐淡的光圈\nconst markerFragment = /* glsl */ `\nuniform vec3 uColor;\nuniform float uTime;\nvarying float vFacing;\nvarying float vPhase;\nvoid main() {\n float d = length(gl_PointCoord - 0.5) * 2.0;\n float core = smoothstep(0.3, 0.2, d);\n float wave = fract(uTime * 0.6 + vPhase);\n float ring = smoothstep(0.08, 0.0, abs(d - wave)) * (1.0 - wave);\n float alpha = max(core, ring * 0.9) * smoothstep(-0.1, 0.25, vFacing);\n gl_FragColor = vec4(uColor, alpha);\n #include <colorspace_fragment>\n #include <premultiplied_alpha_fragment>\n}\n`;\n\n// 弧线:整条淡淡的底色,加一段从起点流向终点的亮光\nconst arcVertex = /* glsl */ `\nattribute float aT;\nattribute float aPhase;\nvarying float vT;\nvarying float vPhase;\nvarying float vFacing;\nvoid main() {\n vec4 world = modelMatrix * vec4(position, 1.0);\n vFacing = dot(normalize(world.xyz), normalize(cameraPosition - world.xyz));\n vT = aT;\n vPhase = aPhase;\n gl_Position = projectionMatrix * viewMatrix * world;\n}\n`;\n\nconst arcFragment = /* glsl */ `\nuniform vec3 uColor;\nuniform float uTime;\nvarying float vT;\nvarying float vPhase;\nvarying float vFacing;\nvoid main() {\n float head = fract(uTime * 0.35 + vPhase) * 1.4 - 0.2;\n float glow = exp(-pow((vT - head) * 7.0, 2.0));\n float alpha = (0.18 + 0.82 * glow) * smoothstep(-0.25, 0.2, vFacing);\n gl_FragColor = vec4(uColor, alpha);\n #include <colorspace_fragment>\n #include <premultiplied_alpha_fragment>\n}\n`;\n\n// 大气:正对相机的一块方形,按到球心的距离画径向的光(单位是地球半径,uEdge 是轮廓所在的半径):\n// 球面里只有一层淡淡的雾,轮廓外一圈亮边向外淡出\nconst glowVertex = /* glsl */ `\nvarying vec2 vPosition;\nvoid main() {\n vPosition = position.xy;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}\n`;\n\nconst glowFragment = /* glsl */ `\nuniform vec3 uColor;\nuniform float uEdge;\nuniform float uLimit;\nvarying vec2 vPosition;\nvoid main() {\n float r = length(vPosition) / uEdge;\n float inner = smoothstep(0.55, 1.0, r) * 0.22;\n // 到画布边缘(短边方向在 uLimit 处)之前淡完,不留方形的边\n float outer = exp(-(r - 1.0) * 9.0) * smoothstep(uLimit, uLimit - 0.12, r);\n float intensity = r < 1.0 ? inner : outer * 0.75;\n // 先转色彩空间再乘强度(预乘):反过来的话,sRGB 会把很淡的颜色提亮,方形的边缘就露出来了\n gl_FragColor = vec4(uColor, 1.0);\n #include <colorspace_fragment>\n gl_FragColor = vec4(gl_FragColor.rgb, 1.0) * intensity;\n}\n`;\n\n/** 透明叠加的着色器材质 */\nconst overlay = (params: ConstructorParameters<typeof ShaderMaterial>[0]) =>\n new ShaderMaterial({\n ...params,\n transparent: true,\n premultipliedAlpha: true,\n depthWrite: false,\n });\n\n/** 两地之间的大圆弧,抬离地面(越远抬得越高),采样成 segments 段 */\nfunction arcPoints({ from, to }: GlobeArc, segments: number): Vector3[] {\n const a = latLngToVector(from[0], from[1]);\n const b = latLngToVector(to[0], to[1]);\n const angle = a.angleTo(b);\n const lift = 0.06 + angle * 0.22;\n const points: Vector3[] = [];\n for (let i = 0; i <= segments; i++) {\n const t = i / segments;\n // 球面线性插值(slerp),再按 sin 抬高\n const point =\n angle < 1e-6\n ? a.clone()\n : a\n .clone()\n .multiplyScalar(Math.sin((1 - t) * angle) / Math.sin(angle))\n .add(b.clone().multiplyScalar(Math.sin(t * angle) / Math.sin(angle)));\n points.push(point.normalize().multiplyScalar(1 + lift * Math.sin(Math.PI * t)));\n }\n return points;\n}\n\n/** 点阵地球 */\nexport const Globe = _component(\n ({\n markers = [],\n arcs = [],\n center = { lat: 20, lng: 100 },\n rotationSpeed = 6,\n draggable = true,\n density = 1,\n landColor = colors.textMuted,\n markerColor = colors.accent,\n glow = true,\n ...rest\n }: GlobeProps) => {\n // 朝向:一开始正对 center;拖动左右改 yaw、上下改 pitch,松手后带惯性回到自转\n const start = _untrack(center);\n const orbit = createOrbit({ yaw: -start.lng * DEG, pitch: start.lat * DEG });\n\n return () => (\n <EffectSurface\n {...rest}\n sx={[\n globeStyles.root,\n draggable && globeStyles.draggable,\n orbit.dragging && globeStyles.dragging,\n rest.sx,\n ]}\n {...(draggable ? orbit.handlers : {})}\n // 颜色也在键里:改了 landColor、markerColor 要重建场景(颜色在 setup 里读一次)\n sceneKey={`${density}|${glow}|${landColor}|${markerColor}|${JSON.stringify(markers)}|${JSON.stringify(arcs)}`}\n setup={({ scene, quality, still, themeColors }) => {\n const camera = new PerspectiveCamera(FOV, 1, 0.1, 100);\n const palette = themeColors({ land: landColor, marker: markerColor }) as {\n land: Color;\n marker: Color;\n };\n // 标注按颜色分组:同色的一次画完\n const byColor = new Map<string, GlobeMarker[]>();\n for (const marker of markers) {\n const color = marker.color ?? markerColor;\n byColor.set(color, [...(byColor.get(color) ?? []), marker]);\n }\n const markerTints = themeColors(\n Object.fromEntries([...byColor.keys()].map((color, index) => [index, color])),\n ) as Record<string, Color>;\n\n const globe = new Group();\n scene.add(globe);\n const uniforms = {\n uPixelRatio: { value: 1 },\n uScale: { value: 1 },\n uTime: { value: 0 },\n };\n\n // 陆地:斐波那契球面上均匀撒点,落在陆地上的留下\n const candidates = Math.round(24_000 * density * Math.min(1, quality.density));\n const land: number[] = [];\n const golden = Math.PI * (3 - Math.sqrt(5));\n const at = new Vector3();\n for (let i = 0; i < candidates; i++) {\n const y = 1 - (2 * (i + 0.5)) / candidates;\n const lat = Math.asin(y) / DEG;\n const lng = (((((i * golden) / DEG) % 360) + 360) % 360) - 180;\n if (!landBits(lat, lng)) continue;\n latLngToVector(lat, lng, 1, at);\n land.push(at.x, at.y, at.z);\n }\n const landGeometry = new BufferGeometry();\n landGeometry.setAttribute('position', new BufferAttribute(new Float32Array(land), 3));\n const landCount = land.length / 3;\n landGeometry.setAttribute(\n 'aSize',\n new BufferAttribute(new Float32Array(landCount).fill(2.2), 1),\n );\n landGeometry.setAttribute('aPhase', new BufferAttribute(new Float32Array(landCount), 1));\n globe.add(\n new Points(\n landGeometry,\n overlay({\n vertexShader: dotVertex,\n fragmentShader: landFragment,\n uniforms: { ...uniforms, uColor: { value: palette.land } },\n }),\n ),\n );\n\n // 标注:实心点加扩散的光圈\n [...byColor.values()].forEach((list, group) => {\n const positions = new Float32Array(list.length * 3);\n list.forEach((marker, i) => {\n latLngToVector(marker.lat, marker.lng, 1.005, at).toArray(positions, i * 3);\n });\n const geometry = new BufferGeometry();\n geometry.setAttribute('position', new BufferAttribute(positions, 3));\n geometry.setAttribute(\n 'aSize',\n new BufferAttribute(\n Float32Array.from(list, (marker) => 22 * (marker.size ?? 1)),\n 1,\n ),\n );\n geometry.setAttribute(\n 'aPhase',\n new BufferAttribute(\n Float32Array.from(list, (_, i) => (i * 0.37) % 1),\n 1,\n ),\n );\n globe.add(\n new Points(\n geometry,\n overlay({\n vertexShader: dotVertex,\n fragmentShader: markerFragment,\n uniforms: { ...uniforms, uColor: { value: markerTints[group] } },\n }),\n ),\n );\n });\n\n // 弧线:所有弧线放在同一组线段里,一次画完\n if (arcs.length) {\n const SEGMENTS = 64;\n const positions: number[] = [];\n const ts: number[] = [];\n const phases: number[] = [];\n arcs.forEach((arc, index) => {\n const points = arcPoints(arc, SEGMENTS);\n const phase = (index * 0.29) % 1;\n for (let i = 0; i < SEGMENTS; i++) {\n positions.push(...points[i]!.toArray(), ...points[i + 1]!.toArray());\n ts.push(i / SEGMENTS, (i + 1) / SEGMENTS);\n phases.push(phase, phase);\n }\n });\n const geometry = new BufferGeometry();\n geometry.setAttribute('position', new BufferAttribute(new Float32Array(positions), 3));\n geometry.setAttribute('aT', new BufferAttribute(new Float32Array(ts), 1));\n geometry.setAttribute('aPhase', new BufferAttribute(new Float32Array(phases), 1));\n globe.add(\n new LineSegments(\n geometry,\n overlay({\n vertexShader: arcVertex,\n fragmentShader: arcFragment,\n uniforms: { uColor: { value: palette.marker }, uTime: uniforms.uTime },\n }),\n ),\n );\n }\n\n // 透视下球的轮廓比半径大一点:相机距离 d 时在 z = 0 平面上是 d / √(d² − 1)\n const edge = { value: 1 };\n if (glow) {\n // 不随地球转:相机在 z 轴上,xy 平面上的方形总是正对相机\n const atmosphere = new Mesh(\n new PlaneGeometry(3, 3),\n overlay({\n vertexShader: glowVertex,\n fragmentShader: glowFragment,\n uniforms: {\n uColor: { value: palette.marker },\n uEdge: edge,\n uLimit: { value: 1 / FIT },\n },\n }),\n );\n atmosphere.renderOrder = -1;\n scene.add(atmosphere);\n }\n\n const apply = () => globe.rotation.set(orbit.pitch, orbit.yaw, 0, 'XYZ');\n apply();\n\n return {\n resize: (size, context) => {\n camera.aspect = size.width / Math.max(size.height, 1);\n // 轮廓的直径占短边的 FIT:相机距离 d 处的轮廓半径是 d / √(d² − 1),\n // 要它等于 FIT · d · tan(fov / 2),解出 d(宽比高窄时再拉远)\n const t = FIT * Math.tan((FOV * DEG) / 2);\n const fitHeight = Math.sqrt(1 + 1 / (t * t));\n camera.position.z = fitHeight * Math.max(1, 1 / camera.aspect);\n camera.updateProjectionMatrix();\n context.camera = camera;\n const d = camera.position.z;\n edge.value = d / Math.sqrt(d * d - 1);\n uniforms.uPixelRatio.value = size.pixelRatio;\n // 点的大小(CSS 像素)在 z = 相机距离处不变:/ -view.z 的透视缩放乘回来,再按画布大小缩放\n uniforms.uScale.value = (camera.position.z * Math.min(size.width, size.height)) / 360;\n },\n frame: ({ time, delta }) => {\n uniforms.uTime.value = time;\n if (still) return;\n orbit.step(delta, rotationSpeed * DEG);\n apply();\n },\n };\n }}\n />\n );\n },\n);\n"],"mappings":"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"}
@@ -4,8 +4,8 @@ import { Spinner } from "../../base/Spinner.js";
4
4
  import { Small } from "../../base/Text.js";
5
5
  import { EffectSurface } from "../core/EffectSurface.js";
6
6
  import { createOrbit } from "../core/orbit.js";
7
- import { createVNode, mergeProps, ref } from "vue";
8
- import { _component, readonlyProp, restProps, untrack } from "@zerodep-dev/vue-tsx-pro-tsx";
7
+ import { createVNode, ref } from "vue";
8
+ import { _component, mergeJsxProps, readonlyProp, restProps, untrack } from "@zerodep-dev/vue-tsx-pro-tsx";
9
9
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
10
10
  import { ACESFilmicToneMapping, Box3, Group, PMREMGenerator, PerspectiveCamera, Sphere, Vector3 } from "three";
11
11
  import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
@@ -90,7 +90,7 @@ var ModelViewer = /*#__PURE__*/ _component((_props, _ctx) => {
90
90
  distance = Math.min(ZOOM_RANGE[1], Math.max(ZOOM_RANGE[0], distance * Math.exp(event.deltaY * .001)));
91
91
  redraw();
92
92
  }
93
- return () => createVNode(EffectSurface, mergeProps(rest, {
93
+ return () => createVNode(EffectSurface, mergeJsxProps(rest, {
94
94
  "sx": [
95
95
  modelViewerStyles.root,
96
96
  controls.value && modelViewerStyles.interactive,