@class-kit/vue 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (275) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +20 -2
  3. package/README.md +5 -1
  4. package/dist/components/affix.cjs.map +1 -1
  5. package/dist/components/affix.js.map +1 -1
  6. package/dist/components/backtop.cjs.map +1 -1
  7. package/dist/components/backtop.js.map +1 -1
  8. package/dist/components/badge.cjs.map +1 -1
  9. package/dist/components/badge.js.map +1 -1
  10. package/dist/components/barcode.cjs.map +1 -1
  11. package/dist/components/barcode.js.map +1 -1
  12. package/dist/components/breadcrumb.cjs.map +1 -1
  13. package/dist/components/breadcrumb.js.map +1 -1
  14. package/dist/components/button.cjs.map +1 -1
  15. package/dist/components/button.js.map +1 -1
  16. package/dist/components/calendar.cjs.map +1 -1
  17. package/dist/components/calendar.js.map +1 -1
  18. package/dist/components/canvas-editor.cjs.map +1 -1
  19. package/dist/components/canvas-editor.js.map +1 -1
  20. package/dist/components/canvas-image.cjs.map +1 -1
  21. package/dist/components/canvas-image.js.map +1 -1
  22. package/dist/components/chat-textarea.cjs +234 -0
  23. package/dist/components/chat-textarea.cjs.map +1 -0
  24. package/dist/components/chat-textarea.d.ts +2 -0
  25. package/dist/components/chat-textarea.d.ts.map +1 -0
  26. package/dist/components/chat-textarea.js +232 -0
  27. package/dist/components/chat-textarea.js.map +1 -0
  28. package/dist/components/chat-virtual-list.cjs +140 -13
  29. package/dist/components/chat-virtual-list.cjs.map +1 -1
  30. package/dist/components/chat-virtual-list.js +140 -13
  31. package/dist/components/chat-virtual-list.js.map +1 -1
  32. package/dist/components/checkbox.cjs.map +1 -1
  33. package/dist/components/checkbox.js.map +1 -1
  34. package/dist/components/checked.cjs.map +1 -1
  35. package/dist/components/checked.js.map +1 -1
  36. package/dist/components/code-preview.cjs +343 -0
  37. package/dist/components/code-preview.cjs.map +1 -0
  38. package/dist/components/code-preview.d.ts +2 -0
  39. package/dist/components/code-preview.d.ts.map +1 -0
  40. package/dist/components/code-preview.js +341 -0
  41. package/dist/components/code-preview.js.map +1 -0
  42. package/dist/components/color-picker.cjs +1 -1
  43. package/dist/components/color-picker.cjs.map +1 -1
  44. package/dist/components/color-picker.js +1 -1
  45. package/dist/components/color-picker.js.map +1 -1
  46. package/dist/components/comic-reader.cjs.map +1 -1
  47. package/dist/components/comic-reader.js.map +1 -1
  48. package/dist/components/config-provider.cjs.map +1 -1
  49. package/dist/components/config-provider.js.map +1 -1
  50. package/dist/components/config-table.cjs.map +1 -1
  51. package/dist/components/config-table.js.map +1 -1
  52. package/dist/components/countdown.cjs.map +1 -1
  53. package/dist/components/countdown.js.map +1 -1
  54. package/dist/components/danmaku.cjs.map +1 -1
  55. package/dist/components/danmaku.js.map +1 -1
  56. package/dist/components/date-picker.cjs.map +1 -1
  57. package/dist/components/date-picker.js.map +1 -1
  58. package/dist/components/date-range-picker.cjs.map +1 -1
  59. package/dist/components/date-range-picker.js.map +1 -1
  60. package/dist/components/design-effect.cjs.map +1 -1
  61. package/dist/components/design-effect.js.map +1 -1
  62. package/dist/components/drag-drop-board.cjs +24 -0
  63. package/dist/components/drag-drop-board.cjs.map +1 -1
  64. package/dist/components/drag-drop-board.js +24 -0
  65. package/dist/components/drag-drop-board.js.map +1 -1
  66. package/dist/components/draggable.cjs.map +1 -1
  67. package/dist/components/draggable.js.map +1 -1
  68. package/dist/components/ellipsis-text.cjs.map +1 -1
  69. package/dist/components/ellipsis-text.js.map +1 -1
  70. package/dist/components/empty.cjs.map +1 -1
  71. package/dist/components/empty.js.map +1 -1
  72. package/dist/components/field.cjs.map +1 -1
  73. package/dist/components/field.js.map +1 -1
  74. package/dist/components/file-preview.cjs.map +1 -1
  75. package/dist/components/file-preview.js.map +1 -1
  76. package/dist/components/floating-ball.cjs.map +1 -1
  77. package/dist/components/floating-ball.js.map +1 -1
  78. package/dist/components/form.cjs.map +1 -1
  79. package/dist/components/form.js.map +1 -1
  80. package/dist/components/gradient-text.cjs.map +1 -1
  81. package/dist/components/gradient-text.js.map +1 -1
  82. package/dist/components/height-transition.cjs +118 -0
  83. package/dist/components/height-transition.cjs.map +1 -0
  84. package/dist/components/height-transition.d.ts +2 -0
  85. package/dist/components/height-transition.d.ts.map +1 -0
  86. package/dist/components/height-transition.js +116 -0
  87. package/dist/components/height-transition.js.map +1 -0
  88. package/dist/components/input.cjs.map +1 -1
  89. package/dist/components/input.js.map +1 -1
  90. package/dist/components/lazy-image.cjs.map +1 -1
  91. package/dist/components/lazy-image.js.map +1 -1
  92. package/dist/components/live-room.cjs.map +1 -1
  93. package/dist/components/live-room.js.map +1 -1
  94. package/dist/components/loading.cjs.map +1 -1
  95. package/dist/components/loading.js.map +1 -1
  96. package/dist/components/marquee.cjs.map +1 -1
  97. package/dist/components/marquee.js.map +1 -1
  98. package/dist/components/masonry-virtual-list.cjs.map +1 -1
  99. package/dist/components/masonry-virtual-list.js.map +1 -1
  100. package/dist/components/menu.cjs +259 -0
  101. package/dist/components/menu.cjs.map +1 -0
  102. package/dist/components/menu.d.ts +2 -0
  103. package/dist/components/menu.d.ts.map +1 -0
  104. package/dist/components/menu.js +257 -0
  105. package/dist/components/menu.js.map +1 -0
  106. package/dist/components/modal.cjs.map +1 -1
  107. package/dist/components/modal.js.map +1 -1
  108. package/dist/components/multi-column-picker.cjs.map +1 -1
  109. package/dist/components/multi-column-picker.js.map +1 -1
  110. package/dist/components/novel-reader.cjs.map +1 -1
  111. package/dist/components/novel-reader.js.map +1 -1
  112. package/dist/components/number-input.cjs.map +1 -1
  113. package/dist/components/number-input.js.map +1 -1
  114. package/dist/components/orbital-sphere.cjs +128 -0
  115. package/dist/components/orbital-sphere.cjs.map +1 -0
  116. package/dist/components/orbital-sphere.d.ts +2 -0
  117. package/dist/components/orbital-sphere.d.ts.map +1 -0
  118. package/dist/components/orbital-sphere.js +126 -0
  119. package/dist/components/orbital-sphere.js.map +1 -0
  120. package/dist/components/pagination.cjs.map +1 -1
  121. package/dist/components/pagination.js.map +1 -1
  122. package/dist/components/password-input.cjs.map +1 -1
  123. package/dist/components/password-input.js.map +1 -1
  124. package/dist/components/popconfirm.cjs +64 -23
  125. package/dist/components/popconfirm.cjs.map +1 -1
  126. package/dist/components/popconfirm.js +65 -24
  127. package/dist/components/popconfirm.js.map +1 -1
  128. package/dist/components/popup.cjs +1 -3
  129. package/dist/components/popup.cjs.map +1 -1
  130. package/dist/components/popup.js +1 -3
  131. package/dist/components/popup.js.map +1 -1
  132. package/dist/components/progress-bar.cjs.map +1 -1
  133. package/dist/components/progress-bar.js.map +1 -1
  134. package/dist/components/qr-code.cjs.map +1 -1
  135. package/dist/components/qr-code.js.map +1 -1
  136. package/dist/components/radio-group.cjs.map +1 -1
  137. package/dist/components/radio-group.js.map +1 -1
  138. package/dist/components/rating.cjs.map +1 -1
  139. package/dist/components/rating.js.map +1 -1
  140. package/dist/components/rolling-number.cjs.map +1 -1
  141. package/dist/components/rolling-number.js.map +1 -1
  142. package/dist/components/select.cjs.map +1 -1
  143. package/dist/components/select.js.map +1 -1
  144. package/dist/components/signature.cjs +1 -1
  145. package/dist/components/signature.cjs.map +1 -1
  146. package/dist/components/signature.js +1 -1
  147. package/dist/components/signature.js.map +1 -1
  148. package/dist/components/skeleton.cjs.map +1 -1
  149. package/dist/components/skeleton.js.map +1 -1
  150. package/dist/components/slide-captcha.cjs.map +1 -1
  151. package/dist/components/slide-captcha.js.map +1 -1
  152. package/dist/components/swiper.cjs.map +1 -1
  153. package/dist/components/swiper.js.map +1 -1
  154. package/dist/components/switch.cjs.map +1 -1
  155. package/dist/components/switch.js.map +1 -1
  156. package/dist/components/table.cjs.map +1 -1
  157. package/dist/components/table.js.map +1 -1
  158. package/dist/components/tabs.cjs.map +1 -1
  159. package/dist/components/tabs.js.map +1 -1
  160. package/dist/components/tag.cjs.map +1 -1
  161. package/dist/components/tag.js.map +1 -1
  162. package/dist/components/textarea.cjs.map +1 -1
  163. package/dist/components/textarea.js.map +1 -1
  164. package/dist/components/tilt-card.cjs.map +1 -1
  165. package/dist/components/tilt-card.js.map +1 -1
  166. package/dist/components/timeline.cjs.map +1 -1
  167. package/dist/components/timeline.js.map +1 -1
  168. package/dist/components/toast.cjs +161 -22
  169. package/dist/components/toast.cjs.map +1 -1
  170. package/dist/components/toast.d.ts +1 -1
  171. package/dist/components/toast.d.ts.map +1 -1
  172. package/dist/components/toast.js +159 -23
  173. package/dist/components/toast.js.map +1 -1
  174. package/dist/components/tooltip.cjs +56 -17
  175. package/dist/components/tooltip.cjs.map +1 -1
  176. package/dist/components/tooltip.js +57 -18
  177. package/dist/components/tooltip.js.map +1 -1
  178. package/dist/components/typewriter-text.cjs.map +1 -1
  179. package/dist/components/typewriter-text.js.map +1 -1
  180. package/dist/components/upload.cjs.map +1 -1
  181. package/dist/components/upload.js.map +1 -1
  182. package/dist/components/verification-code.cjs.map +1 -1
  183. package/dist/components/verification-code.js.map +1 -1
  184. package/dist/components/video-detail-transition.cjs.map +1 -1
  185. package/dist/components/video-detail-transition.js.map +1 -1
  186. package/dist/components/video-player.cjs.map +1 -1
  187. package/dist/components/video-player.js.map +1 -1
  188. package/dist/components/virtual-list.cjs.map +1 -1
  189. package/dist/components/virtual-list.js.map +1 -1
  190. package/dist/components/virtual-select.cjs.map +1 -1
  191. package/dist/components/virtual-select.js.map +1 -1
  192. package/dist/components/virtual-table.cjs.map +1 -1
  193. package/dist/components/virtual-table.js.map +1 -1
  194. package/dist/{import-transform-DLby8nRN.js → import-transform-BFq5_6VQ.js} +7 -1
  195. package/dist/import-transform-BFq5_6VQ.js.map +1 -0
  196. package/dist/{import-transform-BiXH181o.js → import-transform-CvGKNZyR.js} +7 -1
  197. package/dist/import-transform-CvGKNZyR.js.map +1 -0
  198. package/dist/import-transform.d.ts.map +1 -1
  199. package/dist/index.cjs +1003 -80
  200. package/dist/index.cjs.map +1 -1
  201. package/dist/index.d.ts +514 -8
  202. package/dist/index.d.ts.map +1 -1
  203. package/dist/index.js +985 -83
  204. package/dist/index.js.map +1 -1
  205. package/dist/styles/base.css +168 -41
  206. package/dist/styles/components/barcode.css +206 -0
  207. package/dist/styles/components/button.css +7 -2
  208. package/dist/styles/components/calendar.css +0 -23
  209. package/dist/styles/components/canvas-editor.css +18 -21
  210. package/dist/styles/components/canvas-image.css +0 -23
  211. package/dist/styles/components/chat-textarea.css +124 -0
  212. package/dist/styles/components/chat-virtual-list.css +15 -26
  213. package/dist/styles/components/checkbox.css +39 -23
  214. package/dist/styles/components/checked.css +39 -23
  215. package/dist/styles/components/code-preview.css +208 -0
  216. package/dist/styles/components/color-picker.css +46 -27
  217. package/dist/styles/components/config-table.css +0 -23
  218. package/dist/styles/components/date-picker.css +39 -23
  219. package/dist/styles/components/date-range-picker.css +39 -23
  220. package/dist/styles/components/design-effect.css +5 -1
  221. package/dist/styles/components/drag-drop-board.css +6 -1
  222. package/dist/styles/components/field.css +39 -23
  223. package/dist/styles/components/form.css +39 -23
  224. package/dist/styles/components/gradient-text.css +4 -0
  225. package/dist/styles/components/height-transition.css +50 -0
  226. package/dist/styles/components/input.css +39 -23
  227. package/dist/styles/components/loading.css +47 -0
  228. package/dist/styles/components/menu.css +286 -0
  229. package/dist/styles/components/modal.css +2 -23
  230. package/dist/styles/components/number-input.css +39 -23
  231. package/dist/styles/components/orbital-sphere.css +224 -0
  232. package/dist/styles/components/password-input.css +39 -23
  233. package/dist/styles/components/popconfirm.css +5 -0
  234. package/dist/styles/components/popup.css +2 -23
  235. package/dist/styles/components/qr-code.css +206 -0
  236. package/dist/styles/components/radio-group.css +39 -23
  237. package/dist/styles/components/rating.css +39 -23
  238. package/dist/styles/components/select.css +39 -23
  239. package/dist/styles/components/signature.css +39 -23
  240. package/dist/styles/components/switch.css +39 -23
  241. package/dist/styles/components/table.css +0 -23
  242. package/dist/styles/components/tabs.css +10 -0
  243. package/dist/styles/components/textarea.css +39 -23
  244. package/dist/styles/components/tilt-card.css +2 -23
  245. package/dist/styles/components/toast.css +109 -48
  246. package/dist/styles/components/tooltip.css +8 -23
  247. package/dist/styles/components/typewriter-text.css +4 -0
  248. package/dist/styles/components/upload.css +39 -23
  249. package/dist/styles/components/verification-code.css +39 -23
  250. package/dist/styles/components/virtual-select.css +39 -23
  251. package/dist/styles/components/virtual-table.css +0 -23
  252. package/dist/styles/components.css +1250 -165
  253. package/dist/styles/themes/business-blue.css +375 -0
  254. package/dist/styles/themes/cartoon-3d.css +695 -0
  255. package/dist/styles/themes/creative-purple.css +376 -0
  256. package/dist/styles/themes/dark-tech.css +495 -0
  257. package/dist/styles/themes/liquid-glass.css +526 -21
  258. package/dist/styles/themes/minimal.css +406 -14
  259. package/dist/styles/themes/soft-pink.css +376 -0
  260. package/dist/styles.css +1250 -165
  261. package/dist/vite.cjs +1 -1
  262. package/dist/vite.cjs.map +1 -1
  263. package/dist/vite.d.ts +1 -1
  264. package/dist/vite.js +1 -1
  265. package/dist/vite.js.map +1 -1
  266. package/dist/webpack-loader.cjs +1 -1
  267. package/dist/webpack-loader.js +1 -1
  268. package/package.json +4 -4
  269. package/dist/import-transform-BiXH181o.js.map +0 -1
  270. package/dist/import-transform-DLby8nRN.js.map +0 -1
  271. package/dist/styles/themes/amber.css +0 -19
  272. package/dist/styles/themes/emerald.css +0 -19
  273. package/dist/styles/themes/rose.css +0 -19
  274. package/dist/styles/themes/sky.css +0 -19
  275. package/dist/styles/themes/violet.css +0 -19
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { defineComponent, ref, watch, h, inject, shallowRef, onBeforeUnmount, onMounted, provide, computed, Teleport, nextTick } from 'vue';
2
- import { configureClassComponents, ToastManager, FormController, getClassComponentsLocale, PasswordInputController, ColorPickerController, DatePickerController, DateRangePickerController, VerificationCodeController, SlideCaptchaController, VirtualSelectController, VirtualListController, RollingNumberController, CountdownController, CalendarController, TypewriterTextController, DesignEffectController, GradientTextController, LazyImageController, TiltCardController, VideoPlayerController, VideoDetailTransitionController, FilePreviewController, CanvasEditorController, ProgressController, SignatureController, TimelineController, DragController, DropController, GestureController, FloatingBallController, MultiColumnPickerController, SwiperController, MasonryVirtualListController, ChatVirtualListController, BadgeController, TagController, SkeletonController, BreadcrumbController, PaginationController, BacktopController, ModalController, PopupController, TooltipController, TabsController, TableController, UploadController, NovelReaderController, ComicReaderController, DanmakuController, LiveRoomController, AffixController, CanvasImageController, MarqueeController, getSafeTooltipPlacement } from '@class-kit/core';
3
- export { AffixController, BacktopController, BadgeController, BreadcrumbController, CalendarController, CanvasEditorController, CanvasImageController, ChatVirtualListController, ColorPickerController, ComicReaderController, CountdownController, DanmakuController, DatePickerController, DateRangePickerController, DesignEffectController, DragController, DropController, FilePreviewController, FloatingBallController, FormController, GestureController, GradientTextController, LazyImageController, LiveRoomController, MasonryVirtualListController, ModalController, MultiColumnPickerController, NovelReaderController, PaginationController, PasswordInputController, PopupController, ProgressController, SignatureController, SkeletonController, SlideCaptchaController, SwiperController, TableController, TabsController, TagController, TiltCardController, TimelineController, ToastManager, TooltipController, TypewriterTextController, UploadController, VerificationCodeController, VideoDetailTransitionController, VideoPlayerController, VirtualListController, VirtualSelectController, configureClassComponents, getClassComponentsConfig, getClassComponentsLocale, resetClassComponentsConfig } from '@class-kit/core';
2
+ import { configureClassComponents, ToastManager, FormController, getClassComponentsLocale, PasswordInputController, ColorPickerController, DatePickerController, DateRangePickerController, ChatTextareaController, VerificationCodeController, SlideCaptchaController, VirtualSelectController, VirtualListController, RollingNumberController, CountdownController, CalendarController, TypewriterTextController, DesignEffectController, GradientTextController, LazyImageController, TiltCardController, OrbitalSphereController, HeightTransitionController, CodePreviewController, VideoPlayerController, VideoDetailTransitionController, FilePreviewController, CanvasEditorController, ProgressController, SignatureController, TimelineController, DragController, DropController, GestureController, FloatingBallController, MultiColumnPickerController, SwiperController, MasonryVirtualListController, ChatVirtualListController, BadgeController, TagController, SkeletonController, BreadcrumbController, MenuController, PaginationController, BacktopController, ModalController, PopupController, TooltipController, TabsController, TableController, UploadController, NovelReaderController, ComicReaderController, DanmakuController, LiveRoomController, AffixController, CanvasImageController, MarqueeController, getSafeTooltipPlacement } from '@class-kit/core';
3
+ export { AffixController, BacktopController, BadgeController, BreadcrumbController, CalendarController, CanvasEditorController, CanvasImageController, ChatVirtualListController, CodePreviewController, ColorPickerController, ComicReaderController, CountdownController, DanmakuController, DatePickerController, DateRangePickerController, DesignEffectController, DragController, DropController, FilePreviewController, FloatingBallController, FormController, GestureController, GradientTextController, HeightTransitionController, LazyImageController, LiveRoomController, MasonryVirtualListController, MenuController, ModalController, MultiColumnPickerController, NovelReaderController, OrbitalSphereController, PaginationController, PasswordInputController, PopupController, ProgressController, SignatureController, SkeletonController, SlideCaptchaController, SwiperController, TableController, TabsController, TagController, TiltCardController, TimelineController, ToastManager, TooltipController, TypewriterTextController, UploadController, VerificationCodeController, VideoDetailTransitionController, VideoPlayerController, VirtualListController, VirtualSelectController, configureClassComponents, getClassComponentsConfig, getClassComponentsLocale, resetClassComponentsConfig } from '@class-kit/core';
4
4
 
5
5
  const formSymbol = /*#__PURE__*/ Symbol("ClassComponentsForm");
6
6
  const formInteractivitySymbol = /*#__PURE__*/ Symbol("ClassComponentsFormInteractivity");
@@ -106,6 +106,14 @@ function animationStyle(animation) {
106
106
  "--cc-animation-easing": animation.easing,
107
107
  };
108
108
  }
109
+ function normalizeToastMaxVisible(maxVisible) {
110
+ if (typeof maxVisible !== "number" || !Number.isFinite(maxVisible))
111
+ return 3;
112
+ return Math.max(1, Math.min(6, Math.floor(maxVisible)));
113
+ }
114
+ function isToastTopPosition(position) {
115
+ return (position === "top" || position === "top-left" || position === "top-right");
116
+ }
109
117
  const focusableSelector = [
110
118
  "a[href]",
111
119
  "button:not([disabled])",
@@ -726,7 +734,7 @@ const ClassColorPicker = /*#__PURE__*/ defineComponent({
726
734
  });
727
735
  return () => {
728
736
  const interactivity = resolveFieldInteractivity(formInteractivity, props.disabled, props.readOnly ?? props.readonly);
729
- const controller = new ColorPickerController(String(field.value.value || "#7c3aed"));
737
+ const controller = new ColorPickerController(String(field.value.value || "#1d2129"));
730
738
  const state = controller.getState();
731
739
  const commit = (value) => {
732
740
  if (interactivity.disabled || interactivity.readOnly)
@@ -1465,6 +1473,152 @@ const ClassTextarea = /*#__PURE__*/ defineComponent({
1465
1473
  };
1466
1474
  },
1467
1475
  });
1476
+ function getVueTextareaMetrics(element) {
1477
+ const computed = window.getComputedStyle(element);
1478
+ const fontSize = Number.parseFloat(computed.fontSize) || 14;
1479
+ const lineHeight = Number.parseFloat(computed.lineHeight) || fontSize * 1.5;
1480
+ const paddingY = (Number.parseFloat(computed.paddingTop) || 0) +
1481
+ (Number.parseFloat(computed.paddingBottom) || 0);
1482
+ const borderY = (Number.parseFloat(computed.borderTopWidth) || 0) +
1483
+ (Number.parseFloat(computed.borderBottomWidth) || 0);
1484
+ return { borderY, lineHeight, paddingY };
1485
+ }
1486
+ const ClassChatTextarea = /*#__PURE__*/ defineComponent({
1487
+ name: "ClassChatTextarea",
1488
+ inheritAttrs: false,
1489
+ props: {
1490
+ className: { type: String, default: "cc-chat-textarea" },
1491
+ clearable: { type: Boolean, default: true },
1492
+ clearIcon: {
1493
+ type: null,
1494
+ default: () => classIcon("x"),
1495
+ },
1496
+ clearLabel: {
1497
+ type: String,
1498
+ default: () => getClassComponentsLocale().inputClearLabel,
1499
+ },
1500
+ defaultValue: { type: String, default: "" },
1501
+ disabled: optionalBooleanProp(),
1502
+ maxRows: { type: Number, default: 3 },
1503
+ minRows: { type: Number, default: 1 },
1504
+ modelValue: String,
1505
+ placeholder: String,
1506
+ readOnly: optionalBooleanProp(),
1507
+ readonly: optionalBooleanProp(),
1508
+ textareaClass: { type: String, default: "cc-chat-textarea__control" },
1509
+ textareaStyle: Object,
1510
+ value: String,
1511
+ },
1512
+ emits: ["change", "input", "update:modelValue", "update:value"],
1513
+ setup(props, { attrs, emit, expose }) {
1514
+ const textareaRef = ref(null);
1515
+ const controller = new ChatTextareaController({
1516
+ maxRows: props.maxRows,
1517
+ minRows: props.minRows,
1518
+ value: props.modelValue ?? props.value ?? props.defaultValue,
1519
+ });
1520
+ const state = ref(controller.getState());
1521
+ const controlled = computed(() => props.modelValue !== undefined || props.value !== undefined);
1522
+ let resizeObserver;
1523
+ const resize = () => {
1524
+ const element = textareaRef.value;
1525
+ if (!element || typeof window === "undefined")
1526
+ return;
1527
+ const { borderY, lineHeight, paddingY } = getVueTextareaMetrics(element);
1528
+ const minHeight = lineHeight * state.value.minRows + paddingY + borderY;
1529
+ const maxHeight = lineHeight * state.value.maxRows + paddingY + borderY;
1530
+ element.style.height = "auto";
1531
+ const nextHeight = Math.min(Math.max(element.scrollHeight, minHeight), maxHeight);
1532
+ element.style.height = `${nextHeight}px`;
1533
+ element.style.overflowY =
1534
+ element.scrollHeight > maxHeight + 1 ? "auto" : "hidden";
1535
+ };
1536
+ const syncState = () => {
1537
+ state.value = controller.update({
1538
+ maxRows: props.maxRows,
1539
+ minRows: props.minRows,
1540
+ value: controlled.value
1541
+ ? (props.modelValue ?? props.value ?? "")
1542
+ : state.value.value,
1543
+ });
1544
+ nextTick(resize);
1545
+ };
1546
+ watch(() => [props.maxRows, props.minRows, props.modelValue, props.value], syncState);
1547
+ onMounted(() => {
1548
+ resize();
1549
+ if (typeof ResizeObserver === "undefined" || !textareaRef.value)
1550
+ return;
1551
+ resizeObserver = new ResizeObserver(resize);
1552
+ resizeObserver.observe(textareaRef.value);
1553
+ });
1554
+ onBeforeUnmount(() => {
1555
+ resizeObserver?.disconnect();
1556
+ });
1557
+ const commit = (nextValue, event) => {
1558
+ const nextState = controller.setValue(nextValue);
1559
+ if (!controlled.value)
1560
+ state.value = nextState;
1561
+ emit("update:modelValue", nextValue);
1562
+ emit("update:value", nextValue);
1563
+ emit("input", nextValue, event);
1564
+ emit("change", nextValue, event);
1565
+ nextTick(resize);
1566
+ };
1567
+ expose({
1568
+ blur: () => textareaRef.value?.blur(),
1569
+ focus: () => textareaRef.value?.focus(),
1570
+ getElement: () => textareaRef.value,
1571
+ });
1572
+ return () => {
1573
+ const locked = props.disabled || props.readOnly || props.readonly;
1574
+ const currentValue = controlled.value
1575
+ ? (props.modelValue ?? props.value ?? "")
1576
+ : state.value.value;
1577
+ const canClear = props.clearable && currentValue !== "" && !locked;
1578
+ return h("div", {
1579
+ class: props.className,
1580
+ "data-disabled": Boolean(props.disabled),
1581
+ "data-readonly": Boolean(props.readOnly || props.readonly),
1582
+ "data-scrollable": currentValue.length > 0,
1583
+ }, [
1584
+ h("textarea", {
1585
+ ...attrs,
1586
+ class: [
1587
+ props.textareaClass,
1588
+ canClear ? "cc-chat-textarea__control--clearable" : "",
1589
+ ],
1590
+ disabled: props.disabled,
1591
+ placeholder: props.placeholder,
1592
+ readonly: props.readOnly || props.readonly,
1593
+ ref: textareaRef,
1594
+ rows: state.value.minRows,
1595
+ style: {
1596
+ "--cc-chat-textarea-max-rows": state.value.maxRows,
1597
+ "--cc-chat-textarea-min-rows": state.value.minRows,
1598
+ ...(props.textareaStyle ?? {}),
1599
+ },
1600
+ value: currentValue,
1601
+ onInput: (event) => {
1602
+ if (locked)
1603
+ return;
1604
+ commit(event.currentTarget.value, event);
1605
+ },
1606
+ }),
1607
+ canClear
1608
+ ? h("button", {
1609
+ "aria-label": props.clearLabel,
1610
+ class: "cc-chat-textarea__clear",
1611
+ type: "button",
1612
+ onClick: (event) => {
1613
+ commit("", event);
1614
+ textareaRef.value?.focus();
1615
+ },
1616
+ }, props.clearIcon)
1617
+ : null,
1618
+ ]);
1619
+ };
1620
+ },
1621
+ });
1468
1622
  const ClassVerificationCode = /*#__PURE__*/ defineComponent({
1469
1623
  name: "ClassVerificationCode",
1470
1624
  inheritAttrs: false,
@@ -3772,6 +3926,367 @@ const ClassTiltCard = /*#__PURE__*/ defineComponent({
3772
3926
  ]);
3773
3927
  },
3774
3928
  });
3929
+ const ClassOrbitalSphere = /*#__PURE__*/ defineComponent({
3930
+ name: "ClassOrbitalSphere",
3931
+ inheritAttrs: false,
3932
+ props: {
3933
+ animated: { type: Boolean, default: true },
3934
+ className: { type: String, default: "cc-orbital-sphere" },
3935
+ cycleDuration: { type: Number, default: 12000 },
3936
+ depth: { type: Number, default: 0.72 },
3937
+ disabled: { type: Boolean, default: false },
3938
+ duration: { type: Number, default: 9000 },
3939
+ itemClass: { type: String, default: "cc-orbital-sphere__item" },
3940
+ itemContentClass: {
3941
+ type: String,
3942
+ default: "cc-orbital-sphere__item-content",
3943
+ },
3944
+ itemSize: { type: Number, default: 72 },
3945
+ items: {
3946
+ type: Array,
3947
+ default: undefined,
3948
+ },
3949
+ radius: { type: [Number, String], default: "50%" },
3950
+ shellClass: { type: String, default: "cc-orbital-sphere__shell" },
3951
+ size: { type: [Number, String], default: "360px" },
3952
+ spread: { type: Number, default: 0.86 },
3953
+ stageClass: { type: String, default: "cc-orbital-sphere__stage" },
3954
+ visibleCount: { type: Number, default: 10 },
3955
+ },
3956
+ emits: ["item-click"],
3957
+ setup(props, { attrs, emit, slots }) {
3958
+ return () => {
3959
+ const state = new OrbitalSphereController({
3960
+ animated: props.animated,
3961
+ cycleDuration: props.cycleDuration,
3962
+ depth: props.depth,
3963
+ disabled: props.disabled,
3964
+ duration: props.duration,
3965
+ itemSize: props.itemSize,
3966
+ items: props.items,
3967
+ radius: props.radius,
3968
+ size: props.size,
3969
+ spread: props.spread,
3970
+ visibleCount: props.visibleCount,
3971
+ }).getState();
3972
+ return h("div", {
3973
+ ...attrs,
3974
+ class: [props.className, attrs.class],
3975
+ "data-animated": state.animated ? "true" : "false",
3976
+ "data-disabled": state.disabled ? "true" : "false",
3977
+ "data-overflow": state.items.length > state.visibleCount ? "true" : "false",
3978
+ style: [state.styleVars, attrs.style],
3979
+ }, [
3980
+ h("span", { "aria-hidden": "true", class: props.shellClass }),
3981
+ h("div", { class: props.stageClass }, state.items.map((item) => h("button", {
3982
+ "aria-label": item.label,
3983
+ class: props.itemClass,
3984
+ "data-tone": item.tone,
3985
+ disabled: state.disabled,
3986
+ key: item.id,
3987
+ onClick: (event) => emit("item-click", item, event),
3988
+ style: [
3989
+ {
3990
+ "--cc-orbital-index": item.index,
3991
+ },
3992
+ item.styleVars,
3993
+ ],
3994
+ type: "button",
3995
+ }, [
3996
+ h("span", { class: props.itemContentClass }, slots.item?.({ index: item.index, item }) ?? item.content),
3997
+ ]))),
3998
+ ]);
3999
+ };
4000
+ },
4001
+ });
4002
+ const ClassHeightTransition = /*#__PURE__*/ defineComponent({
4003
+ name: "ClassHeightTransition",
4004
+ inheritAttrs: false,
4005
+ props: {
4006
+ className: { type: String, default: "cc-height-transition" },
4007
+ contentClass: { type: String, default: "cc-height-transition__content" },
4008
+ duration: { type: Number, default: 220 },
4009
+ easing: { type: String, default: "cubic-bezier(0.22, 0.8, 0.28, 1)" },
4010
+ expanded: { type: Boolean, default: false },
4011
+ mode: {
4012
+ type: String,
4013
+ default: "auto",
4014
+ },
4015
+ },
4016
+ setup(props, { attrs, slots }) {
4017
+ const contentRef = ref(null);
4018
+ const height = ref(0);
4019
+ const controller = new HeightTransitionController({
4020
+ duration: props.duration,
4021
+ easing: props.easing,
4022
+ expanded: props.expanded,
4023
+ mode: props.mode,
4024
+ });
4025
+ const state = ref(controller.getState());
4026
+ let observer;
4027
+ const measure = () => {
4028
+ height.value = contentRef.value?.scrollHeight ?? 0;
4029
+ };
4030
+ watch(() => [props.duration, props.easing, props.expanded, props.mode], () => {
4031
+ state.value = controller.update({
4032
+ duration: props.duration,
4033
+ easing: props.easing,
4034
+ expanded: props.expanded,
4035
+ mode: props.mode,
4036
+ });
4037
+ nextTick(measure);
4038
+ }, { immediate: true });
4039
+ onMounted(() => {
4040
+ measure();
4041
+ if (typeof ResizeObserver !== "undefined" && contentRef.value) {
4042
+ observer = new ResizeObserver(measure);
4043
+ observer.observe(contentRef.value);
4044
+ }
4045
+ });
4046
+ onBeforeUnmount(() => observer?.disconnect());
4047
+ return () => h("div", {
4048
+ ...attrs,
4049
+ class: props.className,
4050
+ "data-expanded": state.value.expanded,
4051
+ "data-mode": state.value.mode,
4052
+ style: [
4053
+ attrs.style,
4054
+ {
4055
+ "--cc-height-transition-duration": `${state.value.duration}ms`,
4056
+ "--cc-height-transition-easing": state.value.easing,
4057
+ "--cc-height-transition-height": `${height.value}px`,
4058
+ },
4059
+ ],
4060
+ }, [
4061
+ h("div", { ref: contentRef, class: props.contentClass }, slots.default?.()),
4062
+ ]);
4063
+ },
4064
+ });
4065
+ const ClassCodePreview = /*#__PURE__*/ defineComponent({
4066
+ name: "ClassCodePreview",
4067
+ inheritAttrs: false,
4068
+ props: {
4069
+ className: { type: String, default: "cc-code-preview" },
4070
+ code: { type: String, required: true },
4071
+ defaultExpanded: { type: Boolean, default: false },
4072
+ language: { type: String, default: "tsx" },
4073
+ placement: {
4074
+ type: String,
4075
+ default: "auto",
4076
+ },
4077
+ strategy: {
4078
+ type: String,
4079
+ default: "fixed",
4080
+ },
4081
+ title: { type: String, default: "示例源码" },
4082
+ transitionDuration: { type: Number, default: 220 },
4083
+ transitionEasing: {
4084
+ type: String,
4085
+ default: "cubic-bezier(0.22, 0.8, 0.28, 1)",
4086
+ },
4087
+ },
4088
+ emits: ["copy"],
4089
+ setup(props, { attrs, emit, slots }) {
4090
+ const rootRef = ref(null);
4091
+ const panelRef = ref(null);
4092
+ const panelStyle = ref({});
4093
+ const controller = new CodePreviewController({
4094
+ code: props.code,
4095
+ defaultExpanded: props.defaultExpanded,
4096
+ language: props.language,
4097
+ placement: props.placement,
4098
+ title: props.title,
4099
+ });
4100
+ const state = ref(controller.getState());
4101
+ let resetTimer;
4102
+ const sync = () => {
4103
+ state.value = controller.update({
4104
+ code: props.code,
4105
+ language: props.language,
4106
+ placement: props.placement,
4107
+ title: props.title,
4108
+ });
4109
+ };
4110
+ const resolvePlacement = (estimate = false) => {
4111
+ const rect = rootRef.value?.getBoundingClientRect();
4112
+ const panel = panelRef.value;
4113
+ if (!rect || (!panel && !estimate) || typeof window === "undefined")
4114
+ return;
4115
+ const padding = 10;
4116
+ const gap = 10;
4117
+ const viewportWidth = document.documentElement.clientWidth || window.innerWidth;
4118
+ const viewportHeight = document.documentElement.clientHeight || window.innerHeight;
4119
+ const maxPanelHeight = Math.max(160, viewportHeight - padding * 2);
4120
+ const maxPanelWidth = Math.max(160, viewportWidth - padding * 2);
4121
+ const minPanelHeight = Math.min(160, maxPanelHeight);
4122
+ const panelContent = panel?.querySelector("pre");
4123
+ const measuredPanelHeight = Math.max(panel?.offsetHeight ?? 0, panel?.scrollHeight ?? 0, panelContent?.scrollHeight ?? 0, estimate ? 420 : 0);
4124
+ const preferredPanelHeight = Math.min(Math.max(160, measuredPanelHeight || 420), maxPanelHeight);
4125
+ const panelWidth = Math.min(Math.max(rect.width, panel?.offsetWidth || 720), maxPanelWidth);
4126
+ const availableBelow = Math.max(minPanelHeight, viewportHeight - rect.bottom - gap - padding);
4127
+ const availableAbove = Math.max(minPanelHeight, rect.top - gap - padding);
4128
+ const placementHeight = Math.min(preferredPanelHeight, Math.max(availableBelow, availableAbove));
4129
+ const nextState = controller.resolvePlacement({
4130
+ anchorBottom: rect.bottom,
4131
+ anchorLeft: rect.left,
4132
+ anchorRight: rect.right,
4133
+ anchorTop: rect.top,
4134
+ panelHeight: placementHeight,
4135
+ panelWidth,
4136
+ viewportHeight,
4137
+ viewportWidth,
4138
+ });
4139
+ state.value = nextState;
4140
+ if (props.strategy !== "fixed") {
4141
+ panelStyle.value = {};
4142
+ return;
4143
+ }
4144
+ const clamp = (value, min, max) => Math.min(Math.max(min, value), max);
4145
+ const width = panelWidth;
4146
+ const maxLeft = Math.max(padding, viewportWidth - width - padding);
4147
+ const viewportPanelHeight = Math.min(preferredPanelHeight, maxPanelHeight);
4148
+ const maxTop = Math.max(padding, viewportHeight - viewportPanelHeight - padding);
4149
+ let left = clamp(rect.left, padding, maxLeft);
4150
+ let top = rect.bottom + gap;
4151
+ let maxHeight = Math.min(preferredPanelHeight, Math.max(minPanelHeight, viewportHeight - top - padding));
4152
+ let transformOrigin = "top left";
4153
+ if (nextState.resolvedPlacement === "top") {
4154
+ maxHeight = Math.min(preferredPanelHeight, availableAbove);
4155
+ top = Math.max(padding, rect.top - gap - maxHeight);
4156
+ transformOrigin = "bottom left";
4157
+ }
4158
+ else if (nextState.resolvedPlacement === "right") {
4159
+ left = clamp(rect.right + gap, padding, maxLeft);
4160
+ top = clamp(rect.top, padding, maxTop);
4161
+ maxHeight = viewportPanelHeight;
4162
+ transformOrigin = "top left";
4163
+ }
4164
+ else if (nextState.resolvedPlacement === "left") {
4165
+ left = clamp(rect.left - width - gap, padding, maxLeft);
4166
+ top = clamp(rect.top, padding, maxTop);
4167
+ maxHeight = viewportPanelHeight;
4168
+ transformOrigin = "top right";
4169
+ }
4170
+ panelStyle.value = {
4171
+ left: `${left}px`,
4172
+ maxHeight: `${maxHeight}px`,
4173
+ top: `${top}px`,
4174
+ transformOrigin,
4175
+ width: `${width}px`,
4176
+ };
4177
+ };
4178
+ const resolvePlacementFromViewport = () => resolvePlacement();
4179
+ const copy = async () => {
4180
+ if (typeof navigator !== "undefined") {
4181
+ await navigator.clipboard?.writeText(props.code);
4182
+ }
4183
+ state.value = controller.copied();
4184
+ emit("copy", props.code);
4185
+ window.clearTimeout(resetTimer);
4186
+ resetTimer = window.setTimeout(() => {
4187
+ state.value = controller.resetCopied();
4188
+ }, 1200);
4189
+ };
4190
+ watch(() => [props.code, props.language, props.placement, props.title], () => {
4191
+ sync();
4192
+ nextTick(resolvePlacement);
4193
+ });
4194
+ watch(() => state.value.expanded, () => nextTick(resolvePlacement));
4195
+ watch(() => state.value.expanded, (expanded, _previous, onCleanup) => {
4196
+ if (!expanded || typeof document === "undefined")
4197
+ return;
4198
+ const close = () => {
4199
+ panelStyle.value = {};
4200
+ state.value = controller.close();
4201
+ };
4202
+ const closeOnOutside = (event) => {
4203
+ const target = event.target;
4204
+ if (target &&
4205
+ (rootRef.value?.contains(target) ||
4206
+ panelRef.value?.contains(target)))
4207
+ return;
4208
+ close();
4209
+ };
4210
+ const closeOnEscape = (event) => {
4211
+ if (event.key === "Escape")
4212
+ close();
4213
+ };
4214
+ document.addEventListener("pointerdown", closeOnOutside, true);
4215
+ document.addEventListener("keydown", closeOnEscape, true);
4216
+ onCleanup(() => {
4217
+ document.removeEventListener("pointerdown", closeOnOutside, true);
4218
+ document.removeEventListener("keydown", closeOnEscape, true);
4219
+ });
4220
+ });
4221
+ onMounted(() => {
4222
+ resolvePlacement();
4223
+ window.addEventListener("resize", resolvePlacementFromViewport);
4224
+ window.addEventListener("scroll", resolvePlacementFromViewport, true);
4225
+ });
4226
+ onBeforeUnmount(() => {
4227
+ window.clearTimeout(resetTimer);
4228
+ window.removeEventListener("resize", resolvePlacementFromViewport);
4229
+ window.removeEventListener("scroll", resolvePlacementFromViewport, true);
4230
+ });
4231
+ return () => {
4232
+ const panel = h("div", {
4233
+ ref: panelRef,
4234
+ class: "cc-code-preview__panel",
4235
+ "data-placement": state.value.resolvedPlacement,
4236
+ "data-strategy": props.strategy,
4237
+ "data-expanded": state.value.expanded,
4238
+ style: panelStyle.value,
4239
+ }, [
4240
+ h(ClassHeightTransition, {
4241
+ className: "cc-height-transition cc-code-preview__transition",
4242
+ contentClass: "cc-height-transition__content cc-code-preview__panel-content",
4243
+ duration: props.transitionDuration,
4244
+ easing: props.transitionEasing,
4245
+ expanded: state.value.expanded,
4246
+ mode: "auto",
4247
+ }, {
4248
+ default: () => h("pre", null, [h("code", null, state.value.code)]),
4249
+ }),
4250
+ ]);
4251
+ return h("div", {
4252
+ ...attrs,
4253
+ ref: rootRef,
4254
+ class: props.className,
4255
+ "data-expanded": state.value.expanded,
4256
+ "data-placement": state.value.resolvedPlacement,
4257
+ "data-strategy": props.strategy,
4258
+ }, [
4259
+ h("div", { class: "cc-code-preview__bar" }, [
4260
+ h("div", { class: "cc-code-preview__meta" }, [
4261
+ h("span", { class: "cc-code-preview__title" }, [
4262
+ slots.title?.() ?? props.title,
4263
+ ]),
4264
+ h("span", { class: "cc-code-preview__lang" }, state.value.language),
4265
+ ]),
4266
+ h("div", { class: "cc-code-preview__actions" }, [
4267
+ h("button", {
4268
+ type: "button",
4269
+ onClick: () => {
4270
+ const nextState = controller.toggle();
4271
+ state.value = nextState;
4272
+ if (!nextState.expanded) {
4273
+ panelStyle.value = {};
4274
+ return;
4275
+ }
4276
+ resolvePlacement(true);
4277
+ window.requestAnimationFrame(() => resolvePlacement());
4278
+ },
4279
+ }, state.value.expanded ? "收起" : "源码"),
4280
+ h("button", { type: "button", onClick: copy }, state.value.copied ? "已复制" : "复制"),
4281
+ ]),
4282
+ ]),
4283
+ props.strategy === "fixed"
4284
+ ? h(Teleport, { to: "body" }, panel)
4285
+ : panel,
4286
+ ]);
4287
+ };
4288
+ },
4289
+ });
3775
4290
  function optionalDependencyError(packageName, featureName, fallbackName, cause) {
3776
4291
  const detail = cause instanceof Error ? ` Original error: ${cause.message}` : "";
3777
4292
  return new Error(`${featureName} requires optional dependency "${packageName}". Install it or provide ${fallbackName} from a CDN/global fallback.${detail}`);
@@ -5628,7 +6143,7 @@ const ClassSignature = /*#__PURE__*/ defineComponent({
5628
6143
  labelClass: { type: String, default: "cc-field__label" },
5629
6144
  lineWidth: { type: Number, default: 3 },
5630
6145
  name: String,
5631
- penColor: { type: String, default: "#111827" },
6146
+ penColor: { type: String, default: "#1d2129" },
5632
6147
  readOnly: optionalBooleanProp(),
5633
6148
  readonly: optionalBooleanProp(),
5634
6149
  rules: Array,
@@ -6035,6 +6550,28 @@ function getRectOverlapRatio(source, target) {
6035
6550
  const sourceArea = Math.max(1, source.width * source.height);
6036
6551
  return (width * height) / sourceArea;
6037
6552
  }
6553
+ function readDragDropPreviewStyleVars(element) {
6554
+ if (!element || typeof window === "undefined")
6555
+ return {};
6556
+ const styles = window.getComputedStyle(element);
6557
+ const read = (name) => styles.getPropertyValue(name).trim();
6558
+ const slotDraggingBackground = read("--cc-drag-drop-slot-dragging-background");
6559
+ const slotDraggingBorderColor = read("--cc-drag-drop-slot-dragging-border-color");
6560
+ const previewBackground = read("--cc-drag-drop-preview-background");
6561
+ const previewBorderColor = read("--cc-drag-drop-preview-border-color");
6562
+ const values = {
6563
+ "--cc-drag-drop-preview-background": previewBackground && !previewBackground.includes("var(")
6564
+ ? previewBackground
6565
+ : slotDraggingBackground,
6566
+ "--cc-drag-drop-preview-border-color": previewBorderColor && !previewBorderColor.includes("var(")
6567
+ ? previewBorderColor
6568
+ : slotDraggingBorderColor,
6569
+ "--cc-drag-drop-preview-color": read("--cc-drag-drop-preview-color"),
6570
+ "--cc-drag-drop-preview-shadow": read("--cc-drag-drop-preview-shadow"),
6571
+ "--cc-drag-drop-motion-duration": read("--cc-drag-drop-motion-duration"),
6572
+ };
6573
+ return Object.fromEntries(Object.entries(values).filter(([, value]) => value.length > 0));
6574
+ }
6038
6575
  const ClassDragDropBoard = /*#__PURE__*/ defineComponent({
6039
6576
  name: "ClassDragDropBoard",
6040
6577
  inheritAttrs: false,
@@ -6287,6 +6824,7 @@ const ClassDragDropBoard = /*#__PURE__*/ defineComponent({
6287
6824
  offsetY: event.clientY - rect.top,
6288
6825
  originX: rect.left,
6289
6826
  originY: rect.top,
6827
+ styleVars: readDragDropPreviewStyleVars(boardRef.value),
6290
6828
  width: rect.width,
6291
6829
  x: rect.left,
6292
6830
  y: rect.top,
@@ -6342,6 +6880,7 @@ const ClassDragDropBoard = /*#__PURE__*/ defineComponent({
6342
6880
  "data-returning": preview.value.returning,
6343
6881
  ref: previewRef,
6344
6882
  style: {
6883
+ ...preview.value.styleVars,
6345
6884
  height: `${preview.value.height}px`,
6346
6885
  transform: `translate3d(${preview.value.x}px, ${preview.value.y}px, 0)`,
6347
6886
  width: `${preview.value.width}px`,
@@ -7704,6 +8243,8 @@ const ClassMasonryVirtualList = /*#__PURE__*/ defineComponent({
7704
8243
  };
7705
8244
  },
7706
8245
  });
8246
+ const CHAT_PREPEND_MOMENTUM_LOCK_MS = 420;
8247
+ const CHAT_PREPEND_STABILIZE_FRAMES = 24;
7707
8248
  const ClassChatVirtualList = /*#__PURE__*/ defineComponent({
7708
8249
  name: "ClassChatVirtualList",
7709
8250
  inheritAttrs: false,
@@ -7778,7 +8319,7 @@ const ClassChatVirtualList = /*#__PURE__*/ defineComponent({
7778
8319
  },
7779
8320
  topLoadingContent: {
7780
8321
  type: String,
7781
- default: "正在加载历史消息...",
8322
+ default: "",
7782
8323
  },
7783
8324
  pullUpLoading: {
7784
8325
  type: Boolean,
@@ -7821,6 +8362,7 @@ const ClassChatVirtualList = /*#__PURE__*/ defineComponent({
7821
8362
  let bottomFrame;
7822
8363
  let bottomTimer;
7823
8364
  let prependFrame;
8365
+ let prependStabilizeFrame;
7824
8366
  let prependTimer;
7825
8367
  let topLoadingFallbackTimer;
7826
8368
  let topLoadingMutationPending = false;
@@ -7896,14 +8438,68 @@ const ClassChatVirtualList = /*#__PURE__*/ defineComponent({
7896
8438
  return;
7897
8439
  releaseTopLoadingLock();
7898
8440
  };
7899
- const clearPendingPrependAnchor = () => {
8441
+ const clearPendingPrependAnchor = (force = false) => {
8442
+ const pendingAnchor = pendingPrependAnchor.value;
8443
+ if (!force && pendingAnchor) {
8444
+ const remaining = pendingAnchor.releaseAt - Date.now();
8445
+ if (remaining > 0) {
8446
+ if (prependTimer !== undefined)
8447
+ window.clearTimeout(prependTimer);
8448
+ prependTimer = window.setTimeout(() => {
8449
+ clearPendingPrependAnchor(true);
8450
+ }, remaining);
8451
+ schedulePrependStabilization();
8452
+ return;
8453
+ }
8454
+ }
7900
8455
  pendingPrependAnchor.value = null;
8456
+ if (prependStabilizeFrame !== undefined) {
8457
+ window.cancelAnimationFrame(prependStabilizeFrame);
8458
+ prependStabilizeFrame = undefined;
8459
+ }
7901
8460
  if (prependTimer !== undefined) {
7902
8461
  window.clearTimeout(prependTimer);
7903
8462
  prependTimer = undefined;
7904
8463
  }
7905
8464
  maybeReleaseTopLoadingLock();
7906
8465
  };
8466
+ const applyPendingPrependAnchor = () => {
8467
+ const pendingAnchor = pendingPrependAnchor.value;
8468
+ const viewport = viewportRef.value;
8469
+ if (!pendingAnchor || !viewport)
8470
+ return false;
8471
+ const keys = getKeys();
8472
+ const anchorIndex = keys.findIndex((itemKey) => Object.is(itemKey, pendingAnchor.anchorKey));
8473
+ const nextScrollTop = anchorIndex >= 0
8474
+ ? Math.max(0, listController.getItem(anchorIndex).start -
8475
+ pendingAnchor.anchorOffset)
8476
+ : pendingAnchor.targetScrollTop;
8477
+ viewport.scrollTop = nextScrollTop;
8478
+ scrollOffset.value = nextScrollTop;
8479
+ previousScrollTop.value = nextScrollTop;
8480
+ return true;
8481
+ };
8482
+ const schedulePrependStabilization = () => {
8483
+ if (prependStabilizeFrame !== undefined) {
8484
+ window.cancelAnimationFrame(prependStabilizeFrame);
8485
+ }
8486
+ let remainingFrames = CHAT_PREPEND_STABILIZE_FRAMES;
8487
+ const stabilize = () => {
8488
+ const pendingAnchor = pendingPrependAnchor.value;
8489
+ if (!pendingAnchor) {
8490
+ prependStabilizeFrame = undefined;
8491
+ return;
8492
+ }
8493
+ applyPendingPrependAnchor();
8494
+ remainingFrames -= 1;
8495
+ if (remainingFrames <= 0 && pendingAnchor.releaseAt <= Date.now()) {
8496
+ prependStabilizeFrame = undefined;
8497
+ return;
8498
+ }
8499
+ prependStabilizeFrame = window.requestAnimationFrame(stabilize);
8500
+ };
8501
+ prependStabilizeFrame = window.requestAnimationFrame(stabilize);
8502
+ };
7907
8503
  const scheduleTopLoadingFallback = () => {
7908
8504
  if (topLoadingFallbackTimer !== undefined) {
7909
8505
  window.clearTimeout(topLoadingFallbackTimer);
@@ -8015,8 +8611,12 @@ const ClassChatVirtualList = /*#__PURE__*/ defineComponent({
8015
8611
  anchorOffset: previousAnchor.offset,
8016
8612
  measuredKeys: new Set(),
8017
8613
  prependKeys: new Set(keys.slice(0, prependCount)),
8614
+ releaseAt: Date.now() + CHAT_PREPEND_MOMENTUM_LOCK_MS,
8615
+ targetScrollTop: nextScrollTop,
8018
8616
  }
8019
8617
  : null;
8618
+ if (pendingPrependAnchor.value)
8619
+ schedulePrependStabilization();
8020
8620
  if (prependFrame !== undefined)
8021
8621
  window.cancelAnimationFrame(prependFrame);
8022
8622
  if (prependTimer !== undefined)
@@ -8138,6 +8738,8 @@ const ClassChatVirtualList = /*#__PURE__*/ defineComponent({
8138
8738
  window.clearTimeout(bottomTimer);
8139
8739
  if (prependFrame !== undefined)
8140
8740
  window.cancelAnimationFrame(prependFrame);
8741
+ if (prependStabilizeFrame !== undefined)
8742
+ window.cancelAnimationFrame(prependStabilizeFrame);
8141
8743
  if (prependTimer !== undefined)
8142
8744
  window.clearTimeout(prependTimer);
8143
8745
  if (topLoadingFallbackTimer !== undefined)
@@ -8151,6 +8753,12 @@ const ClassChatVirtualList = /*#__PURE__*/ defineComponent({
8151
8753
  if (!(element instanceof HTMLElement))
8152
8754
  return;
8153
8755
  const measure = () => {
8756
+ const keys = getKeys();
8757
+ const oldKeys = previousKeys.value;
8758
+ const hasPendingKeySync = oldKeys.length !== keys.length ||
8759
+ oldKeys.some((itemKey, keyIndex) => !Object.is(itemKey, keys[keyIndex]));
8760
+ if (!pendingPrependAnchor.value && hasPendingKeySync)
8761
+ return;
8154
8762
  const viewport = viewportRef.value;
8155
8763
  const oldTotal = listController.getTotalSize();
8156
8764
  const oldItem = listController.getItem(index);
@@ -8164,17 +8772,19 @@ const ClassChatVirtualList = /*#__PURE__*/ defineComponent({
8164
8772
  if (pendingAnchor) {
8165
8773
  if (pendingAnchor.prependKeys.has(key))
8166
8774
  pendingAnchor.measuredKeys.add(key);
8167
- const keys = getKeys();
8168
8775
  const anchorIndex = keys.findIndex((itemKey) => Object.is(itemKey, pendingAnchor.anchorKey));
8169
8776
  if (anchorIndex >= 0) {
8170
8777
  const anchorItem = listController.getItem(anchorIndex);
8171
8778
  const nextItem = listController.getItem(index);
8172
8779
  const delta = nextItem.size - oldItem.size;
8173
- viewport.scrollTop = Math.max(0, index < anchorIndex && delta !== 0
8780
+ const nextScrollTop = Math.max(0, index < anchorIndex && delta !== 0
8174
8781
  ? oldScrollTop + delta
8175
8782
  : anchorItem.start - pendingAnchor.anchorOffset);
8176
- scrollOffset.value = viewport.scrollTop;
8177
- previousScrollTop.value = viewport.scrollTop;
8783
+ pendingAnchor.targetScrollTop = nextScrollTop;
8784
+ viewport.scrollTop = nextScrollTop;
8785
+ scrollOffset.value = nextScrollTop;
8786
+ previousScrollTop.value = nextScrollTop;
8787
+ schedulePrependStabilization();
8178
8788
  }
8179
8789
  if (pendingAnchor.measuredKeys.size >= pendingAnchor.prependKeys.size) {
8180
8790
  clearPendingPrependAnchor();
@@ -8212,18 +8822,24 @@ const ClassChatVirtualList = /*#__PURE__*/ defineComponent({
8212
8822
  "data-top-loading": topLoadingPending.value ? "true" : undefined,
8213
8823
  style: { "--cc-chat-virtual-list-height": resolvedHeight },
8214
8824
  }, [
8215
- h("div", {
8216
- "aria-hidden": topLoadingPending.value ? undefined : "true",
8217
- class: props.topLoadingClass,
8218
- "data-active": topLoadingPending.value ? "true" : "false",
8219
- role: topLoadingPending.value ? "status" : undefined,
8220
- }, slots.topLoading?.({ loading: topLoadingPending.value }) ??
8221
- props.topLoadingContent),
8825
+ slots.topLoading?.({ loading: topLoadingPending.value }) ??
8826
+ h(ClassLoading, {
8827
+ "aria-hidden": topLoadingPending.value ? undefined : "true",
8828
+ className: props.topLoadingClass,
8829
+ "data-active": topLoadingPending.value ? "true" : "false",
8830
+ role: topLoadingPending.value ? "status" : undefined,
8831
+ text: props.topLoadingContent,
8832
+ }),
8222
8833
  h("div", {
8223
8834
  class: props.viewportClass,
8224
8835
  "data-top-loading": topLoadingPending.value ? "true" : undefined,
8225
8836
  ref: viewportRef,
8226
8837
  onScroll: (event) => {
8838
+ if (pendingPrependAnchor.value) {
8839
+ const stabilized = applyPendingPrependAnchor();
8840
+ if (stabilized)
8841
+ return;
8842
+ }
8227
8843
  const nextScrollTop = event.currentTarget
8228
8844
  .scrollTop;
8229
8845
  const viewport = event.currentTarget;
@@ -8605,6 +9221,117 @@ const ClassBreadcrumb = /*#__PURE__*/ defineComponent({
8605
9221
  };
8606
9222
  },
8607
9223
  });
9224
+ function renderVueMenuItems(items, collapsed, slots, toggle, select) {
9225
+ return items.map((item) => {
9226
+ const hasChildren = item.children.length > 0;
9227
+ const icon = slots.icon?.({ item }) ??
9228
+ item.icon ??
9229
+ (collapsed ? item.label.slice(0, 1) : undefined);
9230
+ return h("li", {
9231
+ class: "cc-menu__item",
9232
+ "data-active": item.isActive,
9233
+ "data-disabled": item.disabled,
9234
+ "data-expanded": item.expanded,
9235
+ "data-level": item.level,
9236
+ key: item.key,
9237
+ }, [
9238
+ h("button", {
9239
+ "aria-current": item.isActive ? "page" : undefined,
9240
+ "aria-expanded": hasChildren ? item.expanded : undefined,
9241
+ class: "cc-menu__button",
9242
+ disabled: item.disabled,
9243
+ title: collapsed ? item.label : undefined,
9244
+ type: "button",
9245
+ onClick: () => {
9246
+ if (hasChildren && !collapsed)
9247
+ toggle(item.key);
9248
+ select(item.key, item);
9249
+ },
9250
+ }, [
9251
+ icon
9252
+ ? h("span", { class: "cc-menu__icon", "aria-hidden": "true" }, icon)
9253
+ : null,
9254
+ h("span", { class: "cc-menu__label" }, item.label),
9255
+ hasChildren ? classIcon("chevronDown", "cc-menu__arrow") : null,
9256
+ ]),
9257
+ hasChildren
9258
+ ? h(ClassHeightTransition, {
9259
+ className: "cc-height-transition cc-menu__transition",
9260
+ contentClass: "cc-height-transition__content cc-menu__transition-content",
9261
+ duration: 180,
9262
+ expanded: !collapsed && item.expanded,
9263
+ mode: "grid",
9264
+ }, () => h("ul", { class: "cc-menu__list cc-menu__list--child" }, renderVueMenuItems(item.children, collapsed, slots, toggle, select)))
9265
+ : null,
9266
+ ]);
9267
+ });
9268
+ }
9269
+ const ClassMenu = /*#__PURE__*/ defineComponent({
9270
+ name: "ClassMenu",
9271
+ props: {
9272
+ activeKey: String,
9273
+ className: { type: String, default: "cc-menu" },
9274
+ collapsed: Boolean,
9275
+ collapsible: { type: Boolean, default: true },
9276
+ defaultExpandedKeys: {
9277
+ type: Array,
9278
+ default: () => [],
9279
+ },
9280
+ items: { type: Array, default: () => [] },
9281
+ },
9282
+ emits: ["collapsed-change", "select", "update:activeKey", "update:collapsed"],
9283
+ setup(props, { attrs, emit, slots }) {
9284
+ const controller = new MenuController({
9285
+ activeKey: props.activeKey,
9286
+ collapsed: props.collapsed,
9287
+ defaultExpandedKeys: props.defaultExpandedKeys,
9288
+ items: props.items,
9289
+ });
9290
+ const state = ref(controller.getState());
9291
+ watch(() => [
9292
+ props.activeKey,
9293
+ props.collapsed,
9294
+ props.defaultExpandedKeys,
9295
+ props.items,
9296
+ ], () => {
9297
+ state.value = controller.update({
9298
+ activeKey: props.activeKey,
9299
+ collapsed: props.collapsed,
9300
+ defaultExpandedKeys: props.defaultExpandedKeys,
9301
+ items: props.items,
9302
+ });
9303
+ }, { deep: true });
9304
+ const toggle = (key) => {
9305
+ state.value = controller.toggleExpanded(key);
9306
+ };
9307
+ const select = (key, item) => {
9308
+ state.value = controller.activate(key);
9309
+ emit("update:activeKey", key);
9310
+ emit("select", key, item);
9311
+ };
9312
+ const toggleCollapsed = () => {
9313
+ state.value = controller.toggleCollapsed();
9314
+ emit("update:collapsed", state.value.collapsed);
9315
+ emit("collapsed-change", state.value.collapsed);
9316
+ };
9317
+ return () => h("nav", {
9318
+ ...attrs,
9319
+ class: props.className,
9320
+ "data-collapsed": state.value.collapsed,
9321
+ "data-collapsible": props.collapsible,
9322
+ }, [
9323
+ props.collapsible
9324
+ ? h("button", {
9325
+ "aria-label": state.value.collapsed ? "展开菜单" : "收起菜单",
9326
+ class: "cc-menu__collapse",
9327
+ type: "button",
9328
+ onClick: toggleCollapsed,
9329
+ }, classIcon(state.value.collapsed ? "chevronRight" : "chevronLeft"))
9330
+ : null,
9331
+ h("ul", { class: "cc-menu__list" }, renderVueMenuItems(state.value.items, state.value.collapsed, slots, toggle, select)),
9332
+ ]);
9333
+ },
9334
+ });
8608
9335
  const ClassPagination = /*#__PURE__*/ defineComponent({
8609
9336
  name: "ClassPagination",
8610
9337
  props: {
@@ -8687,6 +9414,7 @@ const ClassPopconfirm = /*#__PURE__*/ defineComponent({
8687
9414
  },
8688
9415
  closeOnEsc: { type: Boolean, default: true },
8689
9416
  closeOnOutsideClick: { type: Boolean, default: true },
9417
+ portal: { type: Boolean, default: true },
8690
9418
  },
8691
9419
  emits: ["confirm"],
8692
9420
  setup(props, { emit, slots }) {
@@ -8696,8 +9424,23 @@ const ClassPopconfirm = /*#__PURE__*/ defineComponent({
8696
9424
  const visible = ref(false);
8697
9425
  const phase = ref("exit");
8698
9426
  const safePlacement = ref(props.placement);
9427
+ const anchorStyle = ref({
9428
+ height: 0,
9429
+ left: -9999,
9430
+ top: -9999,
9431
+ width: 0,
9432
+ });
8699
9433
  let exitTimer;
8700
9434
  const updatePlacement = () => {
9435
+ if (rootRef.value) {
9436
+ const rect = rootRef.value.getBoundingClientRect();
9437
+ anchorStyle.value = {
9438
+ height: rect.height,
9439
+ left: rect.left,
9440
+ top: rect.top,
9441
+ width: rect.width,
9442
+ };
9443
+ }
8701
9444
  if (!props.autoAdjust || !rootRef.value || !panelRef.value) {
8702
9445
  safePlacement.value = props.placement;
8703
9446
  return;
@@ -8727,7 +9470,8 @@ const ClassPopconfirm = /*#__PURE__*/ defineComponent({
8727
9470
  };
8728
9471
  const closeOnOutside = (event) => {
8729
9472
  if (!props.closeOnOutsideClick ||
8730
- rootRef.value?.contains(event.target))
9473
+ rootRef.value?.contains(event.target) ||
9474
+ panelRef.value?.contains(event.target))
8731
9475
  return;
8732
9476
  hide();
8733
9477
  };
@@ -8754,34 +9498,58 @@ const ClassPopconfirm = /*#__PURE__*/ defineComponent({
8754
9498
  watch(() => props.placement, updatePlacement);
8755
9499
  return () => {
8756
9500
  const motion = resolveAnimation(props.animation, "scale");
8757
- return h("span", {
8758
- class: ["cc-popconfirm", `cc-popconfirm--${safePlacement.value}`],
9501
+ const rootClass = [
9502
+ "cc-popconfirm",
9503
+ `cc-popconfirm--${safePlacement.value}`,
9504
+ ];
9505
+ const panelNode = visible.value
9506
+ ? h("span", {
9507
+ class: "cc-popconfirm__panel",
9508
+ "data-state": phase.value,
9509
+ ref: panelRef,
9510
+ role: "dialog",
9511
+ }, [
9512
+ h("span", null, props.content),
9513
+ h("span", { class: "cc-popconfirm__actions" }, [
9514
+ h("button", { type: "button", onClick: hide }, props.cancelText),
9515
+ h("button", {
9516
+ type: "button",
9517
+ onClick: () => {
9518
+ emit("confirm");
9519
+ hide();
9520
+ },
9521
+ }, props.confirmText),
9522
+ ]),
9523
+ ])
9524
+ : null;
9525
+ const rootNode = h("span", {
9526
+ class: rootClass,
8759
9527
  "data-animation": motion.name,
8760
9528
  ref: rootRef,
8761
9529
  style: animationStyle(motion),
8762
9530
  }, [
8763
9531
  h("span", { onClick: show }, slots.default?.()),
8764
- visible.value
8765
- ? h("span", {
8766
- class: "cc-popconfirm__panel",
8767
- "data-state": phase.value,
8768
- ref: panelRef,
8769
- role: "dialog",
8770
- }, [
8771
- h("span", null, props.content),
8772
- h("span", { class: "cc-popconfirm__actions" }, [
8773
- h("button", { type: "button", onClick: hide }, props.cancelText),
8774
- h("button", {
8775
- type: "button",
8776
- onClick: () => {
8777
- emit("confirm");
8778
- hide();
8779
- },
8780
- }, props.confirmText),
8781
- ]),
8782
- ])
8783
- : null,
9532
+ props.portal ? null : panelNode,
8784
9533
  ]);
9534
+ if (!props.portal)
9535
+ return rootNode;
9536
+ const portalNode = visible.value
9537
+ ? h("span", {
9538
+ class: [...rootClass, "cc-popconfirm--portal"],
9539
+ "data-animation": motion.name,
9540
+ style: {
9541
+ ...animationStyle(motion),
9542
+ height: `${anchorStyle.value.height}px`,
9543
+ left: `${anchorStyle.value.left}px`,
9544
+ top: `${anchorStyle.value.top}px`,
9545
+ width: `${anchorStyle.value.width}px`,
9546
+ },
9547
+ }, [panelNode])
9548
+ : null;
9549
+ return [
9550
+ rootNode,
9551
+ portalNode ? h(Teleport, { to: "body" }, portalNode) : null,
9552
+ ];
8785
9553
  };
8786
9554
  },
8787
9555
  });
@@ -9330,9 +10098,7 @@ const ClassPopup = /*#__PURE__*/ defineComponent({
9330
10098
  ]),
9331
10099
  ]);
9332
10100
  return rendered.value
9333
- ? props.container
9334
- ? h(Teleport, { to: props.container }, popupNode)
9335
- : popupNode
10101
+ ? h(Teleport, { to: props.container ?? "body" }, popupNode)
9336
10102
  : null;
9337
10103
  };
9338
10104
  },
@@ -9369,6 +10135,10 @@ const ClassTooltip = /*#__PURE__*/ defineComponent({
9369
10135
  type: Boolean,
9370
10136
  default: true,
9371
10137
  },
10138
+ portal: {
10139
+ type: Boolean,
10140
+ default: true,
10141
+ },
9372
10142
  className: String,
9373
10143
  },
9374
10144
  setup(props, { attrs, slots }) {
@@ -9378,7 +10148,22 @@ const ClassTooltip = /*#__PURE__*/ defineComponent({
9378
10148
  const controller = new TooltipController();
9379
10149
  const open = ref(controller.isOpen());
9380
10150
  const safePlacement = ref(props.placement);
10151
+ const anchorStyle = ref({
10152
+ height: 0,
10153
+ left: -9999,
10154
+ top: -9999,
10155
+ width: 0,
10156
+ });
9381
10157
  const updatePlacement = () => {
10158
+ if (rootRef.value) {
10159
+ const rect = rootRef.value.getBoundingClientRect();
10160
+ anchorStyle.value = {
10161
+ height: rect.height,
10162
+ left: rect.left,
10163
+ top: rect.top,
10164
+ width: rect.width,
10165
+ };
10166
+ }
9382
10167
  if (!props.autoAdjust || !rootRef.value || !contentRef.value) {
9383
10168
  safePlacement.value = props.placement;
9384
10169
  return;
@@ -9396,7 +10181,8 @@ const ClassTooltip = /*#__PURE__*/ defineComponent({
9396
10181
  return;
9397
10182
  const handlePointerDown = (event) => {
9398
10183
  if (!props.closeOnOutsideClick ||
9399
- rootRef.value?.contains(event.target))
10184
+ rootRef.value?.contains(event.target) ||
10185
+ contentRef.value?.contains(event.target))
9400
10186
  return;
9401
10187
  controller.close();
9402
10188
  };
@@ -9422,7 +10208,6 @@ const ClassTooltip = /*#__PURE__*/ defineComponent({
9422
10208
  });
9423
10209
  watch(() => props.placement, () => updatePlacement());
9424
10210
  return () => {
9425
- const motion = resolveAnimation(props.animation, "fade");
9426
10211
  const openEvents = props.trigger === "click"
9427
10212
  ? {
9428
10213
  onClick: () => {
@@ -9443,29 +10228,49 @@ const ClassTooltip = /*#__PURE__*/ defineComponent({
9443
10228
  controller.close();
9444
10229
  },
9445
10230
  };
9446
- return h("span", {
10231
+ const motion = resolveAnimation(props.animation, "fade");
10232
+ const tooltipClass = [
10233
+ "cc-tooltip",
10234
+ `cc-tooltip--${safePlacement.value}`,
10235
+ props.className,
10236
+ ];
10237
+ const tooltipContent = h("span", {
10238
+ class: "cc-tooltip__content",
10239
+ id: contentId,
10240
+ ref: contentRef,
10241
+ role: "tooltip",
10242
+ }, props.content);
10243
+ const rootNode = h("span", {
9447
10244
  ...attrs,
9448
10245
  ...openEvents,
9449
10246
  "aria-describedby": open.value ? contentId : undefined,
9450
- class: [
9451
- "cc-tooltip",
9452
- `cc-tooltip--${safePlacement.value}`,
9453
- props.className,
9454
- ],
10247
+ class: tooltipClass,
9455
10248
  "data-animation": motion.name,
9456
10249
  "data-open": open.value,
9457
10250
  ref: rootRef,
9458
10251
  style: animationStyle(motion),
9459
10252
  tabindex: props.trigger === "click" ? 0 : undefined,
9460
- }, [
9461
- slots.default?.(),
9462
- h("span", {
9463
- class: "cc-tooltip__content",
9464
- id: contentId,
9465
- ref: contentRef,
9466
- role: "tooltip",
9467
- }, props.content),
9468
- ]);
10253
+ }, [slots.default?.(), props.portal ? null : tooltipContent]);
10254
+ if (!props.portal)
10255
+ return rootNode;
10256
+ const portalNode = open.value || anchorStyle.value.left > -9999
10257
+ ? h("span", {
10258
+ class: [...tooltipClass, "cc-tooltip--portal"],
10259
+ "data-animation": motion.name,
10260
+ "data-open": open.value,
10261
+ style: {
10262
+ ...animationStyle(motion),
10263
+ height: `${anchorStyle.value.height}px`,
10264
+ left: `${anchorStyle.value.left}px`,
10265
+ top: `${anchorStyle.value.top}px`,
10266
+ width: `${anchorStyle.value.width}px`,
10267
+ },
10268
+ }, [tooltipContent])
10269
+ : null;
10270
+ return [
10271
+ rootNode,
10272
+ portalNode ? h(Teleport, { to: "body" }, portalNode) : null,
10273
+ ];
9469
10274
  };
9470
10275
  },
9471
10276
  });
@@ -9478,6 +10283,10 @@ const ClassToastViewport = /*#__PURE__*/ defineComponent({
9478
10283
  default: undefined,
9479
10284
  },
9480
10285
  manager: Object,
10286
+ maxVisible: {
10287
+ type: Number,
10288
+ default: undefined,
10289
+ },
9481
10290
  position: {
9482
10291
  type: String,
9483
10292
  default: "top-right",
@@ -9488,38 +10297,110 @@ const ClassToastViewport = /*#__PURE__*/ defineComponent({
9488
10297
  },
9489
10298
  },
9490
10299
  setup(props, { attrs, slots }) {
9491
- const manager = props.manager ?? defaultToastManager;
9492
- const items = shallowRef(manager.getToasts());
9493
- const getVisibleItems = (source) => source.filter((item) => item.position === props.position);
9494
- const renderedItems = shallowRef(getVisibleItems(items.value).map((item) => ({ item, state: "enter" })));
10300
+ const activeManager = shallowRef(props.manager ?? defaultToastManager);
10301
+ const items = shallowRef(activeManager.value.getToasts());
10302
+ const getVisibleItems = (source) => {
10303
+ const positionItems = source.filter((item) => item.position === props.position);
10304
+ const visible = positionItems.slice(Math.max(0, positionItems.length - normalizeToastMaxVisible(props.maxVisible)));
10305
+ return isToastTopPosition(props.position)
10306
+ ? [...visible].reverse()
10307
+ : visible;
10308
+ };
10309
+ const renderedItems = shallowRef(getVisibleItems(items.value).map((item) => ({
10310
+ item,
10311
+ motion: false,
10312
+ state: "enter",
10313
+ })));
10314
+ const toastNodes = new Map();
10315
+ let rects = new Map();
9495
10316
  let timer;
9496
10317
  let frame = 0;
10318
+ let flipFrame = 0;
10319
+ const setToastNode = (id, node) => {
10320
+ if (node instanceof HTMLElement)
10321
+ toastNodes.set(id, node);
10322
+ else
10323
+ toastNodes.delete(id);
10324
+ };
10325
+ const runFlip = async (motion) => {
10326
+ if (flipFrame)
10327
+ cancelAnimationFrame(flipFrame);
10328
+ await nextTick();
10329
+ const previousRects = rects;
10330
+ const nextRects = new Map();
10331
+ const activeIds = new Set(renderedItems.value
10332
+ .filter((entry) => entry.motion && entry.state !== "exit")
10333
+ .map(({ item }) => item.id));
10334
+ toastNodes.forEach((node, id) => {
10335
+ if (!activeIds.has(id))
10336
+ return;
10337
+ const rect = node.getBoundingClientRect();
10338
+ nextRects.set(id, rect);
10339
+ const previous = previousRects.get(id);
10340
+ if (!previous)
10341
+ return;
10342
+ const deltaY = previous.top - rect.top;
10343
+ if (Math.abs(deltaY) < 1)
10344
+ return;
10345
+ node.style.transition = "none";
10346
+ node.style.setProperty("--cc-toast-stack-offset", `${deltaY}px`);
10347
+ node.style.willChange = "transform, opacity";
10348
+ });
10349
+ flipFrame = requestAnimationFrame(() => {
10350
+ toastNodes.forEach((node, id) => {
10351
+ if (!nextRects.has(id))
10352
+ return;
10353
+ node.style.transition = `transform ${motion.duration}ms ${motion.easing}, opacity ${motion.duration}ms ${motion.easing}, margin ${motion.duration}ms ${motion.easing}`;
10354
+ node.style.removeProperty("--cc-toast-stack-offset");
10355
+ window.setTimeout(() => {
10356
+ node.style.transition = "";
10357
+ node.style.willChange = "";
10358
+ }, motion.duration);
10359
+ });
10360
+ flipFrame = 0;
10361
+ });
10362
+ rects = nextRects;
10363
+ };
9497
10364
  const syncRenderedItems = (nextItems) => {
9498
10365
  if (frame)
9499
10366
  cancelAnimationFrame(frame);
10367
+ const motion = resolveAnimation(props.animation, "slide");
9500
10368
  const currentIds = new Set(renderedItems.value.map(({ item }) => item.id));
9501
10369
  const incomingIds = new Set(nextItems.map((item) => item.id));
10370
+ const incomingById = new Map(nextItems.map((item) => [item.id, item]));
9502
10371
  const enteringIds = nextItems
9503
10372
  .filter((item) => !currentIds.has(item.id))
9504
10373
  .map((item) => item.id);
9505
- const next = nextItems.map((item) => ({
9506
- item,
9507
- state: currentIds.has(item.id) ? "enter" : "exit",
10374
+ const retainedOrExiting = renderedItems.value.map(({ item }) => ({
10375
+ item: incomingById.get(item.id) ?? item,
10376
+ motion: !incomingIds.has(item.id),
10377
+ state: incomingIds.has(item.id)
10378
+ ? "enter"
10379
+ : "exit",
9508
10380
  }));
9509
- const exiting = renderedItems.value
9510
- .filter(({ item }) => !incomingIds.has(item.id))
9511
- .map(({ item }) => ({ item, state: "exit" }));
9512
- renderedItems.value = [...next, ...exiting];
10381
+ const entering = nextItems
10382
+ .filter((item) => !currentIds.has(item.id))
10383
+ .map((item) => ({ item, motion: true, state: "prepare" }));
10384
+ renderedItems.value = [...retainedOrExiting, ...entering];
10385
+ void runFlip(motion);
9513
10386
  if (enteringIds.length) {
9514
10387
  frame = requestAnimationFrame(() => {
9515
10388
  renderedItems.value = renderedItems.value.map((entry) => enteringIds.includes(entry.item.id)
9516
10389
  ? { ...entry, state: "enter" }
9517
10390
  : entry);
9518
10391
  });
10392
+ const clearMotion = () => {
10393
+ renderedItems.value = renderedItems.value.map((entry) => enteringIds.includes(entry.item.id) && entry.state === "enter"
10394
+ ? { ...entry, motion: false }
10395
+ : entry);
10396
+ };
10397
+ if (!motion.enabled || motion.duration <= 0)
10398
+ clearMotion();
10399
+ else
10400
+ setTimeout(clearMotion, motion.duration);
9519
10401
  }
9520
- if (!exiting.length)
10402
+ if (!retainedOrExiting.some((entry) => entry.state === "exit"))
9521
10403
  return;
9522
- const motion = resolveAnimation(props.animation, "slide");
9523
10404
  if (timer)
9524
10405
  clearTimeout(timer);
9525
10406
  if (!motion.enabled || motion.duration <= 0) {
@@ -9530,37 +10411,57 @@ const ClassToastViewport = /*#__PURE__*/ defineComponent({
9530
10411
  renderedItems.value = renderedItems.value.filter((entry) => entry.state !== "exit");
9531
10412
  }, motion.duration);
9532
10413
  };
9533
- const unsubscribe = manager.subscribe((nextItems) => {
9534
- items.value = nextItems;
9535
- syncRenderedItems(getVisibleItems(nextItems));
10414
+ let unsubscribe = () => { };
10415
+ const subscribeManager = (nextManager) => {
10416
+ unsubscribe();
10417
+ activeManager.value = nextManager;
10418
+ items.value = nextManager.getToasts();
10419
+ syncRenderedItems(getVisibleItems(items.value));
10420
+ unsubscribe = nextManager.subscribe((nextItems) => {
10421
+ items.value = nextItems;
10422
+ syncRenderedItems(getVisibleItems(nextItems));
10423
+ });
10424
+ };
10425
+ subscribeManager(activeManager.value);
10426
+ watch(() => props.manager, (nextManager) => {
10427
+ subscribeManager(nextManager ?? defaultToastManager);
9536
10428
  });
9537
- watch(() => props.position, () => syncRenderedItems(getVisibleItems(items.value)));
10429
+ watch(() => [props.position, props.maxVisible], () => syncRenderedItems(getVisibleItems(items.value)));
9538
10430
  onBeforeUnmount(() => {
9539
10431
  if (timer)
9540
10432
  clearTimeout(timer);
9541
10433
  if (frame)
9542
10434
  cancelAnimationFrame(frame);
10435
+ if (flipFrame)
10436
+ cancelAnimationFrame(flipFrame);
9543
10437
  unsubscribe();
9544
10438
  });
9545
10439
  return () => {
9546
10440
  const motion = resolveAnimation(props.animation, "slide");
9547
- return h("div", {
10441
+ const viewportNode = h("div", {
9548
10442
  ...attrs,
9549
10443
  "aria-live": "polite",
9550
10444
  class: [props.className, `cc-toast-viewport--${props.position}`],
9551
10445
  role: "status",
9552
10446
  style: animationStyle(motion),
9553
- }, renderedItems.value.map(({ item, state }) => slots.default
10447
+ }, renderedItems.value.map(({ item, motion: isMotionActive, state }, index) => slots.default
9554
10448
  ? slots.default({
9555
10449
  item,
9556
- dismiss: () => manager.dismiss(item.id),
10450
+ dismiss: () => activeManager.value.dismiss(item.id),
9557
10451
  state,
9558
10452
  })
9559
10453
  : h("article", {
9560
10454
  class: `cc-toast cc-toast--${item.tone}`,
9561
10455
  "data-animation": motion.name,
10456
+ "data-motion": isMotionActive ? "true" : "false",
9562
10457
  "data-state": state,
9563
10458
  key: item.id,
10459
+ style: {
10460
+ "--cc-toast-stack-index": index,
10461
+ },
10462
+ ref: (node) => {
10463
+ setToastNode(item.id, node instanceof Element ? node : null);
10464
+ },
9564
10465
  }, [
9565
10466
  item.title
9566
10467
  ? h("strong", { class: "cc-toast__title" }, item.title)
@@ -9570,9 +10471,10 @@ const ClassToastViewport = /*#__PURE__*/ defineComponent({
9570
10471
  "aria-label": "Dismiss toast",
9571
10472
  class: "cc-toast__close",
9572
10473
  type: "button",
9573
- onClick: () => manager.dismiss(item.id),
9574
- }, "x"),
10474
+ onClick: () => activeManager.value.dismiss(item.id),
10475
+ }, classIcon("x")),
9575
10476
  ])));
10477
+ return h(Teleport, { to: "body" }, viewportNode);
9576
10478
  };
9577
10479
  },
9578
10480
  });
@@ -11066,5 +11968,5 @@ const ClassLiveRoom = /*#__PURE__*/ defineComponent({
11066
11968
  },
11067
11969
  });
11068
11970
 
11069
- export { ClassAffix, ClassBacktop, ClassBadge, ClassBarcode, ClassBreadcrumb, ClassButton, ClassCalendar, ClassCanvasEditor, ClassCanvasImage, ClassChatVirtualList, ClassCheckbox, ClassChecked, ClassColorPicker, ClassComicReader, ClassConfigProvider, ClassConfigTable, ClassCountdown, ClassDanmaku, ClassDatePicker, ClassDateRangePicker, ClassDesignEffect, ClassDragDropBoard, ClassDraggable, ClassEllipsisText, ClassEmpty, ClassField, ClassFilePreview, ClassFloatingBall, ClassForm, ClassGradientText, ClassInput, ClassLazyImage, ClassLiveRoom, ClassLoading, ClassMarquee, ClassMasonryVirtualList, ClassModal, ClassMultiColumnPicker, ClassNovelReader, ClassNumberInput, ClassPagination, ClassPasswordInput, ClassPopconfirm, ClassPopup, ClassProgressBar, ClassQRCode, ClassRadioGroup, ClassRating, ClassRollingNumber, ClassSelect, ClassSignature, ClassSkeleton, ClassSlideCaptcha, ClassSwiper, ClassSwitch, ClassTable, ClassTabs, ClassTag, ClassTextarea, ClassTiltCard, ClassTimeline, ClassToastViewport, ClassTooltip, ClassTypewriterText, ClassUpload, ClassVerificationCode, ClassVideoDetailTransition, ClassVideoPlayer, ClassVirtualList, ClassVirtualSelect, ClassVirtualTable, defaultToastManager, useField, useForm, useFormState };
11971
+ export { ClassAffix, ClassBacktop, ClassBadge, ClassBarcode, ClassBreadcrumb, ClassButton, ClassCalendar, ClassCanvasEditor, ClassCanvasImage, ClassChatTextarea, ClassChatVirtualList, ClassCheckbox, ClassChecked, ClassCodePreview, ClassColorPicker, ClassComicReader, ClassConfigProvider, ClassConfigTable, ClassCountdown, ClassDanmaku, ClassDatePicker, ClassDateRangePicker, ClassDesignEffect, ClassDragDropBoard, ClassDraggable, ClassEllipsisText, ClassEmpty, ClassField, ClassFilePreview, ClassFloatingBall, ClassForm, ClassGradientText, ClassHeightTransition, ClassInput, ClassLazyImage, ClassLiveRoom, ClassLoading, ClassMarquee, ClassMasonryVirtualList, ClassMenu, ClassModal, ClassMultiColumnPicker, ClassNovelReader, ClassNumberInput, ClassOrbitalSphere, ClassPagination, ClassPasswordInput, ClassPopconfirm, ClassPopup, ClassProgressBar, ClassQRCode, ClassRadioGroup, ClassRating, ClassRollingNumber, ClassSelect, ClassSignature, ClassSkeleton, ClassSlideCaptcha, ClassSwiper, ClassSwitch, ClassTable, ClassTabs, ClassTag, ClassTextarea, ClassTiltCard, ClassTimeline, ClassToastViewport, ClassTooltip, ClassTypewriterText, ClassUpload, ClassVerificationCode, ClassVideoDetailTransition, ClassVideoPlayer, ClassVirtualList, ClassVirtualSelect, ClassVirtualTable, defaultToastManager, useField, useForm, useFormState };
11070
11972
  //# sourceMappingURL=index.js.map