@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,5 +1,6 @@
1
+ import { useDetachedRender } from "../overlay/detached.js";
1
2
  import { chartDuration, createChartInstances, uniqueHighlightFilter, usePlotSeen } from "./frame.js";
2
- import { render, useId } from "vue";
3
+ import { useId } from "vue";
3
4
  import { effect } from "@zerodep-dev/vue-tsx-pro-tsx";
4
5
  import { SingleContainer, Tooltip } from "@unovis/ts";
5
6
  //#region src/charts/single.tsx
@@ -21,12 +22,12 @@ function useSingleChart(read) {
21
22
  const id = useId();
22
23
  const instances = createChartInstances();
23
24
  let tooltipElement;
25
+ const renderDetached = useDetachedRender();
24
26
  let container;
25
27
  let containerElement;
26
28
  const seen = usePlotSeen(() => read().element);
27
29
  effect(() => () => {
28
30
  container?.destroy();
29
- if (tooltipElement) render(null, tooltipElement);
30
31
  });
31
32
  effect(() => {
32
33
  const { element, ready, tooltip, build } = read();
@@ -55,7 +56,7 @@ function useSingleChart(read) {
55
56
  });
56
57
  return { tooltip(content) {
57
58
  tooltipElement ??= document.createElement("div");
58
- render(content, tooltipElement);
59
+ renderDetached(content, tooltipElement);
59
60
  return tooltipElement;
60
61
  } };
61
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"single.js","names":[],"sources":["../../src/charts/single.tsx"],"sourcesContent":["/**\n * 单容器图表(环形图、桑基图、弦图)共用的绘制过程:Unovis 的 SingleContainer 只建一次,数据与配置变化时 update,\n * 卸载时 destroy;绘图区换了元素(加载、空状态之后重新出现)时容器连同组件、提示框一起重建。\n * 提示框按选择器触发,内容用 Vue 渲染进同一个元素交给 Unovis 定位。在组件 setup 里调用。\n *\n * const chart = useSingleChart(() => ({\n * element: plot, ready: !loading && rows.length > 0, tooltip,\n * build: (instance) => ({ component: …, data: rows, triggers: { [Donut.selectors.segment]: (d) => chart.tooltip(…) } }),\n * }));\n */\nimport { SingleContainer, Tooltip, type ComponentCore } from '@unovis/ts';\nimport { render, useId, type VNode } from 'vue';\nimport { chartDuration, createChartInstances, uniqueHighlightFilter, usePlotSeen } from './frame';\n\n/** 一次绘制要的东西 */\nexport interface SingleChartBuild<D> {\n /** 配置好的组件 */\n component: ComponentCore<D>;\n /** 交给组件的数据 */\n data: D;\n /** 提示框:选择器 → 悬停的数据 → 内容(Unovis 的 Tooltip triggers) */\n triggers?: NonNullable<Tooltip['config']['triggers']>;\n /** 每次画完之后(容器的 onRenderComplete):组件要在画好之后调整的(地图的标签避让) */\n onRender?: () => void;\n}\n\n/** useSingleChart 每次读取的状态 */\nexport interface SingleChartState<D> {\n /** 绘图区元素 */\n element: HTMLElement | null;\n /** 可以画了:不在加载中、有数据 */\n ready: boolean;\n /** 显示提示框 */\n tooltip: boolean;\n /** 配置组件:instance 取跨渲染保留的实例(第一次调用时创建) */\n build: (instance: <C>(key: string, create: () => C) => C) => SingleChartBuild<D>;\n}\n\n/** useSingleChart 的返回值 */\nexport interface SingleChart {\n /** 提示框的内容渲染进同一个元素,交给 Unovis 定位 */\n tooltip(content: VNode): HTMLElement;\n}\n\n/** 单容器图表的绘制 */\nexport function useSingleChart<D>(read: () => SingleChartState<D>): SingleChart {\n const id = useId();\n const instances = createChartInstances();\n let tooltipElement: HTMLElement | undefined;\n let container: SingleContainer<D> | undefined;\n let containerElement: HTMLElement | undefined;\n const seen = usePlotSeen(() => read().element);\n\n _effect(() => () => {\n container?.destroy();\n if (tooltipElement) render(null, tooltipElement);\n });\n _effect(() => {\n const { element, ready, tooltip, build } = read();\n if (!element || !ready || !seen()) return;\n // 绘图区换了元素:旧容器连同组件、提示框一起销毁,实例表清空后重新创建\n if (container && containerElement !== element) {\n container.destroy();\n container = undefined;\n instances.reset();\n }\n const { component, data, triggers, onRender } = build(instances.get);\n const tooltipBox = instances.get('tooltip', () => new Tooltip());\n tooltipBox.setConfig({ triggers: triggers ?? {} });\n const config = {\n component,\n tooltip: tooltip ? tooltipBox : undefined,\n ariaLabel: null,\n duration: chartDuration(element),\n onRenderComplete: onRender,\n };\n if (container) container.update(config, undefined, data);\n else {\n container = new SingleContainer<D>(element, config, data);\n containerElement = element;\n uniqueHighlightFilter(element, `${id}-highlight`);\n }\n });\n\n return {\n tooltip(content) {\n tooltipElement ??= document.createElement('div');\n render(content, tooltipElement);\n return tooltipElement;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA6CA,SAAgB,eAAkB,MAA8C;CAC9E,MAAM,KAAK,MAAM;CACjB,MAAM,YAAY,qBAAqB;CACvC,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM,OAAO,kBAAkB,KAAK,CAAC,CAAC,OAAO;CAE7C,mBAAoB;EAClB,WAAW,QAAQ;EACnB,IAAI,gBAAgB,OAAO,MAAM,cAAc;CACjD,CAAC;CACD,aAAc;EACZ,MAAM,EAAE,SAAS,OAAO,SAAS,UAAU,KAAK;EAChD,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,GAAG;EAEnC,IAAI,aAAa,qBAAqB,SAAS;GAC7C,UAAU,QAAQ;GAClB,YAAY,KAAA;GACZ,UAAU,MAAM;EAClB;EACA,MAAM,EAAE,WAAW,MAAM,UAAU,aAAa,MAAM,UAAU,GAAG;EACnE,MAAM,aAAa,UAAU,IAAI,iBAAiB,IAAI,QAAQ,CAAC;EAC/D,WAAW,UAAU,EAAE,UAAU,YAAY,CAAC,EAAE,CAAC;EACjD,MAAM,SAAS;GACb;GACA,SAAS,UAAU,aAAa,KAAA;GAChC,WAAW;GACX,UAAU,cAAc,OAAO;GAC/B,kBAAkB;EACpB;EACA,IAAI,WAAW,UAAU,OAAO,QAAQ,KAAA,GAAW,IAAI;OAClD;GACH,YAAY,IAAI,gBAAmB,SAAS,QAAQ,IAAI;GACxD,mBAAmB;GACnB,sBAAsB,SAAS,GAAG,GAAE,WAAY;EAClD;CACF,CAAC;CAED,OAAO,EACL,QAAQ,SAAS;EACf,mBAAmB,SAAS,cAAc,KAAK;EAC/C,OAAO,SAAS,cAAc;EAC9B,OAAO;CACT,EACF;AACF"}
1
+ {"version":3,"file":"single.js","names":[],"sources":["../../src/charts/single.tsx"],"sourcesContent":["/**\n * 单容器图表(环形图、桑基图、弦图)共用的绘制过程:Unovis 的 SingleContainer 只建一次,数据与配置变化时 update,\n * 卸载时 destroy;绘图区换了元素(加载、空状态之后重新出现)时容器连同组件、提示框一起重建。\n * 提示框按选择器触发,内容用 Vue 渲染进同一个元素交给 Unovis 定位。在组件 setup 里调用。\n *\n * const chart = useSingleChart(() => ({\n * element: plot, ready: !loading && rows.length > 0, tooltip,\n * build: (instance) => ({ component: …, data: rows, triggers: { [Donut.selectors.segment]: (d) => chart.tooltip(…) } }),\n * }));\n */\nimport { SingleContainer, Tooltip, type ComponentCore } from '@unovis/ts';\nimport { useId, type VNode } from 'vue';\nimport { useDetachedRender } from '../overlay/detached';\nimport { chartDuration, createChartInstances, uniqueHighlightFilter, usePlotSeen } from './frame';\n\n/** 一次绘制要的东西 */\nexport interface SingleChartBuild<D> {\n /** 配置好的组件 */\n component: ComponentCore<D>;\n /** 交给组件的数据 */\n data: D;\n /** 提示框:选择器 → 悬停的数据 → 内容(Unovis 的 Tooltip triggers) */\n triggers?: NonNullable<Tooltip['config']['triggers']>;\n /** 每次画完之后(容器的 onRenderComplete):组件要在画好之后调整的(地图的标签避让) */\n onRender?: () => void;\n}\n\n/** useSingleChart 每次读取的状态 */\nexport interface SingleChartState<D> {\n /** 绘图区元素 */\n element: HTMLElement | null;\n /** 可以画了:不在加载中、有数据 */\n ready: boolean;\n /** 显示提示框 */\n tooltip: boolean;\n /** 配置组件:instance 取跨渲染保留的实例(第一次调用时创建) */\n build: (instance: <C>(key: string, create: () => C) => C) => SingleChartBuild<D>;\n}\n\n/** useSingleChart 的返回值 */\nexport interface SingleChart {\n /** 提示框的内容渲染进同一个元素,交给 Unovis 定位 */\n tooltip(content: VNode): HTMLElement;\n}\n\n/** 单容器图表的绘制 */\nexport function useSingleChart<D>(read: () => SingleChartState<D>): SingleChart {\n const id = useId();\n const instances = createChartInstances();\n let tooltipElement: HTMLElement | undefined;\n // 提示框的内容渲染进 Unovis 管的元素:带上调用处的主题与语言,组件卸载时一起卸载\n const renderDetached = useDetachedRender();\n let container: SingleContainer<D> | undefined;\n let containerElement: HTMLElement | undefined;\n const seen = usePlotSeen(() => read().element);\n\n _effect(() => () => {\n container?.destroy();\n });\n _effect(() => {\n const { element, ready, tooltip, build } = read();\n if (!element || !ready || !seen()) return;\n // 绘图区换了元素:旧容器连同组件、提示框一起销毁,实例表清空后重新创建\n if (container && containerElement !== element) {\n container.destroy();\n container = undefined;\n instances.reset();\n }\n const { component, data, triggers, onRender } = build(instances.get);\n const tooltipBox = instances.get('tooltip', () => new Tooltip());\n tooltipBox.setConfig({ triggers: triggers ?? {} });\n const config = {\n component,\n tooltip: tooltip ? tooltipBox : undefined,\n ariaLabel: null,\n duration: chartDuration(element),\n onRenderComplete: onRender,\n };\n if (container) container.update(config, undefined, data);\n else {\n container = new SingleContainer<D>(element, config, data);\n containerElement = element;\n uniqueHighlightFilter(element, `${id}-highlight`);\n }\n });\n\n return {\n tooltip(content) {\n tooltipElement ??= document.createElement('div');\n renderDetached(content, tooltipElement);\n return tooltipElement;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA8CA,SAAgB,eAAkB,MAA8C;CAC9E,MAAM,KAAK,MAAM;CACjB,MAAM,YAAY,qBAAqB;CACvC,IAAI;CAEJ,MAAM,iBAAiB,kBAAkB;CACzC,IAAI;CACJ,IAAI;CACJ,MAAM,OAAO,kBAAkB,KAAK,CAAC,CAAC,OAAO;CAE7C,mBAAoB;EAClB,WAAW,QAAQ;CACrB,CAAC;CACD,aAAc;EACZ,MAAM,EAAE,SAAS,OAAO,SAAS,UAAU,KAAK;EAChD,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,GAAG;EAEnC,IAAI,aAAa,qBAAqB,SAAS;GAC7C,UAAU,QAAQ;GAClB,YAAY,KAAA;GACZ,UAAU,MAAM;EAClB;EACA,MAAM,EAAE,WAAW,MAAM,UAAU,aAAa,MAAM,UAAU,GAAG;EACnE,MAAM,aAAa,UAAU,IAAI,iBAAiB,IAAI,QAAQ,CAAC;EAC/D,WAAW,UAAU,EAAE,UAAU,YAAY,CAAC,EAAE,CAAC;EACjD,MAAM,SAAS;GACb;GACA,SAAS,UAAU,aAAa,KAAA;GAChC,WAAW;GACX,UAAU,cAAc,OAAO;GAC/B,kBAAkB;EACpB;EACA,IAAI,WAAW,UAAU,OAAO,QAAQ,KAAA,GAAW,IAAI;OAClD;GACH,YAAY,IAAI,gBAAmB,SAAS,QAAQ,IAAI;GACxD,mBAAmB;GACnB,sBAAsB,SAAS,GAAG,GAAE,WAAY;EAClD;CACF,CAAC;CAED,OAAO,EACL,QAAQ,SAAS;EACf,mBAAmB,SAAS,cAAc,KAAK;EAC/C,eAAe,SAAS,cAAc;EACtC,OAAO;CACT,EACF;AACF"}
@@ -1,6 +1,6 @@
1
1
  import * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';
2
2
  import type { VNodeChild } from 'vue';
3
- import { type Highlighter, type TextMatcher, type UiRouter } from './context';
3
+ import { type Highlighter, type TextMatcher, type UiPermissions, type UiRouter } from './context';
4
4
  import { type ComponentDefaults } from './defaults';
5
5
  import { type ComponentStyles } from './styles';
6
6
  import { type Lang } from './lang/lang';
@@ -23,6 +23,8 @@ export interface ProviderProps {
23
23
  styles?: ComponentStyles;
24
24
  /** 路由适配;不写时沿用上层配置 */
25
25
  router?: UiRouter;
26
+ /** 权限判断;不写时沿用上层配置 */
27
+ permissions?: UiPermissions;
26
28
  /** 请求客户端;不写时沿用上层配置 */
27
29
  http?: HttpClient;
28
30
  /** 工作日历;不写时沿用上层配置 */
@@ -4,8 +4,8 @@ import { mergeStyles } from "./styles.js";
4
4
  import { resolveTheme, themeAttrs } from "./theme/theme.js";
5
5
  import { usePrefersDark } from "../utils/dom/media-query.js";
6
6
  import { defineLang } from "./lang/lang.js";
7
- import { computed, createVNode, mergeProps } from "vue";
8
- import { _component, childrenProp, readonlyProp } from "@zerodep-dev/vue-tsx-pro-tsx";
7
+ import { computed, createVNode } from "vue";
8
+ import { _component, childrenProp, mergeJsxProps, readonlyProp } from "@zerodep-dev/vue-tsx-pro-tsx";
9
9
  import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
10
10
  //#region src/config/Provider.tsx
11
11
  /** 局部配置;都不写时只是透明的容器,沿用上层配置 */
@@ -31,6 +31,7 @@ var Provider = /*#__PURE__*/ _component((_props, _ctx) => {
31
31
  const defaults = readonlyProp(_props, "defaults");
32
32
  const styles = readonlyProp(_props, "styles");
33
33
  const router = readonlyProp(_props, "router");
34
+ const permissions = readonlyProp(_props, "permissions");
34
35
  const http = readonlyProp(_props, "http");
35
36
  const workCalendar = readonlyProp(_props, "workCalendar");
36
37
  const ripple = readonlyProp(_props, "ripple");
@@ -63,6 +64,9 @@ var Provider = /*#__PURE__*/ _component((_props, _ctx) => {
63
64
  get router() {
64
65
  return router.value ?? parent.router;
65
66
  },
67
+ get permissions() {
68
+ return permissions.value ?? parent.permissions;
69
+ },
66
70
  get http() {
67
71
  return http.value ?? parent.http;
68
72
  },
@@ -73,7 +77,7 @@ var Provider = /*#__PURE__*/ _component((_props, _ctx) => {
73
77
  return ripple.value ?? parent.ripple;
74
78
  }
75
79
  });
76
- return () => createVNode("div", mergeProps(theme.value ? themeAttrs(currentTheme.value) : {}, css.attrs(providerStyles.root, theme.value != null && providerStyles.themed), {
80
+ return () => createVNode("div", mergeJsxProps(theme.value ? themeAttrs(currentTheme.value) : {}, css.attrs(providerStyles.root, theme.value != null && providerStyles.themed), {
77
81
  "lang": currentLang.value.code,
78
82
  "dir": currentLang.value.direction
79
83
  }), [children.value]);
@@ -87,6 +91,7 @@ var Provider = /*#__PURE__*/ _component((_props, _ctx) => {
87
91
  "defaults",
88
92
  "styles",
89
93
  "router",
94
+ "permissions",
90
95
  "http",
91
96
  "workCalendar",
92
97
  "ripple"
@@ -100,7 +105,7 @@ var Provider = /*#__PURE__*/ _component((_props, _ctx) => {
100
105
  var ConfigScope = /*#__PURE__*/ _component((_props2, _ctx2) => {
101
106
  const children = childrenProp(_props2);
102
107
  const config = useConfig();
103
- return () => createVNode("div", mergeProps(themeAttrs(config.theme), css.attrs(providerStyles.root, providerStyles.themed), {
108
+ return () => createVNode("div", mergeJsxProps(themeAttrs(config.theme), css.attrs(providerStyles.root, providerStyles.themed), {
104
109
  "lang": config.lang.code,
105
110
  "dir": config.lang.direction
106
111
  }), [children.value]);
@@ -1 +1 @@
1
- {"version":3,"file":"Provider.js","names":["_vtp_readonlyProp","_vtp_childrenProp","_vue_computed","_createVNode","_mergeProps"],"sources":["../../src/config/Provider.tsx"],"sourcesContent":["import { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport {\n ConfigContext,\n useConfig,\n type Highlighter,\n type TextMatcher,\n type UiRouter,\n} from './context';\nimport { mergeDefaults, type ComponentDefaults } from './defaults';\nimport { mergeStyles, type ComponentStyles } from './styles';\nimport { defineLang, type Lang } from './lang/lang';\nimport { usePrefersDark } from '../utils/dom/media-query';\nimport type { WorkCalendar } from '../utils/data/workdays';\nimport type { HttpClient } from '../utils/request/http';\nimport { resolveTheme, themeAttrs, type ThemeInput } from './theme/theme';\n\n/** 局部配置;都不写时只是透明的容器,沿用上层配置 */\nexport interface ProviderProps {\n /** 主题;不写时沿用上层配置 */\n theme?: ThemeInput;\n /** 语言;只写要改的字段,其余沿用上层配置 */\n lang?: Partial<Lang>;\n /** 代码高亮器(CodeBlock 用);不写时沿用上层配置 */\n highlighter?: Highlighter;\n /** 额外的文字匹配(拼音);不写时沿用上层配置 */\n textMatcher?: TextMatcher;\n /** 组件默认值:按组件逐个与上层合并,只写要改的 */\n defaults?: ComponentDefaults;\n /** 组件的主题定制:追加在上层的定制之后(见 styles.ts) */\n styles?: ComponentStyles;\n /** 路由适配;不写时沿用上层配置 */\n router?: UiRouter;\n /** 请求客户端;不写时沿用上层配置 */\n http?: HttpClient;\n /** 工作日历;不写时沿用上层配置 */\n workCalendar?: WorkCalendar;\n /** 波纹效果的开关;不写时沿用上层配置 */\n ripple?: boolean;\n children?: VNodeChild;\n}\n\n/** Provider 的样式:root、themed */\nexport const providerStyles = css.create({\n // 不产生盒子,不影响布局;主题变量与文字样式照常由子元素继承\n root: { display: 'contents' },\n themed: {\n color: '_text',\n fontFamily: '_sans',\n fontSize: '_md',\n lineHeight: '_normal',\n },\n});\n\n/**\n * 局部配置主题与语言,可以嵌套:内层只写要改的部分,其余继承外层。\n * 应用级配置见 createUi。\n */\nexport const Provider = _component(\n ({\n theme,\n lang,\n highlighter,\n textMatcher,\n defaults,\n styles,\n router,\n http,\n workCalendar,\n ripple,\n children,\n }: ProviderProps) => {\n const parent = useConfig();\n const prefersDark = usePrefersDark();\n const currentTheme = _derived(theme ? resolveTheme(theme, prefersDark.value) : parent.theme);\n const currentLang = _derived(lang ? defineLang(parent.lang, lang) : parent.lang);\n const currentDefaults = _derived(mergeDefaults(parent.defaults, defaults));\n const currentStyles = _derived(mergeStyles(parent.styles, styles));\n ConfigContext.provide({\n get theme() {\n return currentTheme;\n },\n get lang() {\n return currentLang;\n },\n get highlighter() {\n return highlighter ?? parent.highlighter;\n },\n get textMatcher() {\n return textMatcher ?? parent.textMatcher;\n },\n get defaults() {\n return currentDefaults;\n },\n get styles() {\n return currentStyles;\n },\n get router() {\n return router ?? parent.router;\n },\n get http() {\n return http ?? parent.http;\n },\n get workCalendar() {\n return workCalendar ?? parent.workCalendar;\n },\n get ripple() {\n return ripple ?? parent.ripple;\n },\n });\n\n return () => (\n <div\n {...(theme ? themeAttrs(currentTheme) : {})}\n {...css.attrs(providerStyles.root, theme != null && providerStyles.themed)}\n lang={currentLang.code}\n dir={currentLang.direction}\n >\n {children}\n </div>\n );\n },\n);\n\n/** ConfigScope 的 props */\nexport interface ConfigScopeProps {\n children?: VNodeChild;\n}\n\n/**\n * 给移出 Provider 的内容(Teleport 到 body 的 Toaster 等)重新带上当前的主题、语言与文字方向:\n * 主题变量、lang、dir 都挂在 Provider 的元素上,传送出去的元素不再是它的后代。\n */\nexport const ConfigScope = _component(({ children }: ConfigScopeProps) => {\n const config = useConfig();\n return () => (\n <div\n {...themeAttrs(config.theme)}\n {...css.attrs(providerStyles.root, providerStyles.themed)}\n lang={config.lang.code}\n dir={config.lang.direction}\n >\n {children}\n </div>\n );\n});\n"],"mappings":";;;;;;;;;;;;AA4CA,IAAa,iBAAiB,IAAI,OAAO;CAEvC,MAAM,EAAE,SAAS,WAAW;CAC5B,QAAQ;EACN,OAAO;EACP,YAAY;EACZ,UAAU;EACV,YAAY;CACd;AACF,CAAC;;;;;AAMD,IAAa,WAAW,0BACtB,QAAA,SAYqB;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,OAAAA,aAAA,QAAA,MAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,OAAAA,aAAA,QAAA,MAAA;CAAA,MAAA,eAAAA,aAAA,QAAA,cAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,WAAAC,aAAA,MAAA;CACnB,MAAM,SAAS,UAAU;CACzB,MAAM,cAAc,eAAe;CACnC,MAAM,eAAYC,eAAY,MAAA,QAAQ,aAAY,MAAA,OAAQ,YAAY,KAAK,IAAI,OAAO,KAAK;CAC3F,MAAM,cAAWA,eAAY,KAAA,QAAO,WAAW,OAAO,MAAI,KAAA,KAAM,IAAI,OAAO,IAAI;CAC/E,MAAM,kBAAeA,eAAY,cAAc,OAAO,UAAQ,SAAA,KAAU,CAAC;CACzE,MAAM,gBAAaA,eAAY,YAAY,OAAO,QAAM,OAAA,KAAQ,CAAC;CACjE,cAAc,QAAQ;EACpB,IAAI,QAAQ;GACV,OAAA,aAAA;EACF;EACA,IAAI,OAAO;GACT,OAAA,YAAA;EACF;EACA,IAAI,cAAc;GAChB,OAAO,YAAA,SAAe,OAAO;EAC/B;EACA,IAAI,cAAc;GAChB,OAAO,YAAA,SAAe,OAAO;EAC/B;EACA,IAAI,WAAW;GACb,OAAA,gBAAA;EACF;EACA,IAAI,SAAS;GACX,OAAA,cAAA;EACF;EACA,IAAI,SAAS;GACX,OAAO,OAAA,SAAU,OAAO;EAC1B;EACA,IAAI,OAAO;GACT,OAAO,KAAA,SAAQ,OAAO;EACxB;EACA,IAAI,eAAe;GACjB,OAAO,aAAA,SAAgB,OAAO;EAChC;EACA,IAAI,SAAS;GACX,OAAO,OAAA,SAAU,OAAO;EAC1B;CACF,CAAC;CAED,aAAOC,YAAA,OAAAC,WAEE,MAAA,QAAQ,WAAU,aAAA,KAAa,IAAI,CAAC,GACrC,IAAI,MAAM,eAAe,MAAM,MAAA,SAAS,QAAQ,eAAe,MAAM,GAAC;EAAA,QACpE,YAAA,MAAY;EAAI,OACjB,YAAA,MAAY;CAAS,CAAA,GAAA,CAAA,SAAA,KAAA,CAAA;AAKhC,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH;;;;;;AAWA,IAAa,cAAc,0BAAW,SAAA,UAAoC;CAAA,MAAA,WAAAH,aAAA,OAAA;CACxE,MAAM,SAAS,UAAU;CACzB,aAAOE,YAAA,OAAAC,WAEC,WAAW,OAAO,KAAK,GACvB,IAAI,MAAM,eAAe,MAAM,eAAe,MAAM,GAAC;EAAA,QACnD,OAAO,KAAK;EAAI,OACjB,OAAO,KAAK;CAAS,CAAA,GAAA,CAAA,SAAA,KAAA,CAAA;AAKhC,GAAC,EAAA,MAAA,cAAA,CAAA"}
1
+ {"version":3,"file":"Provider.js","names":["_vtp_readonlyProp","_vtp_childrenProp","_vue_computed","_createVNode","_mergeProps"],"sources":["../../src/config/Provider.tsx"],"sourcesContent":["import { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport {\n ConfigContext,\n useConfig,\n type Highlighter,\n type TextMatcher,\n type UiPermissions,\n type UiRouter,\n} from './context';\nimport { mergeDefaults, type ComponentDefaults } from './defaults';\nimport { mergeStyles, type ComponentStyles } from './styles';\nimport { defineLang, type Lang } from './lang/lang';\nimport { usePrefersDark } from '../utils/dom/media-query';\nimport type { WorkCalendar } from '../utils/data/workdays';\nimport type { HttpClient } from '../utils/request/http';\nimport { resolveTheme, themeAttrs, type ThemeInput } from './theme/theme';\n\n/** 局部配置;都不写时只是透明的容器,沿用上层配置 */\nexport interface ProviderProps {\n /** 主题;不写时沿用上层配置 */\n theme?: ThemeInput;\n /** 语言;只写要改的字段,其余沿用上层配置 */\n lang?: Partial<Lang>;\n /** 代码高亮器(CodeBlock 用);不写时沿用上层配置 */\n highlighter?: Highlighter;\n /** 额外的文字匹配(拼音);不写时沿用上层配置 */\n textMatcher?: TextMatcher;\n /** 组件默认值:按组件逐个与上层合并,只写要改的 */\n defaults?: ComponentDefaults;\n /** 组件的主题定制:追加在上层的定制之后(见 styles.ts) */\n styles?: ComponentStyles;\n /** 路由适配;不写时沿用上层配置 */\n router?: UiRouter;\n /** 权限判断;不写时沿用上层配置 */\n permissions?: UiPermissions;\n /** 请求客户端;不写时沿用上层配置 */\n http?: HttpClient;\n /** 工作日历;不写时沿用上层配置 */\n workCalendar?: WorkCalendar;\n /** 波纹效果的开关;不写时沿用上层配置 */\n ripple?: boolean;\n children?: VNodeChild;\n}\n\n/** Provider 的样式:root、themed */\nexport const providerStyles = css.create({\n // 不产生盒子,不影响布局;主题变量与文字样式照常由子元素继承\n root: { display: 'contents' },\n themed: {\n color: '_text',\n fontFamily: '_sans',\n fontSize: '_md',\n lineHeight: '_normal',\n },\n});\n\n/**\n * 局部配置主题与语言,可以嵌套:内层只写要改的部分,其余继承外层。\n * 应用级配置见 createUi。\n */\nexport const Provider = _component(\n ({\n theme,\n lang,\n highlighter,\n textMatcher,\n defaults,\n styles,\n router,\n permissions,\n http,\n workCalendar,\n ripple,\n children,\n }: ProviderProps) => {\n const parent = useConfig();\n const prefersDark = usePrefersDark();\n const currentTheme = _derived(theme ? resolveTheme(theme, prefersDark.value) : parent.theme);\n const currentLang = _derived(lang ? defineLang(parent.lang, lang) : parent.lang);\n const currentDefaults = _derived(mergeDefaults(parent.defaults, defaults));\n const currentStyles = _derived(mergeStyles(parent.styles, styles));\n ConfigContext.provide({\n get theme() {\n return currentTheme;\n },\n get lang() {\n return currentLang;\n },\n get highlighter() {\n return highlighter ?? parent.highlighter;\n },\n get textMatcher() {\n return textMatcher ?? parent.textMatcher;\n },\n get defaults() {\n return currentDefaults;\n },\n get styles() {\n return currentStyles;\n },\n get router() {\n return router ?? parent.router;\n },\n get permissions() {\n return permissions ?? parent.permissions;\n },\n get http() {\n return http ?? parent.http;\n },\n get workCalendar() {\n return workCalendar ?? parent.workCalendar;\n },\n get ripple() {\n return ripple ?? parent.ripple;\n },\n });\n\n return () => (\n <div\n {...(theme ? themeAttrs(currentTheme) : {})}\n {...css.attrs(providerStyles.root, theme != null && providerStyles.themed)}\n lang={currentLang.code}\n dir={currentLang.direction}\n >\n {children}\n </div>\n );\n },\n);\n\n/** ConfigScope 的 props */\nexport interface ConfigScopeProps {\n children?: VNodeChild;\n}\n\n/**\n * 给移出 Provider 的内容(Teleport 到 body 的 Toaster 等)重新带上当前的主题、语言与文字方向:\n * 主题变量、lang、dir 都挂在 Provider 的元素上,传送出去的元素不再是它的后代。\n */\nexport const ConfigScope = _component(({ children }: ConfigScopeProps) => {\n const config = useConfig();\n return () => (\n <div\n {...themeAttrs(config.theme)}\n {...css.attrs(providerStyles.root, providerStyles.themed)}\n lang={config.lang.code}\n dir={config.lang.direction}\n >\n {children}\n </div>\n );\n});\n"],"mappings":";;;;;;;;;;;;AA+CA,IAAa,iBAAiB,IAAI,OAAO;CAEvC,MAAM,EAAE,SAAS,WAAW;CAC5B,QAAQ;EACN,OAAO;EACP,YAAY;EACZ,UAAU;EACV,YAAY;CACd;AACF,CAAC;;;;;AAMD,IAAa,WAAW,0BACtB,QAAA,SAaqB;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,OAAAA,aAAA,QAAA,MAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,OAAAA,aAAA,QAAA,MAAA;CAAA,MAAA,eAAAA,aAAA,QAAA,cAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,WAAAC,aAAA,MAAA;CACnB,MAAM,SAAS,UAAU;CACzB,MAAM,cAAc,eAAe;CACnC,MAAM,eAAYC,eAAY,MAAA,QAAQ,aAAY,MAAA,OAAQ,YAAY,KAAK,IAAI,OAAO,KAAK;CAC3F,MAAM,cAAWA,eAAY,KAAA,QAAO,WAAW,OAAO,MAAI,KAAA,KAAM,IAAI,OAAO,IAAI;CAC/E,MAAM,kBAAeA,eAAY,cAAc,OAAO,UAAQ,SAAA,KAAU,CAAC;CACzE,MAAM,gBAAaA,eAAY,YAAY,OAAO,QAAM,OAAA,KAAQ,CAAC;CACjE,cAAc,QAAQ;EACpB,IAAI,QAAQ;GACV,OAAA,aAAA;EACF;EACA,IAAI,OAAO;GACT,OAAA,YAAA;EACF;EACA,IAAI,cAAc;GAChB,OAAO,YAAA,SAAe,OAAO;EAC/B;EACA,IAAI,cAAc;GAChB,OAAO,YAAA,SAAe,OAAO;EAC/B;EACA,IAAI,WAAW;GACb,OAAA,gBAAA;EACF;EACA,IAAI,SAAS;GACX,OAAA,cAAA;EACF;EACA,IAAI,SAAS;GACX,OAAO,OAAA,SAAU,OAAO;EAC1B;EACA,IAAI,cAAc;GAChB,OAAO,YAAA,SAAe,OAAO;EAC/B;EACA,IAAI,OAAO;GACT,OAAO,KAAA,SAAQ,OAAO;EACxB;EACA,IAAI,eAAe;GACjB,OAAO,aAAA,SAAgB,OAAO;EAChC;EACA,IAAI,SAAS;GACX,OAAO,OAAA,SAAU,OAAO;EAC1B;CACF,CAAC;CAED,aAAOC,YAAA,OAAAC,cAEE,MAAA,QAAQ,WAAU,aAAA,KAAa,IAAI,CAAC,GACrC,IAAI,MAAM,eAAe,MAAM,MAAA,SAAS,QAAQ,eAAe,MAAM,GAAC;EAAA,QACpE,YAAA,MAAY;EAAI,OACjB,YAAA,MAAY;CAAS,CAAA,GAAA,CAAA,SAAA,KAAA,CAAA;AAKhC,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH;;;;;;AAWA,IAAa,cAAc,0BAAW,SAAA,UAAoC;CAAA,MAAA,WAAAH,aAAA,OAAA;CACxE,MAAM,SAAS,UAAU;CACzB,aAAOE,YAAA,OAAAC,cAEC,WAAW,OAAO,KAAK,GACvB,IAAI,MAAM,eAAe,MAAM,eAAe,MAAM,GAAC;EAAA,QACnD,OAAO,KAAK;EAAI,OACjB,OAAO,KAAK;CAAS,CAAA,GAAA,CAAA,SAAA,KAAA,CAAA;AAKhC,GAAC,EAAA,MAAA,cAAA,CAAA"}
@@ -45,6 +45,14 @@ export interface UiRouter {
45
45
  */
46
46
  replaceQuery?: (patch: QueryPatch) => void;
47
47
  }
48
+ /**
49
+ * 权限判断:用户有没有这个权限点。组件库不知道权限从哪来(后端返回的权限点、角色…),由应用接入:
50
+ *
51
+ * createUi({ permissions: (permission) => access.can(permission) })
52
+ *
53
+ * 在渲染时调用,读响应式状态就能跟随变化(登录、退出、换角色后界面随之更新)。用 Can、useCan 控制界面。
54
+ */
55
+ export type UiPermissions = (permission: string) => boolean;
48
56
  /** 地址里的查询参数:同名多个时是数组;只写了键(?flag)时是空字符串 */
49
57
  export type QueryValues = Readonly<Record<string, string | readonly string[]>>;
50
58
  /** 要改的查询参数:undefined 是删掉 */
@@ -65,6 +73,8 @@ export interface UiConfig {
65
73
  readonly styles: StyleLayers;
66
74
  /** 路由适配;没有时链接就是普通的页面跳转 */
67
75
  readonly router?: UiRouter;
76
+ /** 权限判断;没有时 useCan、Can 一律放行 */
77
+ readonly permissions?: UiPermissions;
68
78
  /** 请求客户端(远程选项、上传、列表查询用);没有时 useHttp 给一个默认的 createHttpClient() */
69
79
  readonly http?: HttpClient;
70
80
  /** 工作日历(时限、剩余工作日用);没有时只按周末算 */
@@ -88,3 +98,11 @@ export declare function useLang(): Lang;
88
98
  * 在 setup 里调用,返回的函数在渲染、计算里调用(读到最新的语言与配置)
89
99
  */
90
100
  export declare function useTextMatcher(): () => TextMatcher;
101
+ /**
102
+ * 当前配置下的权限判断(在 setup 里调用):返回 can(权限点),给数组时有其中任意一个就算有。
103
+ * createUi / Provider 没给 permissions 时一律放行(没有权限体系的应用不受影响)。返回的函数在渲染、计算里调用才跟随变化。
104
+ *
105
+ * const can = useCan();
106
+ * <Button disabled={!can('cost:project:add')}>新建</Button>
107
+ */
108
+ export declare function useCan(): (permission: string | readonly string[]) => boolean;
@@ -52,7 +52,22 @@ function useTextMatcher() {
52
52
  return extra ? (text, query) => builtin(text, query) || extra(text, query) : builtin;
53
53
  };
54
54
  }
55
+ /**
56
+ * 当前配置下的权限判断(在 setup 里调用):返回 can(权限点),给数组时有其中任意一个就算有。
57
+ * createUi / Provider 没给 permissions 时一律放行(没有权限体系的应用不受影响)。返回的函数在渲染、计算里调用才跟随变化。
58
+ *
59
+ * const can = useCan();
60
+ * <Button disabled={!can('cost:project:add')}>新建</Button>
61
+ */
62
+ function useCan() {
63
+ const config = useConfig();
64
+ return (permission) => {
65
+ const has = config.permissions;
66
+ if (!has) return true;
67
+ return typeof permission === "string" ? has(permission) : permission.some((item) => has(item));
68
+ };
69
+ }
55
70
  //#endregion
56
- export { ConfigContext, defaultConfig, useConfig, useLang, useTextMatcher };
71
+ export { ConfigContext, defaultConfig, useCan, useConfig, useLang, useTextMatcher };
57
72
 
58
73
  //# sourceMappingURL=context.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","names":[],"sources":["../../src/config/context.ts"],"sourcesContent":["/**\n * 组件库配置(主题与语言)的上下文:应用级由 createUi 提供,局部由 <Provider> 覆盖;\n * 都没有时使用默认值(亮色主题 + 简体中文),组件单独使用也能工作。\n */\nimport { createContext } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { createMatcher } from '../utils/data/collation';\nimport type { WorkCalendar } from '../utils/data/workdays';\nimport type { HttpClient } from '../utils/request/http';\nimport type { ComponentDefaults } from './defaults';\nimport type { StyleLayers } from './styles';\nimport type { Lang } from './lang/lang';\nimport { zhCN } from './lang/zh-CN';\nimport { lightTheme } from './theme/light';\nimport type { Theme } from './theme/theme';\n\n/**\n * 代码高亮器:代码 + 语言 → 高亮后的行内 HTML(只含 span 与换行的 br,不含 pre、code),交给 CodeBlock。\n * 组件库不依赖具体实现;Shiki 的实现见子路径 `@zerodep-dev/vue-tsx-pro-ui/shiki` 的 createShikiHighlighter。\n * 返回的 HTML 直接写进页面,实现方负责转义代码里的文字。\n */\nexport type Highlighter = (code: string, lang: string) => Promise<string>;\n\n/**\n * 额外的文字匹配:选项过滤、命令面板、树的搜索在内置匹配(忽略大小写与重音的包含)之外再试它,任一命中就算。\n * 拼音匹配见子路径 `@zerodep-dev/vue-tsx-pro-ui/pinyin` 的 createPinyinMatcher\n */\nexport type TextMatcher = (text: string, query: string) => boolean;\n\n/**\n * 路由适配(参考 React Aria 的 RouterProvider 与 useHref):组件库不依赖具体的路由库。\n * Link、LinkButton、导航组件渲染的仍是 <a href>;普通左键点击站内链接时改由 navigate 跳转(不刷新页面),\n * 新窗口打开、按着修饰键、外部链接、下载照常交给浏览器。\n *\n * createUi({ router: { navigate: (href) => router.push(href), isActive: (href) => route.path === href } })\n */\nexport interface UiRouter {\n /** 站内跳转;收到的是组件上写的原文(/orders),不是 resolve 之后的地址 */\n navigate: (href: string) => void;\n /**\n * 站内链接渲染到 <a href> 上的真实地址:补上路由的 base(/admin/orders)、hash 模式的 #(#/orders),\n * 新标签页打开、复制链接才对。不写时原样渲染\n */\n resolve?: (href: string) => string;\n /** href 是不是当前页:导航组件据此加 aria-current=\"page\"。在渲染时调用,读路由的响应式状态就能跟随变化 */\n isActive?: (href: string) => boolean;\n /**\n * 站内跳转之前问一下(useLeaveConfirmation 用):guard 返回 false(或 resolve 成 false)时不跳转;返回注销函数。\n * 只在路径变了时问,同一页里换 query、锚点不问\n */\n beforeLeave?: (guard: () => boolean | Promise<boolean>) => () => void;\n /** 当前地址的查询参数(useQueryState 用);读路由的响应式状态,在 watch、渲染里读能跟随变化 */\n query?: () => QueryValues;\n /**\n * 改当前地址的查询参数(replace,不加历史记录):patch 里的键覆盖,值为 undefined 的删掉,其余不动。\n * 同一轮里调用几次要合并成一次跳转(各状态分别写入时互不覆盖)\n */\n replaceQuery?: (patch: QueryPatch) => void;\n}\n\n/** 地址里的查询参数:同名多个时是数组;只写了键(?flag)时是空字符串 */\nexport type QueryValues = Readonly<Record<string, string | readonly string[]>>;\n\n/** 要改的查询参数:undefined 是删掉 */\nexport type QueryPatch = Readonly<Record<string, string | readonly string[] | undefined>>;\n\n/** 提供方用 getter 暴露当前值,读取方在渲染或 computed 里读取即可跟随变化 */\nexport interface UiConfig {\n /** 当前主题(明暗已按系统设置选定) */\n readonly theme: Theme;\n /** 当前语言:地区格式与界面文案 */\n readonly lang: Lang;\n /** 代码高亮器;没有时 CodeBlock 显示纯文本 */\n readonly highlighter?: Highlighter;\n /** 额外的文字匹配(拼音);没有时只按字面匹配 */\n readonly textMatcher?: TextMatcher;\n /** 组件默认值(见 defaults.ts) */\n readonly defaults: ComponentDefaults;\n /** 组件的主题定制,外层在前(见 styles.ts) */\n readonly styles: StyleLayers;\n /** 路由适配;没有时链接就是普通的页面跳转 */\n readonly router?: UiRouter;\n /** 请求客户端(远程选项、上传、列表查询用);没有时 useHttp 给一个默认的 createHttpClient() */\n readonly http?: HttpClient;\n /** 工作日历(时限、剩余工作日用);没有时只按周末算 */\n readonly workCalendar?: WorkCalendar;\n /** 可点击组件按下时的波纹效果,默认开启;组件的 ripple prop 可以单独覆盖 */\n readonly ripple: boolean;\n}\n\n/** 配置的注入键:createUi 在应用级提供,Provider 在局部覆盖 */\nexport const ConfigContext = createContext<UiConfig>('Provider');\n\n/** 默认配置:亮色主题 + 简体中文 */\nexport const defaultConfig: UiConfig = {\n theme: lightTheme,\n lang: zhCN,\n defaults: {},\n styles: {},\n ripple: true,\n};\n\n/** 当前的主题与语言配置;没有 createUi 与 Provider 时为默认配置 */\nexport function useConfig(): UiConfig {\n return ConfigContext.inject(defaultConfig);\n}\n\n/**\n * 当前语言:`const lang = useLang()`,之后 `lang.confirm`、`lang.timeZone`。\n * 返回的对象总是转发到最新配置,在渲染函数里读取即可随 Provider 切换语言。\n */\nexport function useLang(): Lang {\n const config = useConfig();\n // 所有读取都转发到当前语言,展开与 Object.keys 也能拿到完整字段\n return new Proxy({} as Lang, {\n get: (_, key) => Reflect.get(config.lang, key),\n has: (_, key) => Reflect.has(config.lang, key),\n ownKeys: () => Reflect.ownKeys(config.lang),\n getOwnPropertyDescriptor: (_, key) => {\n const descriptor = Reflect.getOwnPropertyDescriptor(config.lang, key);\n return descriptor && { ...descriptor, configurable: true };\n },\n });\n}\n\n/**\n * 当前配置下的文字匹配:内置匹配(按当前语言忽略大小写与重音)或 textMatcher(拼音)任一命中。\n * 在 setup 里调用,返回的函数在渲染、计算里调用(读到最新的语言与配置)\n */\nexport function useTextMatcher(): () => TextMatcher {\n const config = useConfig();\n return () => {\n const builtin = createMatcher(config.lang.code);\n const extra = config.textMatcher;\n return extra ? (text, query) => builtin(text, query) || extra(text, query) : builtin;\n };\n}\n"],"mappings":";;;;;;;;;;AA0FA,IAAa,gBAAgB,cAAwB,UAAU;;AAG/D,IAAa,gBAA0B;CACrC,OAAO;CACP,MAAM;CACN,UAAU,CAAC;CACX,QAAQ,CAAC;CACT,QAAQ;AACV;;AAGA,SAAgB,YAAsB;CACpC,OAAO,cAAc,OAAO,aAAa;AAC3C;;;;;AAMA,SAAgB,UAAgB;CAC9B,MAAM,SAAS,UAAU;CAEzB,OAAO,IAAI,MAAM,CAAC,GAAW;EAC3B,MAAM,GAAG,QAAQ,QAAQ,IAAI,OAAO,MAAM,GAAG;EAC7C,MAAM,GAAG,QAAQ,QAAQ,IAAI,OAAO,MAAM,GAAG;EAC7C,eAAe,QAAQ,QAAQ,OAAO,IAAI;EAC1C,2BAA2B,GAAG,QAAQ;GACpC,MAAM,aAAa,QAAQ,yBAAyB,OAAO,MAAM,GAAG;GACpE,OAAO,cAAc;IAAE,GAAG;IAAY,cAAc;GAAK;EAC3D;CACF,CAAC;AACH;;;;;AAMA,SAAgB,iBAAoC;CAClD,MAAM,SAAS,UAAU;CACzB,aAAa;EACX,MAAM,UAAU,cAAc,OAAO,KAAK,IAAI;EAC9C,MAAM,QAAQ,OAAO;EACrB,OAAO,SAAS,MAAM,UAAU,QAAQ,MAAM,KAAK,KAAK,MAAM,MAAM,KAAK,IAAI;CAC/E;AACF"}
1
+ {"version":3,"file":"context.js","names":[],"sources":["../../src/config/context.ts"],"sourcesContent":["/**\n * 组件库配置(主题与语言)的上下文:应用级由 createUi 提供,局部由 <Provider> 覆盖;\n * 都没有时使用默认值(亮色主题 + 简体中文),组件单独使用也能工作。\n */\nimport { createContext } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { createMatcher } from '../utils/data/collation';\nimport type { WorkCalendar } from '../utils/data/workdays';\nimport type { HttpClient } from '../utils/request/http';\nimport type { ComponentDefaults } from './defaults';\nimport type { StyleLayers } from './styles';\nimport type { Lang } from './lang/lang';\nimport { zhCN } from './lang/zh-CN';\nimport { lightTheme } from './theme/light';\nimport type { Theme } from './theme/theme';\n\n/**\n * 代码高亮器:代码 + 语言 → 高亮后的行内 HTML(只含 span 与换行的 br,不含 pre、code),交给 CodeBlock。\n * 组件库不依赖具体实现;Shiki 的实现见子路径 `@zerodep-dev/vue-tsx-pro-ui/shiki` 的 createShikiHighlighter。\n * 返回的 HTML 直接写进页面,实现方负责转义代码里的文字。\n */\nexport type Highlighter = (code: string, lang: string) => Promise<string>;\n\n/**\n * 额外的文字匹配:选项过滤、命令面板、树的搜索在内置匹配(忽略大小写与重音的包含)之外再试它,任一命中就算。\n * 拼音匹配见子路径 `@zerodep-dev/vue-tsx-pro-ui/pinyin` 的 createPinyinMatcher\n */\nexport type TextMatcher = (text: string, query: string) => boolean;\n\n/**\n * 路由适配(参考 React Aria 的 RouterProvider 与 useHref):组件库不依赖具体的路由库。\n * Link、LinkButton、导航组件渲染的仍是 <a href>;普通左键点击站内链接时改由 navigate 跳转(不刷新页面),\n * 新窗口打开、按着修饰键、外部链接、下载照常交给浏览器。\n *\n * createUi({ router: { navigate: (href) => router.push(href), isActive: (href) => route.path === href } })\n */\nexport interface UiRouter {\n /** 站内跳转;收到的是组件上写的原文(/orders),不是 resolve 之后的地址 */\n navigate: (href: string) => void;\n /**\n * 站内链接渲染到 <a href> 上的真实地址:补上路由的 base(/admin/orders)、hash 模式的 #(#/orders),\n * 新标签页打开、复制链接才对。不写时原样渲染\n */\n resolve?: (href: string) => string;\n /** href 是不是当前页:导航组件据此加 aria-current=\"page\"。在渲染时调用,读路由的响应式状态就能跟随变化 */\n isActive?: (href: string) => boolean;\n /**\n * 站内跳转之前问一下(useLeaveConfirmation 用):guard 返回 false(或 resolve 成 false)时不跳转;返回注销函数。\n * 只在路径变了时问,同一页里换 query、锚点不问\n */\n beforeLeave?: (guard: () => boolean | Promise<boolean>) => () => void;\n /** 当前地址的查询参数(useQueryState 用);读路由的响应式状态,在 watch、渲染里读能跟随变化 */\n query?: () => QueryValues;\n /**\n * 改当前地址的查询参数(replace,不加历史记录):patch 里的键覆盖,值为 undefined 的删掉,其余不动。\n * 同一轮里调用几次要合并成一次跳转(各状态分别写入时互不覆盖)\n */\n replaceQuery?: (patch: QueryPatch) => void;\n}\n\n/**\n * 权限判断:用户有没有这个权限点。组件库不知道权限从哪来(后端返回的权限点、角色…),由应用接入:\n *\n * createUi({ permissions: (permission) => access.can(permission) })\n *\n * 在渲染时调用,读响应式状态就能跟随变化(登录、退出、换角色后界面随之更新)。用 Can、useCan 控制界面。\n */\nexport type UiPermissions = (permission: string) => boolean;\n\n/** 地址里的查询参数:同名多个时是数组;只写了键(?flag)时是空字符串 */\nexport type QueryValues = Readonly<Record<string, string | readonly string[]>>;\n\n/** 要改的查询参数:undefined 是删掉 */\nexport type QueryPatch = Readonly<Record<string, string | readonly string[] | undefined>>;\n\n/** 提供方用 getter 暴露当前值,读取方在渲染或 computed 里读取即可跟随变化 */\nexport interface UiConfig {\n /** 当前主题(明暗已按系统设置选定) */\n readonly theme: Theme;\n /** 当前语言:地区格式与界面文案 */\n readonly lang: Lang;\n /** 代码高亮器;没有时 CodeBlock 显示纯文本 */\n readonly highlighter?: Highlighter;\n /** 额外的文字匹配(拼音);没有时只按字面匹配 */\n readonly textMatcher?: TextMatcher;\n /** 组件默认值(见 defaults.ts) */\n readonly defaults: ComponentDefaults;\n /** 组件的主题定制,外层在前(见 styles.ts) */\n readonly styles: StyleLayers;\n /** 路由适配;没有时链接就是普通的页面跳转 */\n readonly router?: UiRouter;\n /** 权限判断;没有时 useCan、Can 一律放行 */\n readonly permissions?: UiPermissions;\n /** 请求客户端(远程选项、上传、列表查询用);没有时 useHttp 给一个默认的 createHttpClient() */\n readonly http?: HttpClient;\n /** 工作日历(时限、剩余工作日用);没有时只按周末算 */\n readonly workCalendar?: WorkCalendar;\n /** 可点击组件按下时的波纹效果,默认开启;组件的 ripple prop 可以单独覆盖 */\n readonly ripple: boolean;\n}\n\n/** 配置的注入键:createUi 在应用级提供,Provider 在局部覆盖 */\nexport const ConfigContext = createContext<UiConfig>('Provider');\n\n/** 默认配置:亮色主题 + 简体中文 */\nexport const defaultConfig: UiConfig = {\n theme: lightTheme,\n lang: zhCN,\n defaults: {},\n styles: {},\n ripple: true,\n};\n\n/** 当前的主题与语言配置;没有 createUi 与 Provider 时为默认配置 */\nexport function useConfig(): UiConfig {\n return ConfigContext.inject(defaultConfig);\n}\n\n/**\n * 当前语言:`const lang = useLang()`,之后 `lang.confirm`、`lang.timeZone`。\n * 返回的对象总是转发到最新配置,在渲染函数里读取即可随 Provider 切换语言。\n */\nexport function useLang(): Lang {\n const config = useConfig();\n // 所有读取都转发到当前语言,展开与 Object.keys 也能拿到完整字段\n return new Proxy({} as Lang, {\n get: (_, key) => Reflect.get(config.lang, key),\n has: (_, key) => Reflect.has(config.lang, key),\n ownKeys: () => Reflect.ownKeys(config.lang),\n getOwnPropertyDescriptor: (_, key) => {\n const descriptor = Reflect.getOwnPropertyDescriptor(config.lang, key);\n return descriptor && { ...descriptor, configurable: true };\n },\n });\n}\n\n/**\n * 当前配置下的文字匹配:内置匹配(按当前语言忽略大小写与重音)或 textMatcher(拼音)任一命中。\n * 在 setup 里调用,返回的函数在渲染、计算里调用(读到最新的语言与配置)\n */\nexport function useTextMatcher(): () => TextMatcher {\n const config = useConfig();\n return () => {\n const builtin = createMatcher(config.lang.code);\n const extra = config.textMatcher;\n return extra ? (text, query) => builtin(text, query) || extra(text, query) : builtin;\n };\n}\n\n/**\n * 当前配置下的权限判断(在 setup 里调用):返回 can(权限点),给数组时有其中任意一个就算有。\n * createUi / Provider 没给 permissions 时一律放行(没有权限体系的应用不受影响)。返回的函数在渲染、计算里调用才跟随变化。\n *\n * const can = useCan();\n * <Button disabled={!can('cost:project:add')}>新建</Button>\n */\nexport function useCan(): (permission: string | readonly string[]) => boolean {\n const config = useConfig();\n return (permission) => {\n const has = config.permissions;\n if (!has) return true;\n return typeof permission === 'string' ? has(permission) : permission.some((item) => has(item));\n };\n}\n"],"mappings":";;;;;;;;;;AAqGA,IAAa,gBAAgB,cAAwB,UAAU;;AAG/D,IAAa,gBAA0B;CACrC,OAAO;CACP,MAAM;CACN,UAAU,CAAC;CACX,QAAQ,CAAC;CACT,QAAQ;AACV;;AAGA,SAAgB,YAAsB;CACpC,OAAO,cAAc,OAAO,aAAa;AAC3C;;;;;AAMA,SAAgB,UAAgB;CAC9B,MAAM,SAAS,UAAU;CAEzB,OAAO,IAAI,MAAM,CAAC,GAAW;EAC3B,MAAM,GAAG,QAAQ,QAAQ,IAAI,OAAO,MAAM,GAAG;EAC7C,MAAM,GAAG,QAAQ,QAAQ,IAAI,OAAO,MAAM,GAAG;EAC7C,eAAe,QAAQ,QAAQ,OAAO,IAAI;EAC1C,2BAA2B,GAAG,QAAQ;GACpC,MAAM,aAAa,QAAQ,yBAAyB,OAAO,MAAM,GAAG;GACpE,OAAO,cAAc;IAAE,GAAG;IAAY,cAAc;GAAK;EAC3D;CACF,CAAC;AACH;;;;;AAMA,SAAgB,iBAAoC;CAClD,MAAM,SAAS,UAAU;CACzB,aAAa;EACX,MAAM,UAAU,cAAc,OAAO,KAAK,IAAI;EAC9C,MAAM,QAAQ,OAAO;EACrB,OAAO,SAAS,MAAM,UAAU,QAAQ,MAAM,KAAK,KAAK,MAAM,MAAM,KAAK,IAAI;CAC/E;AACF;;;;;;;;AASA,SAAgB,SAA8D;CAC5E,MAAM,SAAS,UAAU;CACzB,QAAQ,eAAe;EACrB,MAAM,MAAM,OAAO;EACnB,IAAI,CAAC,KAAK,OAAO;EACjB,OAAO,OAAO,eAAe,WAAW,IAAI,UAAU,IAAI,WAAW,MAAM,SAAS,IAAI,IAAI,CAAC;CAC/F;AACF"}
@@ -2,9 +2,9 @@
2
2
  * 应用级配置:在宿主入口里 `app.use(createUi({ theme, lang }))`,所有 TSX 页面共享,不必逐页包裹 Provider。
3
3
  * 传入 ref 或 getter 即可在运行时切换主题与语言。
4
4
  */
5
- import { type MaybeRefOrGetter, type Plugin } from 'vue';
5
+ import { type MaybeRefOrGetter, type ObjectPlugin } from 'vue';
6
6
  import * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';
7
- import { type Highlighter, type TextMatcher, type UiRouter } from './context';
7
+ import { type Highlighter, type TextMatcher, type UiPermissions, type UiRouter } from './context';
8
8
  import type { ComponentDefaults } from './defaults';
9
9
  import { type ComponentStyles } from './styles';
10
10
  import { type Lang } from './lang/lang';
@@ -27,6 +27,8 @@ export interface UiOptions {
27
27
  styles?: ComponentStyles;
28
28
  /** 路由适配:站内链接不刷新页面地跳转、导航组件判断当前页(见 UiRouter) */
29
29
  router?: UiRouter;
30
+ /** 权限判断:`(权限点) => 用户有没有`,Can、useCan 据此控制按钮等界面;不写时一律放行(见 UiPermissions) */
31
+ permissions?: UiPermissions;
30
32
  /** 请求客户端:createHttpClient({ baseURL, onRequest, onResponse }),或包一层 axios、ky(见 HttpClient) */
31
33
  http?: HttpClient;
32
34
  /** 工作日历:createWorkCalendar({ holidays, workdays }) 带上法定节假日与调休;不写时只按周末算 */
@@ -45,8 +47,23 @@ export declare const documentStyles: Readonly<{
45
47
  body: css.CompiledStyles;
46
48
  page: css.CompiledStyles;
47
49
  }>;
50
+ /** 服务端渲染时 `<html>` 与 `<body>` 要带的属性(createUi 在浏览器里写到页面根元素上的那些) */
51
+ export interface DocumentAttrs {
52
+ /** `<html>` 的属性:主题的类、变量(style)、data-theme,传了 lang 时还有 lang、dir */
53
+ html: Record<string, string>;
54
+ /** `<body>` 的属性:paintDocument 时去掉外边距的类 */
55
+ body: Record<string, string>;
56
+ }
57
+ /** createUi 的结果:Vue 插件,另外能给出服务端渲染时页面根元素的属性 */
58
+ export interface UiPlugin extends ObjectPlugin {
59
+ /**
60
+ * 服务端渲染:`<html>`、`<body>` 要带的属性,首屏就是这套主题与语言,不等客户端接管后再变。
61
+ * 服务端不知道系统的明暗,跟随系统的主题按亮色给;`themeBootScript` 在页面加载前按用户的选择改过来
62
+ */
63
+ documentAttrs(): DocumentAttrs;
64
+ }
48
65
  /**
49
66
  * 应用级配置的 Vue 插件:`app.use(createUi({ theme: { light: lightTheme, dark: darkTheme } }))`。
50
67
  * 主题的 CSS 变量写在页面根元素上,所有 TSX 页面共享;应用卸载时撤销。
51
68
  */
52
- export declare function createUi(options?: UiOptions): Plugin;
69
+ export declare function createUi(options?: UiOptions): UiPlugin;
@@ -27,60 +27,91 @@ var documentStyles = css.create({
27
27
  * 主题的 CSS 变量写在页面根元素上,所有 TSX 页面共享;应用卸载时撤销。
28
28
  */
29
29
  function createUi(options = {}) {
30
- return { install(app) {
31
- const scope = effectScope();
32
- app.onUnmount(() => scope.stop());
33
- scope.run(() => {
34
- const prefersDark = usePrefersDark();
35
- const theme = computed(() => resolveTheme(toValue(options.theme) ?? defaultConfig.theme, prefersDark.value));
36
- const lang = computed(() => defineLang(defaultConfig.lang, toValue(options.lang) ?? {}));
37
- app.provide(ConfigContext.key, {
38
- get theme() {
39
- return theme.value;
40
- },
41
- get lang() {
42
- return lang.value;
43
- },
44
- highlighter: options.highlighter,
45
- textMatcher: options.textMatcher,
46
- defaults: options.defaults ?? {},
47
- styles: mergeStyles({}, options.styles),
48
- router: options.router,
49
- http: options.http,
50
- workCalendar: options.workCalendar,
51
- ripple: options.ripple ?? true
52
- });
53
- if (options.lang && typeof document !== "undefined") {
54
- const root = document.documentElement;
55
- const previous = {
56
- lang: root.lang,
57
- dir: root.dir
58
- };
59
- watchEffect(() => {
60
- root.lang = lang.value.code;
61
- root.dir = lang.value.direction;
62
- });
63
- app.onUnmount(() => Object.assign(root, previous));
30
+ return {
31
+ documentAttrs() {
32
+ const html = {};
33
+ const body = {};
34
+ if (options.lang) {
35
+ const lang = defineLang(defaultConfig.lang, toValue(options.lang));
36
+ html.lang = lang.code;
37
+ html.dir = lang.direction;
64
38
  }
65
- if ((options.theme || options.paintDocument) && typeof document !== "undefined") {
66
- const root = document.documentElement;
67
- if (options.paintDocument) root.style.removeProperty("background-color");
68
- if (options.paintDocument) root.style.removeProperty("color");
69
- watchEffect((onCleanup) => onCleanup(applyTheme(root, theme.value, options.paintDocument ?? false)));
70
- if (options.paintDocument && document.body) {
71
- const body = document.body;
72
- const classes = css.attrs(documentStyles.body).class?.split(" ") ?? [];
73
- body.classList.add(...classes);
74
- app.onUnmount(() => body.classList.remove(...classes));
75
- }
39
+ if (options.theme || options.paintDocument) {
40
+ const theme = resolveTheme(toValue(options.theme) ?? defaultConfig.theme, false);
41
+ const { classes, variables } = rootThemeAttrs(theme, options.paintDocument ?? false);
42
+ if (classes.length) html.class = classes.join(" ");
43
+ const style = Object.entries(variables).map(([name, value]) => `${name}:${value}`).join(";");
44
+ if (style) html.style = style;
45
+ html["data-theme"] = theme.name;
46
+ if (options.paintDocument) body.class = css.attrs(documentStyles.body).class ?? "";
76
47
  }
77
- });
78
- } };
48
+ return {
49
+ html,
50
+ body
51
+ };
52
+ },
53
+ install(app) {
54
+ const scope = effectScope();
55
+ app.onUnmount(() => scope.stop());
56
+ scope.run(() => {
57
+ const prefersDark = usePrefersDark();
58
+ const theme = computed(() => resolveTheme(toValue(options.theme) ?? defaultConfig.theme, prefersDark.value));
59
+ const lang = computed(() => defineLang(defaultConfig.lang, toValue(options.lang) ?? {}));
60
+ app.provide(ConfigContext.key, {
61
+ get theme() {
62
+ return theme.value;
63
+ },
64
+ get lang() {
65
+ return lang.value;
66
+ },
67
+ highlighter: options.highlighter,
68
+ textMatcher: options.textMatcher,
69
+ defaults: options.defaults ?? {},
70
+ styles: mergeStyles({}, options.styles),
71
+ router: options.router,
72
+ permissions: options.permissions,
73
+ http: options.http,
74
+ workCalendar: options.workCalendar,
75
+ ripple: options.ripple ?? true
76
+ });
77
+ if (options.lang && typeof document !== "undefined") {
78
+ const root = document.documentElement;
79
+ const previous = {
80
+ lang: root.lang,
81
+ dir: root.dir
82
+ };
83
+ watchEffect(() => {
84
+ root.lang = lang.value.code;
85
+ root.dir = lang.value.direction;
86
+ });
87
+ app.onUnmount(() => Object.assign(root, previous));
88
+ }
89
+ if ((options.theme || options.paintDocument) && typeof document !== "undefined") {
90
+ const root = document.documentElement;
91
+ if (options.paintDocument) root.style.removeProperty("background-color");
92
+ if (options.paintDocument) root.style.removeProperty("color");
93
+ watchEffect((onCleanup) => onCleanup(applyTheme(root, theme.value, options.paintDocument ?? false)));
94
+ if (options.paintDocument && document.body) {
95
+ const body = document.body;
96
+ const classes = css.attrs(documentStyles.body).class?.split(" ") ?? [];
97
+ body.classList.add(...classes);
98
+ app.onUnmount(() => body.classList.remove(...classes));
99
+ }
100
+ }
101
+ });
102
+ }
103
+ };
104
+ }
105
+ /** 主题挂到页面根元素上的类与 CSS 变量;paint 时加上整页的底色与字体(浏览器里写到元素上,服务端写进 HTML) */
106
+ function rootThemeAttrs(theme, paint) {
107
+ return {
108
+ classes: css.attrs(...theme.styles, paint && documentStyles.page).class?.split(" ").filter(Boolean) ?? [],
109
+ variables: themeVariables(theme)
110
+ };
79
111
  }
80
112
  /** 把主题的 class、CSS 变量与 data-theme 写到元素上,返回撤销函数 */
81
113
  function applyTheme(element, theme, paint) {
82
- const classes = css.attrs(...theme.styles, paint && documentStyles.page).class?.split(" ").filter(Boolean) ?? [];
83
- const variables = themeVariables(theme);
114
+ const { classes, variables } = rootThemeAttrs(theme, paint);
84
115
  element.classList.add(...classes);
85
116
  for (const [name, value] of Object.entries(variables)) element.style.setProperty(name, value);
86
117
  element.dataset.theme = theme.name;
@@ -1 +1 @@
1
- {"version":3,"file":"createUi.js","names":[],"sources":["../../src/config/createUi.ts"],"sourcesContent":["/**\n * 应用级配置:在宿主入口里 `app.use(createUi({ theme, lang }))`,所有 TSX 页面共享,不必逐页包裹 Provider。\n * 传入 ref 或 getter 即可在运行时切换主题与语言。\n */\nimport {\n computed,\n effectScope,\n toValue,\n watchEffect,\n type MaybeRefOrGetter,\n type Plugin,\n} from 'vue';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport {\n ConfigContext,\n defaultConfig,\n type Highlighter,\n type TextMatcher,\n type UiRouter,\n} from './context';\nimport type { ComponentDefaults } from './defaults';\nimport { mergeStyles, type ComponentStyles } from './styles';\nimport { defineLang, type Lang } from './lang/lang';\nimport { usePrefersDark } from '../utils/dom/media-query';\nimport type { WorkCalendar } from '../utils/data/workdays';\nimport type { HttpClient } from '../utils/request/http';\nimport { resolveTheme, themeVariables, type Theme, type ThemeInput } from './theme/theme';\n\n/** 应用级配置;theme 与 lang 可以传 ref 或 getter,运行时切换,其余在安装时确定 */\nexport interface UiOptions {\n /** 主题;不写时用亮色主题,也不改动页面根元素 */\n theme?: MaybeRefOrGetter<ThemeInput>;\n /** 只写要改的字段,其余用简体中文的默认值 */\n lang?: MaybeRefOrGetter<Partial<Lang>>;\n /** 代码高亮器(CodeBlock 用),如 `@zerodep-dev/vue-tsx-pro-ui/shiki` 的 createShikiHighlighter();不写时显示纯文本 */\n highlighter?: Highlighter;\n /** 额外的文字匹配,如 `@zerodep-dev/vue-tsx-pro-ui/pinyin` 的 createPinyinMatcher():选项过滤、命令面板认拼音;不写时只按字面匹配 */\n textMatcher?: TextMatcher;\n /** 组件默认值,如 `{ Button: { variant: 'outline' } }`(见 defaults.ts) */\n defaults?: ComponentDefaults;\n /** 组件的主题定制:追加样式、新增档位,如 `{ Button: { base: { root: { letterSpacing: '0.02em' } } } }`(见 styles.ts) */\n styles?: ComponentStyles;\n /** 路由适配:站内链接不刷新页面地跳转、导航组件判断当前页(见 UiRouter) */\n router?: UiRouter;\n /** 请求客户端:createHttpClient({ baseURL, onRequest, onResponse }),或包一层 axios、ky(见 HttpClient) */\n http?: HttpClient;\n /** 工作日历:createWorkCalendar({ holidays, workdays }) 带上法定节假日与调休;不写时只按周末算 */\n workCalendar?: WorkCalendar;\n /** 按下时的波纹效果,默认 true;关掉后组件的 ripple prop 仍可单独打开 */\n ripple?: boolean;\n /**\n * 页面根元素也用主题的背景色、文字色与字体,并去掉 body 的默认外边距,默认 false。\n * 整页都由组件库主题管理的站点(如文档站)打开:页面边缘、回弹滚动露出的地方不再是浏览器的默认色,\n * AppShell 贴满窗口、四周不留 8px 的白边;配合 themeBootScript 时接手它写的行内颜色\n */\n paintDocument?: boolean;\n}\n\n/** paintDocument 时页面根元素的样式 */\nexport const documentStyles = css.create({\n // 字号不设:根元素的字号是 rem 的基准,留给浏览器(用户的字号设置)\n page: {\n backgroundColor: '_background',\n color: '_text',\n fontFamily: '_sans',\n lineHeight: '_normal',\n // macOS 上用灰度抗锯齿,深色底上的浅色文字不发虚;其他系统忽略\n WebkitFontSmoothing: 'antialiased',\n MozOsxFontSmoothing: 'grayscale',\n },\n // 浏览器给 body 的 8px 外边距:整页的外壳(AppShell)要贴满窗口\n body: { margin: 0 },\n});\n\n/**\n * 应用级配置的 Vue 插件:`app.use(createUi({ theme: { light: lightTheme, dark: darkTheme } }))`。\n * 主题的 CSS 变量写在页面根元素上,所有 TSX 页面共享;应用卸载时撤销。\n */\nexport function createUi(options: UiOptions = {}): Plugin {\n return {\n install(app) {\n const scope = effectScope();\n app.onUnmount(() => scope.stop());\n scope.run(() => {\n const prefersDark = usePrefersDark();\n const theme = computed(() =>\n resolveTheme(toValue(options.theme) ?? defaultConfig.theme, prefersDark.value),\n );\n const lang = computed(() => defineLang(defaultConfig.lang, toValue(options.lang) ?? {}));\n app.provide(ConfigContext.key, {\n get theme() {\n return theme.value;\n },\n get lang() {\n return lang.value;\n },\n highlighter: options.highlighter,\n textMatcher: options.textMatcher,\n defaults: options.defaults ?? {},\n styles: mergeStyles({}, options.styles),\n router: options.router,\n http: options.http,\n workCalendar: options.workCalendar,\n ripple: options.ripple ?? true,\n });\n // 应用级的语言也写在页面根元素上(Provider 写在自己的元素上):读屏按 lang 选发音,\n // 从右到左的语言靠 dir 镜像排版与滚动条;没传 lang 时不动,宿主自己管\n if (options.lang && typeof document !== 'undefined') {\n const root = document.documentElement;\n const previous = { lang: root.lang, dir: root.dir };\n watchEffect(() => {\n root.lang = lang.value.code;\n root.dir = lang.value.direction;\n });\n app.onUnmount(() => Object.assign(root, previous));\n }\n // 应用级没有容器元素,主题变量挂在页面根元素上;变量名带 vtp- 前缀,不会与宿主冲突。\n // 只开 paintDocument、不传主题时用默认主题(整页也要有底色、字体,body 去掉外边距)\n if ((options.theme || options.paintDocument) && typeof document !== 'undefined') {\n const root = document.documentElement;\n // themeBootScript 在应用加载前写的行内颜色:交给主题的 class\n if (options.paintDocument) root.style.removeProperty('background-color');\n if (options.paintDocument) root.style.removeProperty('color');\n watchEffect((onCleanup) =>\n onCleanup(applyTheme(root, theme.value, options.paintDocument ?? false)),\n );\n if (options.paintDocument && document.body) {\n const body = document.body;\n const classes = css.attrs(documentStyles.body).class?.split(' ') ?? [];\n body.classList.add(...classes);\n app.onUnmount(() => body.classList.remove(...classes));\n }\n }\n });\n },\n };\n}\n\n/** 把主题的 class、CSS 变量与 data-theme 写到元素上,返回撤销函数 */\nfunction applyTheme(element: HTMLElement, theme: Theme, paint: boolean) {\n const classes =\n css\n .attrs(...theme.styles, paint && documentStyles.page)\n .class?.split(' ')\n .filter(Boolean) ?? [];\n const variables = themeVariables(theme);\n element.classList.add(...classes);\n for (const [name, value] of Object.entries(variables)) element.style.setProperty(name, value);\n element.dataset.theme = theme.name;\n return () => {\n element.classList.remove(...classes);\n for (const name of Object.keys(variables)) element.style.removeProperty(name);\n delete element.dataset.theme;\n };\n}\n"],"mappings":";;;;;;;;;;;;;AA2DA,IAAa,iBAAiB,IAAI,OAAO;CAEvC,MAAM;EACJ,iBAAiB;EACjB,OAAO;EACP,YAAY;EACZ,YAAY;EAEZ,qBAAqB;EACrB,qBAAqB;CACvB;CAEA,MAAM,EAAE,QAAQ,EAAE;AACpB,CAAC;;;;;AAMD,SAAgB,SAAS,UAAqB,CAAC,GAAW;CACxD,OAAO,EACL,QAAQ,KAAK;EACX,MAAM,QAAQ,YAAY;EAC1B,IAAI,gBAAgB,MAAM,KAAK,CAAC;EAChC,MAAM,UAAU;GACd,MAAM,cAAc,eAAe;GACnC,MAAM,QAAQ,eACZ,aAAa,QAAQ,QAAQ,KAAK,KAAK,cAAc,OAAO,YAAY,KAAK,CAC/E;GACA,MAAM,OAAO,eAAe,WAAW,cAAc,MAAM,QAAQ,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC;GACvF,IAAI,QAAQ,cAAc,KAAK;IAC7B,IAAI,QAAQ;KACV,OAAO,MAAM;IACf;IACA,IAAI,OAAO;KACT,OAAO,KAAK;IACd;IACA,aAAa,QAAQ;IACrB,aAAa,QAAQ;IACrB,UAAU,QAAQ,YAAY,CAAC;IAC/B,QAAQ,YAAY,CAAC,GAAG,QAAQ,MAAM;IACtC,QAAQ,QAAQ;IAChB,MAAM,QAAQ;IACd,cAAc,QAAQ;IACtB,QAAQ,QAAQ,UAAU;GAC5B,CAAC;GAGD,IAAI,QAAQ,QAAQ,OAAO,aAAa,aAAa;IACnD,MAAM,OAAO,SAAS;IACtB,MAAM,WAAW;KAAE,MAAM,KAAK;KAAM,KAAK,KAAK;IAAI;IAClD,kBAAkB;KAChB,KAAK,OAAO,KAAK,MAAM;KACvB,KAAK,MAAM,KAAK,MAAM;IACxB,CAAC;IACD,IAAI,gBAAgB,OAAO,OAAO,MAAM,QAAQ,CAAC;GACnD;GAGA,KAAK,QAAQ,SAAS,QAAQ,kBAAkB,OAAO,aAAa,aAAa;IAC/E,MAAM,OAAO,SAAS;IAEtB,IAAI,QAAQ,eAAe,KAAK,MAAM,eAAe,kBAAkB;IACvE,IAAI,QAAQ,eAAe,KAAK,MAAM,eAAe,OAAO;IAC5D,aAAa,cACX,UAAU,WAAW,MAAM,MAAM,OAAO,QAAQ,iBAAiB,KAAK,CAAC,CACzE;IACA,IAAI,QAAQ,iBAAiB,SAAS,MAAM;KAC1C,MAAM,OAAO,SAAS;KACtB,MAAM,UAAU,IAAI,MAAM,eAAe,IAAI,CAAC,CAAC,OAAO,MAAM,GAAG,KAAK,CAAA;KACpE,KAAK,UAAU,IAAI,GAAG,OAAO;KAC7B,IAAI,gBAAgB,KAAK,UAAU,OAAO,GAAG,OAAO,CAAC;IACvD;GACF;EACF,CAAC;CACH,EACF;AACF;;AAGA,SAAS,WAAW,SAAsB,OAAc,OAAgB;CACtE,MAAM,UACJ,IACG,MAAM,GAAG,MAAM,QAAQ,SAAS,eAAe,IAAI,CAAC,CACpD,OAAO,MAAM,GAAG,CAAC,CACjB,OAAO,OAAO,KAAK,CAAA;CACxB,MAAM,YAAY,eAAe,KAAK;CACtC,QAAQ,UAAU,IAAI,GAAG,OAAO;CAChC,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,SAAS,GAAG,QAAQ,MAAM,YAAY,MAAM,KAAK;CAC5F,QAAQ,QAAQ,QAAQ,MAAM;CAC9B,aAAa;EACX,QAAQ,UAAU,OAAO,GAAG,OAAO;EACnC,KAAK,MAAM,QAAQ,OAAO,KAAK,SAAS,GAAG,QAAQ,MAAM,eAAe,IAAI;EAC5E,OAAO,QAAQ,QAAQ;CACzB;AACF"}
1
+ {"version":3,"file":"createUi.js","names":[],"sources":["../../src/config/createUi.ts"],"sourcesContent":["/**\n * 应用级配置:在宿主入口里 `app.use(createUi({ theme, lang }))`,所有 TSX 页面共享,不必逐页包裹 Provider。\n * 传入 ref 或 getter 即可在运行时切换主题与语言。\n */\nimport {\n computed,\n effectScope,\n toValue,\n watchEffect,\n type MaybeRefOrGetter,\n type ObjectPlugin,\n} from 'vue';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport {\n ConfigContext,\n defaultConfig,\n type Highlighter,\n type TextMatcher,\n type UiPermissions,\n type UiRouter,\n} from './context';\nimport type { ComponentDefaults } from './defaults';\nimport { mergeStyles, type ComponentStyles } from './styles';\nimport { defineLang, type Lang } from './lang/lang';\nimport { usePrefersDark } from '../utils/dom/media-query';\nimport type { WorkCalendar } from '../utils/data/workdays';\nimport type { HttpClient } from '../utils/request/http';\nimport { resolveTheme, themeVariables, type Theme, type ThemeInput } from './theme/theme';\n\n/** 应用级配置;theme 与 lang 可以传 ref 或 getter,运行时切换,其余在安装时确定 */\nexport interface UiOptions {\n /** 主题;不写时用亮色主题,也不改动页面根元素 */\n theme?: MaybeRefOrGetter<ThemeInput>;\n /** 只写要改的字段,其余用简体中文的默认值 */\n lang?: MaybeRefOrGetter<Partial<Lang>>;\n /** 代码高亮器(CodeBlock 用),如 `@zerodep-dev/vue-tsx-pro-ui/shiki` 的 createShikiHighlighter();不写时显示纯文本 */\n highlighter?: Highlighter;\n /** 额外的文字匹配,如 `@zerodep-dev/vue-tsx-pro-ui/pinyin` 的 createPinyinMatcher():选项过滤、命令面板认拼音;不写时只按字面匹配 */\n textMatcher?: TextMatcher;\n /** 组件默认值,如 `{ Button: { variant: 'outline' } }`(见 defaults.ts) */\n defaults?: ComponentDefaults;\n /** 组件的主题定制:追加样式、新增档位,如 `{ Button: { base: { root: { letterSpacing: '0.02em' } } } }`(见 styles.ts) */\n styles?: ComponentStyles;\n /** 路由适配:站内链接不刷新页面地跳转、导航组件判断当前页(见 UiRouter) */\n router?: UiRouter;\n /** 权限判断:`(权限点) => 用户有没有`,Can、useCan 据此控制按钮等界面;不写时一律放行(见 UiPermissions) */\n permissions?: UiPermissions;\n /** 请求客户端:createHttpClient({ baseURL, onRequest, onResponse }),或包一层 axios、ky(见 HttpClient) */\n http?: HttpClient;\n /** 工作日历:createWorkCalendar({ holidays, workdays }) 带上法定节假日与调休;不写时只按周末算 */\n workCalendar?: WorkCalendar;\n /** 按下时的波纹效果,默认 true;关掉后组件的 ripple prop 仍可单独打开 */\n ripple?: boolean;\n /**\n * 页面根元素也用主题的背景色、文字色与字体,并去掉 body 的默认外边距,默认 false。\n * 整页都由组件库主题管理的站点(如文档站)打开:页面边缘、回弹滚动露出的地方不再是浏览器的默认色,\n * AppShell 贴满窗口、四周不留 8px 的白边;配合 themeBootScript 时接手它写的行内颜色\n */\n paintDocument?: boolean;\n}\n\n/** paintDocument 时页面根元素的样式 */\nexport const documentStyles = css.create({\n // 字号不设:根元素的字号是 rem 的基准,留给浏览器(用户的字号设置)\n page: {\n backgroundColor: '_background',\n color: '_text',\n fontFamily: '_sans',\n lineHeight: '_normal',\n // macOS 上用灰度抗锯齿,深色底上的浅色文字不发虚;其他系统忽略\n WebkitFontSmoothing: 'antialiased',\n MozOsxFontSmoothing: 'grayscale',\n },\n // 浏览器给 body 的 8px 外边距:整页的外壳(AppShell)要贴满窗口\n body: { margin: 0 },\n});\n\n/** 服务端渲染时 `<html>` 与 `<body>` 要带的属性(createUi 在浏览器里写到页面根元素上的那些) */\nexport interface DocumentAttrs {\n /** `<html>` 的属性:主题的类、变量(style)、data-theme,传了 lang 时还有 lang、dir */\n html: Record<string, string>;\n /** `<body>` 的属性:paintDocument 时去掉外边距的类 */\n body: Record<string, string>;\n}\n\n/** createUi 的结果:Vue 插件,另外能给出服务端渲染时页面根元素的属性 */\nexport interface UiPlugin extends ObjectPlugin {\n /**\n * 服务端渲染:`<html>`、`<body>` 要带的属性,首屏就是这套主题与语言,不等客户端接管后再变。\n * 服务端不知道系统的明暗,跟随系统的主题按亮色给;`themeBootScript` 在页面加载前按用户的选择改过来\n */\n documentAttrs(): DocumentAttrs;\n}\n\n/**\n * 应用级配置的 Vue 插件:`app.use(createUi({ theme: { light: lightTheme, dark: darkTheme } }))`。\n * 主题的 CSS 变量写在页面根元素上,所有 TSX 页面共享;应用卸载时撤销。\n */\nexport function createUi(options: UiOptions = {}): UiPlugin {\n return {\n documentAttrs() {\n const html: Record<string, string> = {};\n const body: Record<string, string> = {};\n if (options.lang) {\n const lang = defineLang(defaultConfig.lang, toValue(options.lang));\n html.lang = lang.code;\n html.dir = lang.direction;\n }\n if (options.theme || options.paintDocument) {\n const theme = resolveTheme(toValue(options.theme) ?? defaultConfig.theme, false);\n const { classes, variables } = rootThemeAttrs(theme, options.paintDocument ?? false);\n if (classes.length) html.class = classes.join(' ');\n const style = Object.entries(variables)\n .map(([name, value]) => `${name}:${value}`)\n .join(';');\n if (style) html.style = style;\n html['data-theme'] = theme.name;\n if (options.paintDocument) body.class = css.attrs(documentStyles.body).class ?? '';\n }\n return { html, body };\n },\n install(app) {\n const scope = effectScope();\n app.onUnmount(() => scope.stop());\n scope.run(() => {\n const prefersDark = usePrefersDark();\n const theme = computed(() =>\n resolveTheme(toValue(options.theme) ?? defaultConfig.theme, prefersDark.value),\n );\n const lang = computed(() => defineLang(defaultConfig.lang, toValue(options.lang) ?? {}));\n app.provide(ConfigContext.key, {\n get theme() {\n return theme.value;\n },\n get lang() {\n return lang.value;\n },\n highlighter: options.highlighter,\n textMatcher: options.textMatcher,\n defaults: options.defaults ?? {},\n styles: mergeStyles({}, options.styles),\n router: options.router,\n permissions: options.permissions,\n http: options.http,\n workCalendar: options.workCalendar,\n ripple: options.ripple ?? true,\n });\n // 应用级的语言也写在页面根元素上(Provider 写在自己的元素上):读屏按 lang 选发音,\n // 从右到左的语言靠 dir 镜像排版与滚动条;没传 lang 时不动,宿主自己管\n if (options.lang && typeof document !== 'undefined') {\n const root = document.documentElement;\n const previous = { lang: root.lang, dir: root.dir };\n watchEffect(() => {\n root.lang = lang.value.code;\n root.dir = lang.value.direction;\n });\n app.onUnmount(() => Object.assign(root, previous));\n }\n // 应用级没有容器元素,主题变量挂在页面根元素上;变量名带 vtp- 前缀,不会与宿主冲突。\n // 只开 paintDocument、不传主题时用默认主题(整页也要有底色、字体,body 去掉外边距)\n if ((options.theme || options.paintDocument) && typeof document !== 'undefined') {\n const root = document.documentElement;\n // themeBootScript 在应用加载前写的行内颜色:交给主题的 class\n if (options.paintDocument) root.style.removeProperty('background-color');\n if (options.paintDocument) root.style.removeProperty('color');\n watchEffect((onCleanup) =>\n onCleanup(applyTheme(root, theme.value, options.paintDocument ?? false)),\n );\n if (options.paintDocument && document.body) {\n const body = document.body;\n const classes = css.attrs(documentStyles.body).class?.split(' ') ?? [];\n body.classList.add(...classes);\n app.onUnmount(() => body.classList.remove(...classes));\n }\n }\n });\n },\n };\n}\n\n/** 主题挂到页面根元素上的类与 CSS 变量;paint 时加上整页的底色与字体(浏览器里写到元素上,服务端写进 HTML) */\nfunction rootThemeAttrs(theme: Theme, paint: boolean) {\n const classes =\n css\n .attrs(...theme.styles, paint && documentStyles.page)\n .class?.split(' ')\n .filter(Boolean) ?? [];\n return { classes, variables: themeVariables(theme) };\n}\n\n/** 把主题的 class、CSS 变量与 data-theme 写到元素上,返回撤销函数 */\nfunction applyTheme(element: HTMLElement, theme: Theme, paint: boolean) {\n const { classes, variables } = rootThemeAttrs(theme, paint);\n element.classList.add(...classes);\n for (const [name, value] of Object.entries(variables)) element.style.setProperty(name, value);\n element.dataset.theme = theme.name;\n return () => {\n element.classList.remove(...classes);\n for (const name of Object.keys(variables)) element.style.removeProperty(name);\n delete element.dataset.theme;\n };\n}\n"],"mappings":";;;;;;;;;;;;;AA8DA,IAAa,iBAAiB,IAAI,OAAO;CAEvC,MAAM;EACJ,iBAAiB;EACjB,OAAO;EACP,YAAY;EACZ,YAAY;EAEZ,qBAAqB;EACrB,qBAAqB;CACvB;CAEA,MAAM,EAAE,QAAQ,EAAE;AACpB,CAAC;;;;;AAuBD,SAAgB,SAAS,UAAqB,CAAC,GAAa;CAC1D,OAAO;EACL,gBAAgB;GACd,MAAM,OAA+B,CAAC;GACtC,MAAM,OAA+B,CAAC;GACtC,IAAI,QAAQ,MAAM;IAChB,MAAM,OAAO,WAAW,cAAc,MAAM,QAAQ,QAAQ,IAAI,CAAC;IACjE,KAAK,OAAO,KAAK;IACjB,KAAK,MAAM,KAAK;GAClB;GACA,IAAI,QAAQ,SAAS,QAAQ,eAAe;IAC1C,MAAM,QAAQ,aAAa,QAAQ,QAAQ,KAAK,KAAK,cAAc,OAAO,KAAK;IAC/E,MAAM,EAAE,SAAS,cAAc,eAAe,OAAO,QAAQ,iBAAiB,KAAK;IACnF,IAAI,QAAQ,QAAQ,KAAK,QAAQ,QAAQ,KAAK,GAAG;IACjD,MAAM,QAAQ,OAAO,QAAQ,SAAS,CAAC,CACpC,KAAK,CAAC,MAAM,WAAW,GAAG,KAAI,GAAI,OAAO,CAAC,CAC1C,KAAK,GAAG;IACX,IAAI,OAAO,KAAK,QAAQ;IACxB,KAAK,gBAAgB,MAAM;IAC3B,IAAI,QAAQ,eAAe,KAAK,QAAQ,IAAI,MAAM,eAAe,IAAI,CAAC,CAAC,SAAS;GAClF;GACA,OAAO;IAAE;IAAM;GAAK;EACtB;EACA,QAAQ,KAAK;GACX,MAAM,QAAQ,YAAY;GAC1B,IAAI,gBAAgB,MAAM,KAAK,CAAC;GAChC,MAAM,UAAU;IACd,MAAM,cAAc,eAAe;IACnC,MAAM,QAAQ,eACZ,aAAa,QAAQ,QAAQ,KAAK,KAAK,cAAc,OAAO,YAAY,KAAK,CAC/E;IACA,MAAM,OAAO,eAAe,WAAW,cAAc,MAAM,QAAQ,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC;IACvF,IAAI,QAAQ,cAAc,KAAK;KAC7B,IAAI,QAAQ;MACV,OAAO,MAAM;KACf;KACA,IAAI,OAAO;MACT,OAAO,KAAK;KACd;KACA,aAAa,QAAQ;KACrB,aAAa,QAAQ;KACrB,UAAU,QAAQ,YAAY,CAAC;KAC/B,QAAQ,YAAY,CAAC,GAAG,QAAQ,MAAM;KACtC,QAAQ,QAAQ;KAChB,aAAa,QAAQ;KACrB,MAAM,QAAQ;KACd,cAAc,QAAQ;KACtB,QAAQ,QAAQ,UAAU;IAC5B,CAAC;IAGD,IAAI,QAAQ,QAAQ,OAAO,aAAa,aAAa;KACnD,MAAM,OAAO,SAAS;KACtB,MAAM,WAAW;MAAE,MAAM,KAAK;MAAM,KAAK,KAAK;KAAI;KAClD,kBAAkB;MAChB,KAAK,OAAO,KAAK,MAAM;MACvB,KAAK,MAAM,KAAK,MAAM;KACxB,CAAC;KACD,IAAI,gBAAgB,OAAO,OAAO,MAAM,QAAQ,CAAC;IACnD;IAGA,KAAK,QAAQ,SAAS,QAAQ,kBAAkB,OAAO,aAAa,aAAa;KAC/E,MAAM,OAAO,SAAS;KAEtB,IAAI,QAAQ,eAAe,KAAK,MAAM,eAAe,kBAAkB;KACvE,IAAI,QAAQ,eAAe,KAAK,MAAM,eAAe,OAAO;KAC5D,aAAa,cACX,UAAU,WAAW,MAAM,MAAM,OAAO,QAAQ,iBAAiB,KAAK,CAAC,CACzE;KACA,IAAI,QAAQ,iBAAiB,SAAS,MAAM;MAC1C,MAAM,OAAO,SAAS;MACtB,MAAM,UAAU,IAAI,MAAM,eAAe,IAAI,CAAC,CAAC,OAAO,MAAM,GAAG,KAAK,CAAA;MACpE,KAAK,UAAU,IAAI,GAAG,OAAO;MAC7B,IAAI,gBAAgB,KAAK,UAAU,OAAO,GAAG,OAAO,CAAC;KACvD;IACF;GACF,CAAC;EACH;CACF;AACF;;AAGA,SAAS,eAAe,OAAc,OAAgB;CAMpD,OAAO;EAAE,SAJP,IACG,MAAM,GAAG,MAAM,QAAQ,SAAS,eAAe,IAAI,CAAC,CACpD,OAAO,MAAM,GAAG,CAAC,CACjB,OAAO,OAAO,KAAK,CAAA;EACN,WAAW,eAAe,KAAK;CAAE;AACrD;;AAGA,SAAS,WAAW,SAAsB,OAAc,OAAgB;CACtE,MAAM,EAAE,SAAS,cAAc,eAAe,OAAO,KAAK;CAC1D,QAAQ,UAAU,IAAI,GAAG,OAAO;CAChC,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,SAAS,GAAG,QAAQ,MAAM,YAAY,MAAM,KAAK;CAC5F,QAAQ,QAAQ,QAAQ,MAAM;CAC9B,aAAa;EACX,QAAQ,UAAU,OAAO,GAAG,OAAO;EACnC,KAAK,MAAM,QAAQ,OAAO,KAAK,SAAS,GAAG,QAAQ,MAAM,eAAe,IAAI;EAC5E,OAAO,QAAQ,QAAQ;CACzB;AACF"}
@@ -0,0 +1,43 @@
1
+ /** 侧栏的形式 */
2
+ export type LayoutMode = 'docked' | 'overlay';
3
+ /** 抽屉式侧栏从哪一边滑出:start / end 随排版方向(从右到左时互换),top / bottom 是上下 */
4
+ export type LayoutSide = 'start' | 'end' | 'top' | 'bottom';
5
+ /** 可选的侧栏形式,LayoutSwitcher 据此列出选项 */
6
+ export declare const LAYOUT_MODES: readonly LayoutMode[];
7
+ /** 可选的抽屉方向,LayoutSwitcher 据此列出选项 */
8
+ export declare const LAYOUT_SIDES: readonly LayoutSide[];
9
+ /** 默认的抽屉宽度(px):左右两侧 */
10
+ export declare const DEFAULT_LAYOUT_WIDTH = 256;
11
+ /** 默认的抽屉高度(px):上下两侧 */
12
+ export declare const DEFAULT_LAYOUT_HEIGHT = 320;
13
+ /** createLayoutPreference 记住的内容 */
14
+ export interface LayoutState {
15
+ /** 侧栏的形式,默认 docked */
16
+ mode: LayoutMode;
17
+ /** 抽屉从哪一边滑出(只在 overlay 时有效),默认 start */
18
+ side: LayoutSide;
19
+ /** 抽屉开着 */
20
+ open: boolean;
21
+ /** 左右两侧抽屉的宽度(px) */
22
+ width: number;
23
+ /** 上下两侧抽屉的高度(px) */
24
+ height: number;
25
+ /** docked 侧栏收起成了图标栏 */
26
+ collapsed: boolean;
27
+ }
28
+ /** createLayoutPreference 的选项 */
29
+ export interface LayoutPreferenceOptions {
30
+ /** 没记过(或记的值不合法)时各项的值 */
31
+ defaults?: Partial<LayoutState>;
32
+ /** 记住选择的 localStorage 键,默认 'vue-tsx-pro-layout';false 不记 */
33
+ storageKey?: string | false;
34
+ }
35
+ /** 布局偏好:各项可读可写,写了就存盘、其他标签页跟着变 */
36
+ export interface LayoutPreference extends LayoutState {
37
+ /** 全部恢复成默认值(并清掉记住的内容) */
38
+ reset(): void;
39
+ }
40
+ /** 记住选择的默认 localStorage 键 */
41
+ export declare const DEFAULT_LAYOUT_STORAGE_KEY = "vue-tsx-pro-layout";
42
+ /** 创建布局偏好;在应用的生命周期里一直有效(监听其他标签页的改动不撤销) */
43
+ export declare function createLayoutPreference(options?: LayoutPreferenceOptions): LayoutPreference;