@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.cjs CHANGED
@@ -107,6 +107,14 @@ function animationStyle(animation) {
107
107
  "--cc-animation-easing": animation.easing,
108
108
  };
109
109
  }
110
+ function normalizeToastMaxVisible(maxVisible) {
111
+ if (typeof maxVisible !== "number" || !Number.isFinite(maxVisible))
112
+ return 3;
113
+ return Math.max(1, Math.min(6, Math.floor(maxVisible)));
114
+ }
115
+ function isToastTopPosition(position) {
116
+ return (position === "top" || position === "top-left" || position === "top-right");
117
+ }
110
118
  const focusableSelector = [
111
119
  "a[href]",
112
120
  "button:not([disabled])",
@@ -727,7 +735,7 @@ const ClassColorPicker = /*#__PURE__*/ vue.defineComponent({
727
735
  });
728
736
  return () => {
729
737
  const interactivity = resolveFieldInteractivity(formInteractivity, props.disabled, props.readOnly ?? props.readonly);
730
- const controller = new core.ColorPickerController(String(field.value.value || "#7c3aed"));
738
+ const controller = new core.ColorPickerController(String(field.value.value || "#1d2129"));
731
739
  const state = controller.getState();
732
740
  const commit = (value) => {
733
741
  if (interactivity.disabled || interactivity.readOnly)
@@ -1466,6 +1474,152 @@ const ClassTextarea = /*#__PURE__*/ vue.defineComponent({
1466
1474
  };
1467
1475
  },
1468
1476
  });
1477
+ function getVueTextareaMetrics(element) {
1478
+ const computed = window.getComputedStyle(element);
1479
+ const fontSize = Number.parseFloat(computed.fontSize) || 14;
1480
+ const lineHeight = Number.parseFloat(computed.lineHeight) || fontSize * 1.5;
1481
+ const paddingY = (Number.parseFloat(computed.paddingTop) || 0) +
1482
+ (Number.parseFloat(computed.paddingBottom) || 0);
1483
+ const borderY = (Number.parseFloat(computed.borderTopWidth) || 0) +
1484
+ (Number.parseFloat(computed.borderBottomWidth) || 0);
1485
+ return { borderY, lineHeight, paddingY };
1486
+ }
1487
+ const ClassChatTextarea = /*#__PURE__*/ vue.defineComponent({
1488
+ name: "ClassChatTextarea",
1489
+ inheritAttrs: false,
1490
+ props: {
1491
+ className: { type: String, default: "cc-chat-textarea" },
1492
+ clearable: { type: Boolean, default: true },
1493
+ clearIcon: {
1494
+ type: null,
1495
+ default: () => classIcon("x"),
1496
+ },
1497
+ clearLabel: {
1498
+ type: String,
1499
+ default: () => core.getClassComponentsLocale().inputClearLabel,
1500
+ },
1501
+ defaultValue: { type: String, default: "" },
1502
+ disabled: optionalBooleanProp(),
1503
+ maxRows: { type: Number, default: 3 },
1504
+ minRows: { type: Number, default: 1 },
1505
+ modelValue: String,
1506
+ placeholder: String,
1507
+ readOnly: optionalBooleanProp(),
1508
+ readonly: optionalBooleanProp(),
1509
+ textareaClass: { type: String, default: "cc-chat-textarea__control" },
1510
+ textareaStyle: Object,
1511
+ value: String,
1512
+ },
1513
+ emits: ["change", "input", "update:modelValue", "update:value"],
1514
+ setup(props, { attrs, emit, expose }) {
1515
+ const textareaRef = vue.ref(null);
1516
+ const controller = new core.ChatTextareaController({
1517
+ maxRows: props.maxRows,
1518
+ minRows: props.minRows,
1519
+ value: props.modelValue ?? props.value ?? props.defaultValue,
1520
+ });
1521
+ const state = vue.ref(controller.getState());
1522
+ const controlled = vue.computed(() => props.modelValue !== undefined || props.value !== undefined);
1523
+ let resizeObserver;
1524
+ const resize = () => {
1525
+ const element = textareaRef.value;
1526
+ if (!element || typeof window === "undefined")
1527
+ return;
1528
+ const { borderY, lineHeight, paddingY } = getVueTextareaMetrics(element);
1529
+ const minHeight = lineHeight * state.value.minRows + paddingY + borderY;
1530
+ const maxHeight = lineHeight * state.value.maxRows + paddingY + borderY;
1531
+ element.style.height = "auto";
1532
+ const nextHeight = Math.min(Math.max(element.scrollHeight, minHeight), maxHeight);
1533
+ element.style.height = `${nextHeight}px`;
1534
+ element.style.overflowY =
1535
+ element.scrollHeight > maxHeight + 1 ? "auto" : "hidden";
1536
+ };
1537
+ const syncState = () => {
1538
+ state.value = controller.update({
1539
+ maxRows: props.maxRows,
1540
+ minRows: props.minRows,
1541
+ value: controlled.value
1542
+ ? (props.modelValue ?? props.value ?? "")
1543
+ : state.value.value,
1544
+ });
1545
+ vue.nextTick(resize);
1546
+ };
1547
+ vue.watch(() => [props.maxRows, props.minRows, props.modelValue, props.value], syncState);
1548
+ vue.onMounted(() => {
1549
+ resize();
1550
+ if (typeof ResizeObserver === "undefined" || !textareaRef.value)
1551
+ return;
1552
+ resizeObserver = new ResizeObserver(resize);
1553
+ resizeObserver.observe(textareaRef.value);
1554
+ });
1555
+ vue.onBeforeUnmount(() => {
1556
+ resizeObserver?.disconnect();
1557
+ });
1558
+ const commit = (nextValue, event) => {
1559
+ const nextState = controller.setValue(nextValue);
1560
+ if (!controlled.value)
1561
+ state.value = nextState;
1562
+ emit("update:modelValue", nextValue);
1563
+ emit("update:value", nextValue);
1564
+ emit("input", nextValue, event);
1565
+ emit("change", nextValue, event);
1566
+ vue.nextTick(resize);
1567
+ };
1568
+ expose({
1569
+ blur: () => textareaRef.value?.blur(),
1570
+ focus: () => textareaRef.value?.focus(),
1571
+ getElement: () => textareaRef.value,
1572
+ });
1573
+ return () => {
1574
+ const locked = props.disabled || props.readOnly || props.readonly;
1575
+ const currentValue = controlled.value
1576
+ ? (props.modelValue ?? props.value ?? "")
1577
+ : state.value.value;
1578
+ const canClear = props.clearable && currentValue !== "" && !locked;
1579
+ return vue.h("div", {
1580
+ class: props.className,
1581
+ "data-disabled": Boolean(props.disabled),
1582
+ "data-readonly": Boolean(props.readOnly || props.readonly),
1583
+ "data-scrollable": currentValue.length > 0,
1584
+ }, [
1585
+ vue.h("textarea", {
1586
+ ...attrs,
1587
+ class: [
1588
+ props.textareaClass,
1589
+ canClear ? "cc-chat-textarea__control--clearable" : "",
1590
+ ],
1591
+ disabled: props.disabled,
1592
+ placeholder: props.placeholder,
1593
+ readonly: props.readOnly || props.readonly,
1594
+ ref: textareaRef,
1595
+ rows: state.value.minRows,
1596
+ style: {
1597
+ "--cc-chat-textarea-max-rows": state.value.maxRows,
1598
+ "--cc-chat-textarea-min-rows": state.value.minRows,
1599
+ ...(props.textareaStyle ?? {}),
1600
+ },
1601
+ value: currentValue,
1602
+ onInput: (event) => {
1603
+ if (locked)
1604
+ return;
1605
+ commit(event.currentTarget.value, event);
1606
+ },
1607
+ }),
1608
+ canClear
1609
+ ? vue.h("button", {
1610
+ "aria-label": props.clearLabel,
1611
+ class: "cc-chat-textarea__clear",
1612
+ type: "button",
1613
+ onClick: (event) => {
1614
+ commit("", event);
1615
+ textareaRef.value?.focus();
1616
+ },
1617
+ }, props.clearIcon)
1618
+ : null,
1619
+ ]);
1620
+ };
1621
+ },
1622
+ });
1469
1623
  const ClassVerificationCode = /*#__PURE__*/ vue.defineComponent({
1470
1624
  name: "ClassVerificationCode",
1471
1625
  inheritAttrs: false,
@@ -3773,6 +3927,367 @@ const ClassTiltCard = /*#__PURE__*/ vue.defineComponent({
3773
3927
  ]);
3774
3928
  },
3775
3929
  });
3930
+ const ClassOrbitalSphere = /*#__PURE__*/ vue.defineComponent({
3931
+ name: "ClassOrbitalSphere",
3932
+ inheritAttrs: false,
3933
+ props: {
3934
+ animated: { type: Boolean, default: true },
3935
+ className: { type: String, default: "cc-orbital-sphere" },
3936
+ cycleDuration: { type: Number, default: 12000 },
3937
+ depth: { type: Number, default: 0.72 },
3938
+ disabled: { type: Boolean, default: false },
3939
+ duration: { type: Number, default: 9000 },
3940
+ itemClass: { type: String, default: "cc-orbital-sphere__item" },
3941
+ itemContentClass: {
3942
+ type: String,
3943
+ default: "cc-orbital-sphere__item-content",
3944
+ },
3945
+ itemSize: { type: Number, default: 72 },
3946
+ items: {
3947
+ type: Array,
3948
+ default: undefined,
3949
+ },
3950
+ radius: { type: [Number, String], default: "50%" },
3951
+ shellClass: { type: String, default: "cc-orbital-sphere__shell" },
3952
+ size: { type: [Number, String], default: "360px" },
3953
+ spread: { type: Number, default: 0.86 },
3954
+ stageClass: { type: String, default: "cc-orbital-sphere__stage" },
3955
+ visibleCount: { type: Number, default: 10 },
3956
+ },
3957
+ emits: ["item-click"],
3958
+ setup(props, { attrs, emit, slots }) {
3959
+ return () => {
3960
+ const state = new core.OrbitalSphereController({
3961
+ animated: props.animated,
3962
+ cycleDuration: props.cycleDuration,
3963
+ depth: props.depth,
3964
+ disabled: props.disabled,
3965
+ duration: props.duration,
3966
+ itemSize: props.itemSize,
3967
+ items: props.items,
3968
+ radius: props.radius,
3969
+ size: props.size,
3970
+ spread: props.spread,
3971
+ visibleCount: props.visibleCount,
3972
+ }).getState();
3973
+ return vue.h("div", {
3974
+ ...attrs,
3975
+ class: [props.className, attrs.class],
3976
+ "data-animated": state.animated ? "true" : "false",
3977
+ "data-disabled": state.disabled ? "true" : "false",
3978
+ "data-overflow": state.items.length > state.visibleCount ? "true" : "false",
3979
+ style: [state.styleVars, attrs.style],
3980
+ }, [
3981
+ vue.h("span", { "aria-hidden": "true", class: props.shellClass }),
3982
+ vue.h("div", { class: props.stageClass }, state.items.map((item) => vue.h("button", {
3983
+ "aria-label": item.label,
3984
+ class: props.itemClass,
3985
+ "data-tone": item.tone,
3986
+ disabled: state.disabled,
3987
+ key: item.id,
3988
+ onClick: (event) => emit("item-click", item, event),
3989
+ style: [
3990
+ {
3991
+ "--cc-orbital-index": item.index,
3992
+ },
3993
+ item.styleVars,
3994
+ ],
3995
+ type: "button",
3996
+ }, [
3997
+ vue.h("span", { class: props.itemContentClass }, slots.item?.({ index: item.index, item }) ?? item.content),
3998
+ ]))),
3999
+ ]);
4000
+ };
4001
+ },
4002
+ });
4003
+ const ClassHeightTransition = /*#__PURE__*/ vue.defineComponent({
4004
+ name: "ClassHeightTransition",
4005
+ inheritAttrs: false,
4006
+ props: {
4007
+ className: { type: String, default: "cc-height-transition" },
4008
+ contentClass: { type: String, default: "cc-height-transition__content" },
4009
+ duration: { type: Number, default: 220 },
4010
+ easing: { type: String, default: "cubic-bezier(0.22, 0.8, 0.28, 1)" },
4011
+ expanded: { type: Boolean, default: false },
4012
+ mode: {
4013
+ type: String,
4014
+ default: "auto",
4015
+ },
4016
+ },
4017
+ setup(props, { attrs, slots }) {
4018
+ const contentRef = vue.ref(null);
4019
+ const height = vue.ref(0);
4020
+ const controller = new core.HeightTransitionController({
4021
+ duration: props.duration,
4022
+ easing: props.easing,
4023
+ expanded: props.expanded,
4024
+ mode: props.mode,
4025
+ });
4026
+ const state = vue.ref(controller.getState());
4027
+ let observer;
4028
+ const measure = () => {
4029
+ height.value = contentRef.value?.scrollHeight ?? 0;
4030
+ };
4031
+ vue.watch(() => [props.duration, props.easing, props.expanded, props.mode], () => {
4032
+ state.value = controller.update({
4033
+ duration: props.duration,
4034
+ easing: props.easing,
4035
+ expanded: props.expanded,
4036
+ mode: props.mode,
4037
+ });
4038
+ vue.nextTick(measure);
4039
+ }, { immediate: true });
4040
+ vue.onMounted(() => {
4041
+ measure();
4042
+ if (typeof ResizeObserver !== "undefined" && contentRef.value) {
4043
+ observer = new ResizeObserver(measure);
4044
+ observer.observe(contentRef.value);
4045
+ }
4046
+ });
4047
+ vue.onBeforeUnmount(() => observer?.disconnect());
4048
+ return () => vue.h("div", {
4049
+ ...attrs,
4050
+ class: props.className,
4051
+ "data-expanded": state.value.expanded,
4052
+ "data-mode": state.value.mode,
4053
+ style: [
4054
+ attrs.style,
4055
+ {
4056
+ "--cc-height-transition-duration": `${state.value.duration}ms`,
4057
+ "--cc-height-transition-easing": state.value.easing,
4058
+ "--cc-height-transition-height": `${height.value}px`,
4059
+ },
4060
+ ],
4061
+ }, [
4062
+ vue.h("div", { ref: contentRef, class: props.contentClass }, slots.default?.()),
4063
+ ]);
4064
+ },
4065
+ });
4066
+ const ClassCodePreview = /*#__PURE__*/ vue.defineComponent({
4067
+ name: "ClassCodePreview",
4068
+ inheritAttrs: false,
4069
+ props: {
4070
+ className: { type: String, default: "cc-code-preview" },
4071
+ code: { type: String, required: true },
4072
+ defaultExpanded: { type: Boolean, default: false },
4073
+ language: { type: String, default: "tsx" },
4074
+ placement: {
4075
+ type: String,
4076
+ default: "auto",
4077
+ },
4078
+ strategy: {
4079
+ type: String,
4080
+ default: "fixed",
4081
+ },
4082
+ title: { type: String, default: "示例源码" },
4083
+ transitionDuration: { type: Number, default: 220 },
4084
+ transitionEasing: {
4085
+ type: String,
4086
+ default: "cubic-bezier(0.22, 0.8, 0.28, 1)",
4087
+ },
4088
+ },
4089
+ emits: ["copy"],
4090
+ setup(props, { attrs, emit, slots }) {
4091
+ const rootRef = vue.ref(null);
4092
+ const panelRef = vue.ref(null);
4093
+ const panelStyle = vue.ref({});
4094
+ const controller = new core.CodePreviewController({
4095
+ code: props.code,
4096
+ defaultExpanded: props.defaultExpanded,
4097
+ language: props.language,
4098
+ placement: props.placement,
4099
+ title: props.title,
4100
+ });
4101
+ const state = vue.ref(controller.getState());
4102
+ let resetTimer;
4103
+ const sync = () => {
4104
+ state.value = controller.update({
4105
+ code: props.code,
4106
+ language: props.language,
4107
+ placement: props.placement,
4108
+ title: props.title,
4109
+ });
4110
+ };
4111
+ const resolvePlacement = (estimate = false) => {
4112
+ const rect = rootRef.value?.getBoundingClientRect();
4113
+ const panel = panelRef.value;
4114
+ if (!rect || (!panel && !estimate) || typeof window === "undefined")
4115
+ return;
4116
+ const padding = 10;
4117
+ const gap = 10;
4118
+ const viewportWidth = document.documentElement.clientWidth || window.innerWidth;
4119
+ const viewportHeight = document.documentElement.clientHeight || window.innerHeight;
4120
+ const maxPanelHeight = Math.max(160, viewportHeight - padding * 2);
4121
+ const maxPanelWidth = Math.max(160, viewportWidth - padding * 2);
4122
+ const minPanelHeight = Math.min(160, maxPanelHeight);
4123
+ const panelContent = panel?.querySelector("pre");
4124
+ const measuredPanelHeight = Math.max(panel?.offsetHeight ?? 0, panel?.scrollHeight ?? 0, panelContent?.scrollHeight ?? 0, estimate ? 420 : 0);
4125
+ const preferredPanelHeight = Math.min(Math.max(160, measuredPanelHeight || 420), maxPanelHeight);
4126
+ const panelWidth = Math.min(Math.max(rect.width, panel?.offsetWidth || 720), maxPanelWidth);
4127
+ const availableBelow = Math.max(minPanelHeight, viewportHeight - rect.bottom - gap - padding);
4128
+ const availableAbove = Math.max(minPanelHeight, rect.top - gap - padding);
4129
+ const placementHeight = Math.min(preferredPanelHeight, Math.max(availableBelow, availableAbove));
4130
+ const nextState = controller.resolvePlacement({
4131
+ anchorBottom: rect.bottom,
4132
+ anchorLeft: rect.left,
4133
+ anchorRight: rect.right,
4134
+ anchorTop: rect.top,
4135
+ panelHeight: placementHeight,
4136
+ panelWidth,
4137
+ viewportHeight,
4138
+ viewportWidth,
4139
+ });
4140
+ state.value = nextState;
4141
+ if (props.strategy !== "fixed") {
4142
+ panelStyle.value = {};
4143
+ return;
4144
+ }
4145
+ const clamp = (value, min, max) => Math.min(Math.max(min, value), max);
4146
+ const width = panelWidth;
4147
+ const maxLeft = Math.max(padding, viewportWidth - width - padding);
4148
+ const viewportPanelHeight = Math.min(preferredPanelHeight, maxPanelHeight);
4149
+ const maxTop = Math.max(padding, viewportHeight - viewportPanelHeight - padding);
4150
+ let left = clamp(rect.left, padding, maxLeft);
4151
+ let top = rect.bottom + gap;
4152
+ let maxHeight = Math.min(preferredPanelHeight, Math.max(minPanelHeight, viewportHeight - top - padding));
4153
+ let transformOrigin = "top left";
4154
+ if (nextState.resolvedPlacement === "top") {
4155
+ maxHeight = Math.min(preferredPanelHeight, availableAbove);
4156
+ top = Math.max(padding, rect.top - gap - maxHeight);
4157
+ transformOrigin = "bottom left";
4158
+ }
4159
+ else if (nextState.resolvedPlacement === "right") {
4160
+ left = clamp(rect.right + gap, padding, maxLeft);
4161
+ top = clamp(rect.top, padding, maxTop);
4162
+ maxHeight = viewportPanelHeight;
4163
+ transformOrigin = "top left";
4164
+ }
4165
+ else if (nextState.resolvedPlacement === "left") {
4166
+ left = clamp(rect.left - width - gap, padding, maxLeft);
4167
+ top = clamp(rect.top, padding, maxTop);
4168
+ maxHeight = viewportPanelHeight;
4169
+ transformOrigin = "top right";
4170
+ }
4171
+ panelStyle.value = {
4172
+ left: `${left}px`,
4173
+ maxHeight: `${maxHeight}px`,
4174
+ top: `${top}px`,
4175
+ transformOrigin,
4176
+ width: `${width}px`,
4177
+ };
4178
+ };
4179
+ const resolvePlacementFromViewport = () => resolvePlacement();
4180
+ const copy = async () => {
4181
+ if (typeof navigator !== "undefined") {
4182
+ await navigator.clipboard?.writeText(props.code);
4183
+ }
4184
+ state.value = controller.copied();
4185
+ emit("copy", props.code);
4186
+ window.clearTimeout(resetTimer);
4187
+ resetTimer = window.setTimeout(() => {
4188
+ state.value = controller.resetCopied();
4189
+ }, 1200);
4190
+ };
4191
+ vue.watch(() => [props.code, props.language, props.placement, props.title], () => {
4192
+ sync();
4193
+ vue.nextTick(resolvePlacement);
4194
+ });
4195
+ vue.watch(() => state.value.expanded, () => vue.nextTick(resolvePlacement));
4196
+ vue.watch(() => state.value.expanded, (expanded, _previous, onCleanup) => {
4197
+ if (!expanded || typeof document === "undefined")
4198
+ return;
4199
+ const close = () => {
4200
+ panelStyle.value = {};
4201
+ state.value = controller.close();
4202
+ };
4203
+ const closeOnOutside = (event) => {
4204
+ const target = event.target;
4205
+ if (target &&
4206
+ (rootRef.value?.contains(target) ||
4207
+ panelRef.value?.contains(target)))
4208
+ return;
4209
+ close();
4210
+ };
4211
+ const closeOnEscape = (event) => {
4212
+ if (event.key === "Escape")
4213
+ close();
4214
+ };
4215
+ document.addEventListener("pointerdown", closeOnOutside, true);
4216
+ document.addEventListener("keydown", closeOnEscape, true);
4217
+ onCleanup(() => {
4218
+ document.removeEventListener("pointerdown", closeOnOutside, true);
4219
+ document.removeEventListener("keydown", closeOnEscape, true);
4220
+ });
4221
+ });
4222
+ vue.onMounted(() => {
4223
+ resolvePlacement();
4224
+ window.addEventListener("resize", resolvePlacementFromViewport);
4225
+ window.addEventListener("scroll", resolvePlacementFromViewport, true);
4226
+ });
4227
+ vue.onBeforeUnmount(() => {
4228
+ window.clearTimeout(resetTimer);
4229
+ window.removeEventListener("resize", resolvePlacementFromViewport);
4230
+ window.removeEventListener("scroll", resolvePlacementFromViewport, true);
4231
+ });
4232
+ return () => {
4233
+ const panel = vue.h("div", {
4234
+ ref: panelRef,
4235
+ class: "cc-code-preview__panel",
4236
+ "data-placement": state.value.resolvedPlacement,
4237
+ "data-strategy": props.strategy,
4238
+ "data-expanded": state.value.expanded,
4239
+ style: panelStyle.value,
4240
+ }, [
4241
+ vue.h(ClassHeightTransition, {
4242
+ className: "cc-height-transition cc-code-preview__transition",
4243
+ contentClass: "cc-height-transition__content cc-code-preview__panel-content",
4244
+ duration: props.transitionDuration,
4245
+ easing: props.transitionEasing,
4246
+ expanded: state.value.expanded,
4247
+ mode: "auto",
4248
+ }, {
4249
+ default: () => vue.h("pre", null, [vue.h("code", null, state.value.code)]),
4250
+ }),
4251
+ ]);
4252
+ return vue.h("div", {
4253
+ ...attrs,
4254
+ ref: rootRef,
4255
+ class: props.className,
4256
+ "data-expanded": state.value.expanded,
4257
+ "data-placement": state.value.resolvedPlacement,
4258
+ "data-strategy": props.strategy,
4259
+ }, [
4260
+ vue.h("div", { class: "cc-code-preview__bar" }, [
4261
+ vue.h("div", { class: "cc-code-preview__meta" }, [
4262
+ vue.h("span", { class: "cc-code-preview__title" }, [
4263
+ slots.title?.() ?? props.title,
4264
+ ]),
4265
+ vue.h("span", { class: "cc-code-preview__lang" }, state.value.language),
4266
+ ]),
4267
+ vue.h("div", { class: "cc-code-preview__actions" }, [
4268
+ vue.h("button", {
4269
+ type: "button",
4270
+ onClick: () => {
4271
+ const nextState = controller.toggle();
4272
+ state.value = nextState;
4273
+ if (!nextState.expanded) {
4274
+ panelStyle.value = {};
4275
+ return;
4276
+ }
4277
+ resolvePlacement(true);
4278
+ window.requestAnimationFrame(() => resolvePlacement());
4279
+ },
4280
+ }, state.value.expanded ? "收起" : "源码"),
4281
+ vue.h("button", { type: "button", onClick: copy }, state.value.copied ? "已复制" : "复制"),
4282
+ ]),
4283
+ ]),
4284
+ props.strategy === "fixed"
4285
+ ? vue.h(vue.Teleport, { to: "body" }, panel)
4286
+ : panel,
4287
+ ]);
4288
+ };
4289
+ },
4290
+ });
3776
4291
  function optionalDependencyError(packageName, featureName, fallbackName, cause) {
3777
4292
  const detail = cause instanceof Error ? ` Original error: ${cause.message}` : "";
3778
4293
  return new Error(`${featureName} requires optional dependency "${packageName}". Install it or provide ${fallbackName} from a CDN/global fallback.${detail}`);
@@ -5629,7 +6144,7 @@ const ClassSignature = /*#__PURE__*/ vue.defineComponent({
5629
6144
  labelClass: { type: String, default: "cc-field__label" },
5630
6145
  lineWidth: { type: Number, default: 3 },
5631
6146
  name: String,
5632
- penColor: { type: String, default: "#111827" },
6147
+ penColor: { type: String, default: "#1d2129" },
5633
6148
  readOnly: optionalBooleanProp(),
5634
6149
  readonly: optionalBooleanProp(),
5635
6150
  rules: Array,
@@ -6036,6 +6551,28 @@ function getRectOverlapRatio(source, target) {
6036
6551
  const sourceArea = Math.max(1, source.width * source.height);
6037
6552
  return (width * height) / sourceArea;
6038
6553
  }
6554
+ function readDragDropPreviewStyleVars(element) {
6555
+ if (!element || typeof window === "undefined")
6556
+ return {};
6557
+ const styles = window.getComputedStyle(element);
6558
+ const read = (name) => styles.getPropertyValue(name).trim();
6559
+ const slotDraggingBackground = read("--cc-drag-drop-slot-dragging-background");
6560
+ const slotDraggingBorderColor = read("--cc-drag-drop-slot-dragging-border-color");
6561
+ const previewBackground = read("--cc-drag-drop-preview-background");
6562
+ const previewBorderColor = read("--cc-drag-drop-preview-border-color");
6563
+ const values = {
6564
+ "--cc-drag-drop-preview-background": previewBackground && !previewBackground.includes("var(")
6565
+ ? previewBackground
6566
+ : slotDraggingBackground,
6567
+ "--cc-drag-drop-preview-border-color": previewBorderColor && !previewBorderColor.includes("var(")
6568
+ ? previewBorderColor
6569
+ : slotDraggingBorderColor,
6570
+ "--cc-drag-drop-preview-color": read("--cc-drag-drop-preview-color"),
6571
+ "--cc-drag-drop-preview-shadow": read("--cc-drag-drop-preview-shadow"),
6572
+ "--cc-drag-drop-motion-duration": read("--cc-drag-drop-motion-duration"),
6573
+ };
6574
+ return Object.fromEntries(Object.entries(values).filter(([, value]) => value.length > 0));
6575
+ }
6039
6576
  const ClassDragDropBoard = /*#__PURE__*/ vue.defineComponent({
6040
6577
  name: "ClassDragDropBoard",
6041
6578
  inheritAttrs: false,
@@ -6288,6 +6825,7 @@ const ClassDragDropBoard = /*#__PURE__*/ vue.defineComponent({
6288
6825
  offsetY: event.clientY - rect.top,
6289
6826
  originX: rect.left,
6290
6827
  originY: rect.top,
6828
+ styleVars: readDragDropPreviewStyleVars(boardRef.value),
6291
6829
  width: rect.width,
6292
6830
  x: rect.left,
6293
6831
  y: rect.top,
@@ -6343,6 +6881,7 @@ const ClassDragDropBoard = /*#__PURE__*/ vue.defineComponent({
6343
6881
  "data-returning": preview.value.returning,
6344
6882
  ref: previewRef,
6345
6883
  style: {
6884
+ ...preview.value.styleVars,
6346
6885
  height: `${preview.value.height}px`,
6347
6886
  transform: `translate3d(${preview.value.x}px, ${preview.value.y}px, 0)`,
6348
6887
  width: `${preview.value.width}px`,
@@ -7705,6 +8244,8 @@ const ClassMasonryVirtualList = /*#__PURE__*/ vue.defineComponent({
7705
8244
  };
7706
8245
  },
7707
8246
  });
8247
+ const CHAT_PREPEND_MOMENTUM_LOCK_MS = 420;
8248
+ const CHAT_PREPEND_STABILIZE_FRAMES = 24;
7708
8249
  const ClassChatVirtualList = /*#__PURE__*/ vue.defineComponent({
7709
8250
  name: "ClassChatVirtualList",
7710
8251
  inheritAttrs: false,
@@ -7779,7 +8320,7 @@ const ClassChatVirtualList = /*#__PURE__*/ vue.defineComponent({
7779
8320
  },
7780
8321
  topLoadingContent: {
7781
8322
  type: String,
7782
- default: "正在加载历史消息...",
8323
+ default: "",
7783
8324
  },
7784
8325
  pullUpLoading: {
7785
8326
  type: Boolean,
@@ -7822,6 +8363,7 @@ const ClassChatVirtualList = /*#__PURE__*/ vue.defineComponent({
7822
8363
  let bottomFrame;
7823
8364
  let bottomTimer;
7824
8365
  let prependFrame;
8366
+ let prependStabilizeFrame;
7825
8367
  let prependTimer;
7826
8368
  let topLoadingFallbackTimer;
7827
8369
  let topLoadingMutationPending = false;
@@ -7897,14 +8439,68 @@ const ClassChatVirtualList = /*#__PURE__*/ vue.defineComponent({
7897
8439
  return;
7898
8440
  releaseTopLoadingLock();
7899
8441
  };
7900
- const clearPendingPrependAnchor = () => {
8442
+ const clearPendingPrependAnchor = (force = false) => {
8443
+ const pendingAnchor = pendingPrependAnchor.value;
8444
+ if (!force && pendingAnchor) {
8445
+ const remaining = pendingAnchor.releaseAt - Date.now();
8446
+ if (remaining > 0) {
8447
+ if (prependTimer !== undefined)
8448
+ window.clearTimeout(prependTimer);
8449
+ prependTimer = window.setTimeout(() => {
8450
+ clearPendingPrependAnchor(true);
8451
+ }, remaining);
8452
+ schedulePrependStabilization();
8453
+ return;
8454
+ }
8455
+ }
7901
8456
  pendingPrependAnchor.value = null;
8457
+ if (prependStabilizeFrame !== undefined) {
8458
+ window.cancelAnimationFrame(prependStabilizeFrame);
8459
+ prependStabilizeFrame = undefined;
8460
+ }
7902
8461
  if (prependTimer !== undefined) {
7903
8462
  window.clearTimeout(prependTimer);
7904
8463
  prependTimer = undefined;
7905
8464
  }
7906
8465
  maybeReleaseTopLoadingLock();
7907
8466
  };
8467
+ const applyPendingPrependAnchor = () => {
8468
+ const pendingAnchor = pendingPrependAnchor.value;
8469
+ const viewport = viewportRef.value;
8470
+ if (!pendingAnchor || !viewport)
8471
+ return false;
8472
+ const keys = getKeys();
8473
+ const anchorIndex = keys.findIndex((itemKey) => Object.is(itemKey, pendingAnchor.anchorKey));
8474
+ const nextScrollTop = anchorIndex >= 0
8475
+ ? Math.max(0, listController.getItem(anchorIndex).start -
8476
+ pendingAnchor.anchorOffset)
8477
+ : pendingAnchor.targetScrollTop;
8478
+ viewport.scrollTop = nextScrollTop;
8479
+ scrollOffset.value = nextScrollTop;
8480
+ previousScrollTop.value = nextScrollTop;
8481
+ return true;
8482
+ };
8483
+ const schedulePrependStabilization = () => {
8484
+ if (prependStabilizeFrame !== undefined) {
8485
+ window.cancelAnimationFrame(prependStabilizeFrame);
8486
+ }
8487
+ let remainingFrames = CHAT_PREPEND_STABILIZE_FRAMES;
8488
+ const stabilize = () => {
8489
+ const pendingAnchor = pendingPrependAnchor.value;
8490
+ if (!pendingAnchor) {
8491
+ prependStabilizeFrame = undefined;
8492
+ return;
8493
+ }
8494
+ applyPendingPrependAnchor();
8495
+ remainingFrames -= 1;
8496
+ if (remainingFrames <= 0 && pendingAnchor.releaseAt <= Date.now()) {
8497
+ prependStabilizeFrame = undefined;
8498
+ return;
8499
+ }
8500
+ prependStabilizeFrame = window.requestAnimationFrame(stabilize);
8501
+ };
8502
+ prependStabilizeFrame = window.requestAnimationFrame(stabilize);
8503
+ };
7908
8504
  const scheduleTopLoadingFallback = () => {
7909
8505
  if (topLoadingFallbackTimer !== undefined) {
7910
8506
  window.clearTimeout(topLoadingFallbackTimer);
@@ -8016,8 +8612,12 @@ const ClassChatVirtualList = /*#__PURE__*/ vue.defineComponent({
8016
8612
  anchorOffset: previousAnchor.offset,
8017
8613
  measuredKeys: new Set(),
8018
8614
  prependKeys: new Set(keys.slice(0, prependCount)),
8615
+ releaseAt: Date.now() + CHAT_PREPEND_MOMENTUM_LOCK_MS,
8616
+ targetScrollTop: nextScrollTop,
8019
8617
  }
8020
8618
  : null;
8619
+ if (pendingPrependAnchor.value)
8620
+ schedulePrependStabilization();
8021
8621
  if (prependFrame !== undefined)
8022
8622
  window.cancelAnimationFrame(prependFrame);
8023
8623
  if (prependTimer !== undefined)
@@ -8139,6 +8739,8 @@ const ClassChatVirtualList = /*#__PURE__*/ vue.defineComponent({
8139
8739
  window.clearTimeout(bottomTimer);
8140
8740
  if (prependFrame !== undefined)
8141
8741
  window.cancelAnimationFrame(prependFrame);
8742
+ if (prependStabilizeFrame !== undefined)
8743
+ window.cancelAnimationFrame(prependStabilizeFrame);
8142
8744
  if (prependTimer !== undefined)
8143
8745
  window.clearTimeout(prependTimer);
8144
8746
  if (topLoadingFallbackTimer !== undefined)
@@ -8152,6 +8754,12 @@ const ClassChatVirtualList = /*#__PURE__*/ vue.defineComponent({
8152
8754
  if (!(element instanceof HTMLElement))
8153
8755
  return;
8154
8756
  const measure = () => {
8757
+ const keys = getKeys();
8758
+ const oldKeys = previousKeys.value;
8759
+ const hasPendingKeySync = oldKeys.length !== keys.length ||
8760
+ oldKeys.some((itemKey, keyIndex) => !Object.is(itemKey, keys[keyIndex]));
8761
+ if (!pendingPrependAnchor.value && hasPendingKeySync)
8762
+ return;
8155
8763
  const viewport = viewportRef.value;
8156
8764
  const oldTotal = listController.getTotalSize();
8157
8765
  const oldItem = listController.getItem(index);
@@ -8165,17 +8773,19 @@ const ClassChatVirtualList = /*#__PURE__*/ vue.defineComponent({
8165
8773
  if (pendingAnchor) {
8166
8774
  if (pendingAnchor.prependKeys.has(key))
8167
8775
  pendingAnchor.measuredKeys.add(key);
8168
- const keys = getKeys();
8169
8776
  const anchorIndex = keys.findIndex((itemKey) => Object.is(itemKey, pendingAnchor.anchorKey));
8170
8777
  if (anchorIndex >= 0) {
8171
8778
  const anchorItem = listController.getItem(anchorIndex);
8172
8779
  const nextItem = listController.getItem(index);
8173
8780
  const delta = nextItem.size - oldItem.size;
8174
- viewport.scrollTop = Math.max(0, index < anchorIndex && delta !== 0
8781
+ const nextScrollTop = Math.max(0, index < anchorIndex && delta !== 0
8175
8782
  ? oldScrollTop + delta
8176
8783
  : anchorItem.start - pendingAnchor.anchorOffset);
8177
- scrollOffset.value = viewport.scrollTop;
8178
- previousScrollTop.value = viewport.scrollTop;
8784
+ pendingAnchor.targetScrollTop = nextScrollTop;
8785
+ viewport.scrollTop = nextScrollTop;
8786
+ scrollOffset.value = nextScrollTop;
8787
+ previousScrollTop.value = nextScrollTop;
8788
+ schedulePrependStabilization();
8179
8789
  }
8180
8790
  if (pendingAnchor.measuredKeys.size >= pendingAnchor.prependKeys.size) {
8181
8791
  clearPendingPrependAnchor();
@@ -8213,18 +8823,24 @@ const ClassChatVirtualList = /*#__PURE__*/ vue.defineComponent({
8213
8823
  "data-top-loading": topLoadingPending.value ? "true" : undefined,
8214
8824
  style: { "--cc-chat-virtual-list-height": resolvedHeight },
8215
8825
  }, [
8216
- vue.h("div", {
8217
- "aria-hidden": topLoadingPending.value ? undefined : "true",
8218
- class: props.topLoadingClass,
8219
- "data-active": topLoadingPending.value ? "true" : "false",
8220
- role: topLoadingPending.value ? "status" : undefined,
8221
- }, slots.topLoading?.({ loading: topLoadingPending.value }) ??
8222
- props.topLoadingContent),
8826
+ slots.topLoading?.({ loading: topLoadingPending.value }) ??
8827
+ vue.h(ClassLoading, {
8828
+ "aria-hidden": topLoadingPending.value ? undefined : "true",
8829
+ className: props.topLoadingClass,
8830
+ "data-active": topLoadingPending.value ? "true" : "false",
8831
+ role: topLoadingPending.value ? "status" : undefined,
8832
+ text: props.topLoadingContent,
8833
+ }),
8223
8834
  vue.h("div", {
8224
8835
  class: props.viewportClass,
8225
8836
  "data-top-loading": topLoadingPending.value ? "true" : undefined,
8226
8837
  ref: viewportRef,
8227
8838
  onScroll: (event) => {
8839
+ if (pendingPrependAnchor.value) {
8840
+ const stabilized = applyPendingPrependAnchor();
8841
+ if (stabilized)
8842
+ return;
8843
+ }
8228
8844
  const nextScrollTop = event.currentTarget
8229
8845
  .scrollTop;
8230
8846
  const viewport = event.currentTarget;
@@ -8606,6 +9222,117 @@ const ClassBreadcrumb = /*#__PURE__*/ vue.defineComponent({
8606
9222
  };
8607
9223
  },
8608
9224
  });
9225
+ function renderVueMenuItems(items, collapsed, slots, toggle, select) {
9226
+ return items.map((item) => {
9227
+ const hasChildren = item.children.length > 0;
9228
+ const icon = slots.icon?.({ item }) ??
9229
+ item.icon ??
9230
+ (collapsed ? item.label.slice(0, 1) : undefined);
9231
+ return vue.h("li", {
9232
+ class: "cc-menu__item",
9233
+ "data-active": item.isActive,
9234
+ "data-disabled": item.disabled,
9235
+ "data-expanded": item.expanded,
9236
+ "data-level": item.level,
9237
+ key: item.key,
9238
+ }, [
9239
+ vue.h("button", {
9240
+ "aria-current": item.isActive ? "page" : undefined,
9241
+ "aria-expanded": hasChildren ? item.expanded : undefined,
9242
+ class: "cc-menu__button",
9243
+ disabled: item.disabled,
9244
+ title: collapsed ? item.label : undefined,
9245
+ type: "button",
9246
+ onClick: () => {
9247
+ if (hasChildren && !collapsed)
9248
+ toggle(item.key);
9249
+ select(item.key, item);
9250
+ },
9251
+ }, [
9252
+ icon
9253
+ ? vue.h("span", { class: "cc-menu__icon", "aria-hidden": "true" }, icon)
9254
+ : null,
9255
+ vue.h("span", { class: "cc-menu__label" }, item.label),
9256
+ hasChildren ? classIcon("chevronDown", "cc-menu__arrow") : null,
9257
+ ]),
9258
+ hasChildren
9259
+ ? vue.h(ClassHeightTransition, {
9260
+ className: "cc-height-transition cc-menu__transition",
9261
+ contentClass: "cc-height-transition__content cc-menu__transition-content",
9262
+ duration: 180,
9263
+ expanded: !collapsed && item.expanded,
9264
+ mode: "grid",
9265
+ }, () => vue.h("ul", { class: "cc-menu__list cc-menu__list--child" }, renderVueMenuItems(item.children, collapsed, slots, toggle, select)))
9266
+ : null,
9267
+ ]);
9268
+ });
9269
+ }
9270
+ const ClassMenu = /*#__PURE__*/ vue.defineComponent({
9271
+ name: "ClassMenu",
9272
+ props: {
9273
+ activeKey: String,
9274
+ className: { type: String, default: "cc-menu" },
9275
+ collapsed: Boolean,
9276
+ collapsible: { type: Boolean, default: true },
9277
+ defaultExpandedKeys: {
9278
+ type: Array,
9279
+ default: () => [],
9280
+ },
9281
+ items: { type: Array, default: () => [] },
9282
+ },
9283
+ emits: ["collapsed-change", "select", "update:activeKey", "update:collapsed"],
9284
+ setup(props, { attrs, emit, slots }) {
9285
+ const controller = new core.MenuController({
9286
+ activeKey: props.activeKey,
9287
+ collapsed: props.collapsed,
9288
+ defaultExpandedKeys: props.defaultExpandedKeys,
9289
+ items: props.items,
9290
+ });
9291
+ const state = vue.ref(controller.getState());
9292
+ vue.watch(() => [
9293
+ props.activeKey,
9294
+ props.collapsed,
9295
+ props.defaultExpandedKeys,
9296
+ props.items,
9297
+ ], () => {
9298
+ state.value = controller.update({
9299
+ activeKey: props.activeKey,
9300
+ collapsed: props.collapsed,
9301
+ defaultExpandedKeys: props.defaultExpandedKeys,
9302
+ items: props.items,
9303
+ });
9304
+ }, { deep: true });
9305
+ const toggle = (key) => {
9306
+ state.value = controller.toggleExpanded(key);
9307
+ };
9308
+ const select = (key, item) => {
9309
+ state.value = controller.activate(key);
9310
+ emit("update:activeKey", key);
9311
+ emit("select", key, item);
9312
+ };
9313
+ const toggleCollapsed = () => {
9314
+ state.value = controller.toggleCollapsed();
9315
+ emit("update:collapsed", state.value.collapsed);
9316
+ emit("collapsed-change", state.value.collapsed);
9317
+ };
9318
+ return () => vue.h("nav", {
9319
+ ...attrs,
9320
+ class: props.className,
9321
+ "data-collapsed": state.value.collapsed,
9322
+ "data-collapsible": props.collapsible,
9323
+ }, [
9324
+ props.collapsible
9325
+ ? vue.h("button", {
9326
+ "aria-label": state.value.collapsed ? "展开菜单" : "收起菜单",
9327
+ class: "cc-menu__collapse",
9328
+ type: "button",
9329
+ onClick: toggleCollapsed,
9330
+ }, classIcon(state.value.collapsed ? "chevronRight" : "chevronLeft"))
9331
+ : null,
9332
+ vue.h("ul", { class: "cc-menu__list" }, renderVueMenuItems(state.value.items, state.value.collapsed, slots, toggle, select)),
9333
+ ]);
9334
+ },
9335
+ });
8609
9336
  const ClassPagination = /*#__PURE__*/ vue.defineComponent({
8610
9337
  name: "ClassPagination",
8611
9338
  props: {
@@ -8688,6 +9415,7 @@ const ClassPopconfirm = /*#__PURE__*/ vue.defineComponent({
8688
9415
  },
8689
9416
  closeOnEsc: { type: Boolean, default: true },
8690
9417
  closeOnOutsideClick: { type: Boolean, default: true },
9418
+ portal: { type: Boolean, default: true },
8691
9419
  },
8692
9420
  emits: ["confirm"],
8693
9421
  setup(props, { emit, slots }) {
@@ -8697,8 +9425,23 @@ const ClassPopconfirm = /*#__PURE__*/ vue.defineComponent({
8697
9425
  const visible = vue.ref(false);
8698
9426
  const phase = vue.ref("exit");
8699
9427
  const safePlacement = vue.ref(props.placement);
9428
+ const anchorStyle = vue.ref({
9429
+ height: 0,
9430
+ left: -9999,
9431
+ top: -9999,
9432
+ width: 0,
9433
+ });
8700
9434
  let exitTimer;
8701
9435
  const updatePlacement = () => {
9436
+ if (rootRef.value) {
9437
+ const rect = rootRef.value.getBoundingClientRect();
9438
+ anchorStyle.value = {
9439
+ height: rect.height,
9440
+ left: rect.left,
9441
+ top: rect.top,
9442
+ width: rect.width,
9443
+ };
9444
+ }
8702
9445
  if (!props.autoAdjust || !rootRef.value || !panelRef.value) {
8703
9446
  safePlacement.value = props.placement;
8704
9447
  return;
@@ -8728,7 +9471,8 @@ const ClassPopconfirm = /*#__PURE__*/ vue.defineComponent({
8728
9471
  };
8729
9472
  const closeOnOutside = (event) => {
8730
9473
  if (!props.closeOnOutsideClick ||
8731
- rootRef.value?.contains(event.target))
9474
+ rootRef.value?.contains(event.target) ||
9475
+ panelRef.value?.contains(event.target))
8732
9476
  return;
8733
9477
  hide();
8734
9478
  };
@@ -8755,34 +9499,58 @@ const ClassPopconfirm = /*#__PURE__*/ vue.defineComponent({
8755
9499
  vue.watch(() => props.placement, updatePlacement);
8756
9500
  return () => {
8757
9501
  const motion = resolveAnimation(props.animation, "scale");
8758
- return vue.h("span", {
8759
- class: ["cc-popconfirm", `cc-popconfirm--${safePlacement.value}`],
9502
+ const rootClass = [
9503
+ "cc-popconfirm",
9504
+ `cc-popconfirm--${safePlacement.value}`,
9505
+ ];
9506
+ const panelNode = visible.value
9507
+ ? vue.h("span", {
9508
+ class: "cc-popconfirm__panel",
9509
+ "data-state": phase.value,
9510
+ ref: panelRef,
9511
+ role: "dialog",
9512
+ }, [
9513
+ vue.h("span", null, props.content),
9514
+ vue.h("span", { class: "cc-popconfirm__actions" }, [
9515
+ vue.h("button", { type: "button", onClick: hide }, props.cancelText),
9516
+ vue.h("button", {
9517
+ type: "button",
9518
+ onClick: () => {
9519
+ emit("confirm");
9520
+ hide();
9521
+ },
9522
+ }, props.confirmText),
9523
+ ]),
9524
+ ])
9525
+ : null;
9526
+ const rootNode = vue.h("span", {
9527
+ class: rootClass,
8760
9528
  "data-animation": motion.name,
8761
9529
  ref: rootRef,
8762
9530
  style: animationStyle(motion),
8763
9531
  }, [
8764
9532
  vue.h("span", { onClick: show }, slots.default?.()),
8765
- visible.value
8766
- ? vue.h("span", {
8767
- class: "cc-popconfirm__panel",
8768
- "data-state": phase.value,
8769
- ref: panelRef,
8770
- role: "dialog",
8771
- }, [
8772
- vue.h("span", null, props.content),
8773
- vue.h("span", { class: "cc-popconfirm__actions" }, [
8774
- vue.h("button", { type: "button", onClick: hide }, props.cancelText),
8775
- vue.h("button", {
8776
- type: "button",
8777
- onClick: () => {
8778
- emit("confirm");
8779
- hide();
8780
- },
8781
- }, props.confirmText),
8782
- ]),
8783
- ])
8784
- : null,
9533
+ props.portal ? null : panelNode,
8785
9534
  ]);
9535
+ if (!props.portal)
9536
+ return rootNode;
9537
+ const portalNode = visible.value
9538
+ ? vue.h("span", {
9539
+ class: [...rootClass, "cc-popconfirm--portal"],
9540
+ "data-animation": motion.name,
9541
+ style: {
9542
+ ...animationStyle(motion),
9543
+ height: `${anchorStyle.value.height}px`,
9544
+ left: `${anchorStyle.value.left}px`,
9545
+ top: `${anchorStyle.value.top}px`,
9546
+ width: `${anchorStyle.value.width}px`,
9547
+ },
9548
+ }, [panelNode])
9549
+ : null;
9550
+ return [
9551
+ rootNode,
9552
+ portalNode ? vue.h(vue.Teleport, { to: "body" }, portalNode) : null,
9553
+ ];
8786
9554
  };
8787
9555
  },
8788
9556
  });
@@ -9331,9 +10099,7 @@ const ClassPopup = /*#__PURE__*/ vue.defineComponent({
9331
10099
  ]),
9332
10100
  ]);
9333
10101
  return rendered.value
9334
- ? props.container
9335
- ? vue.h(vue.Teleport, { to: props.container }, popupNode)
9336
- : popupNode
10102
+ ? vue.h(vue.Teleport, { to: props.container ?? "body" }, popupNode)
9337
10103
  : null;
9338
10104
  };
9339
10105
  },
@@ -9370,6 +10136,10 @@ const ClassTooltip = /*#__PURE__*/ vue.defineComponent({
9370
10136
  type: Boolean,
9371
10137
  default: true,
9372
10138
  },
10139
+ portal: {
10140
+ type: Boolean,
10141
+ default: true,
10142
+ },
9373
10143
  className: String,
9374
10144
  },
9375
10145
  setup(props, { attrs, slots }) {
@@ -9379,7 +10149,22 @@ const ClassTooltip = /*#__PURE__*/ vue.defineComponent({
9379
10149
  const controller = new core.TooltipController();
9380
10150
  const open = vue.ref(controller.isOpen());
9381
10151
  const safePlacement = vue.ref(props.placement);
10152
+ const anchorStyle = vue.ref({
10153
+ height: 0,
10154
+ left: -9999,
10155
+ top: -9999,
10156
+ width: 0,
10157
+ });
9382
10158
  const updatePlacement = () => {
10159
+ if (rootRef.value) {
10160
+ const rect = rootRef.value.getBoundingClientRect();
10161
+ anchorStyle.value = {
10162
+ height: rect.height,
10163
+ left: rect.left,
10164
+ top: rect.top,
10165
+ width: rect.width,
10166
+ };
10167
+ }
9383
10168
  if (!props.autoAdjust || !rootRef.value || !contentRef.value) {
9384
10169
  safePlacement.value = props.placement;
9385
10170
  return;
@@ -9397,7 +10182,8 @@ const ClassTooltip = /*#__PURE__*/ vue.defineComponent({
9397
10182
  return;
9398
10183
  const handlePointerDown = (event) => {
9399
10184
  if (!props.closeOnOutsideClick ||
9400
- rootRef.value?.contains(event.target))
10185
+ rootRef.value?.contains(event.target) ||
10186
+ contentRef.value?.contains(event.target))
9401
10187
  return;
9402
10188
  controller.close();
9403
10189
  };
@@ -9423,7 +10209,6 @@ const ClassTooltip = /*#__PURE__*/ vue.defineComponent({
9423
10209
  });
9424
10210
  vue.watch(() => props.placement, () => updatePlacement());
9425
10211
  return () => {
9426
- const motion = resolveAnimation(props.animation, "fade");
9427
10212
  const openEvents = props.trigger === "click"
9428
10213
  ? {
9429
10214
  onClick: () => {
@@ -9444,29 +10229,49 @@ const ClassTooltip = /*#__PURE__*/ vue.defineComponent({
9444
10229
  controller.close();
9445
10230
  },
9446
10231
  };
9447
- return vue.h("span", {
10232
+ const motion = resolveAnimation(props.animation, "fade");
10233
+ const tooltipClass = [
10234
+ "cc-tooltip",
10235
+ `cc-tooltip--${safePlacement.value}`,
10236
+ props.className,
10237
+ ];
10238
+ const tooltipContent = vue.h("span", {
10239
+ class: "cc-tooltip__content",
10240
+ id: contentId,
10241
+ ref: contentRef,
10242
+ role: "tooltip",
10243
+ }, props.content);
10244
+ const rootNode = vue.h("span", {
9448
10245
  ...attrs,
9449
10246
  ...openEvents,
9450
10247
  "aria-describedby": open.value ? contentId : undefined,
9451
- class: [
9452
- "cc-tooltip",
9453
- `cc-tooltip--${safePlacement.value}`,
9454
- props.className,
9455
- ],
10248
+ class: tooltipClass,
9456
10249
  "data-animation": motion.name,
9457
10250
  "data-open": open.value,
9458
10251
  ref: rootRef,
9459
10252
  style: animationStyle(motion),
9460
10253
  tabindex: props.trigger === "click" ? 0 : undefined,
9461
- }, [
9462
- slots.default?.(),
9463
- vue.h("span", {
9464
- class: "cc-tooltip__content",
9465
- id: contentId,
9466
- ref: contentRef,
9467
- role: "tooltip",
9468
- }, props.content),
9469
- ]);
10254
+ }, [slots.default?.(), props.portal ? null : tooltipContent]);
10255
+ if (!props.portal)
10256
+ return rootNode;
10257
+ const portalNode = open.value || anchorStyle.value.left > -9999
10258
+ ? vue.h("span", {
10259
+ class: [...tooltipClass, "cc-tooltip--portal"],
10260
+ "data-animation": motion.name,
10261
+ "data-open": open.value,
10262
+ style: {
10263
+ ...animationStyle(motion),
10264
+ height: `${anchorStyle.value.height}px`,
10265
+ left: `${anchorStyle.value.left}px`,
10266
+ top: `${anchorStyle.value.top}px`,
10267
+ width: `${anchorStyle.value.width}px`,
10268
+ },
10269
+ }, [tooltipContent])
10270
+ : null;
10271
+ return [
10272
+ rootNode,
10273
+ portalNode ? vue.h(vue.Teleport, { to: "body" }, portalNode) : null,
10274
+ ];
9470
10275
  };
9471
10276
  },
9472
10277
  });
@@ -9479,6 +10284,10 @@ const ClassToastViewport = /*#__PURE__*/ vue.defineComponent({
9479
10284
  default: undefined,
9480
10285
  },
9481
10286
  manager: Object,
10287
+ maxVisible: {
10288
+ type: Number,
10289
+ default: undefined,
10290
+ },
9482
10291
  position: {
9483
10292
  type: String,
9484
10293
  default: "top-right",
@@ -9489,38 +10298,110 @@ const ClassToastViewport = /*#__PURE__*/ vue.defineComponent({
9489
10298
  },
9490
10299
  },
9491
10300
  setup(props, { attrs, slots }) {
9492
- const manager = props.manager ?? defaultToastManager;
9493
- const items = vue.shallowRef(manager.getToasts());
9494
- const getVisibleItems = (source) => source.filter((item) => item.position === props.position);
9495
- const renderedItems = vue.shallowRef(getVisibleItems(items.value).map((item) => ({ item, state: "enter" })));
10301
+ const activeManager = vue.shallowRef(props.manager ?? defaultToastManager);
10302
+ const items = vue.shallowRef(activeManager.value.getToasts());
10303
+ const getVisibleItems = (source) => {
10304
+ const positionItems = source.filter((item) => item.position === props.position);
10305
+ const visible = positionItems.slice(Math.max(0, positionItems.length - normalizeToastMaxVisible(props.maxVisible)));
10306
+ return isToastTopPosition(props.position)
10307
+ ? [...visible].reverse()
10308
+ : visible;
10309
+ };
10310
+ const renderedItems = vue.shallowRef(getVisibleItems(items.value).map((item) => ({
10311
+ item,
10312
+ motion: false,
10313
+ state: "enter",
10314
+ })));
10315
+ const toastNodes = new Map();
10316
+ let rects = new Map();
9496
10317
  let timer;
9497
10318
  let frame = 0;
10319
+ let flipFrame = 0;
10320
+ const setToastNode = (id, node) => {
10321
+ if (node instanceof HTMLElement)
10322
+ toastNodes.set(id, node);
10323
+ else
10324
+ toastNodes.delete(id);
10325
+ };
10326
+ const runFlip = async (motion) => {
10327
+ if (flipFrame)
10328
+ cancelAnimationFrame(flipFrame);
10329
+ await vue.nextTick();
10330
+ const previousRects = rects;
10331
+ const nextRects = new Map();
10332
+ const activeIds = new Set(renderedItems.value
10333
+ .filter((entry) => entry.motion && entry.state !== "exit")
10334
+ .map(({ item }) => item.id));
10335
+ toastNodes.forEach((node, id) => {
10336
+ if (!activeIds.has(id))
10337
+ return;
10338
+ const rect = node.getBoundingClientRect();
10339
+ nextRects.set(id, rect);
10340
+ const previous = previousRects.get(id);
10341
+ if (!previous)
10342
+ return;
10343
+ const deltaY = previous.top - rect.top;
10344
+ if (Math.abs(deltaY) < 1)
10345
+ return;
10346
+ node.style.transition = "none";
10347
+ node.style.setProperty("--cc-toast-stack-offset", `${deltaY}px`);
10348
+ node.style.willChange = "transform, opacity";
10349
+ });
10350
+ flipFrame = requestAnimationFrame(() => {
10351
+ toastNodes.forEach((node, id) => {
10352
+ if (!nextRects.has(id))
10353
+ return;
10354
+ node.style.transition = `transform ${motion.duration}ms ${motion.easing}, opacity ${motion.duration}ms ${motion.easing}, margin ${motion.duration}ms ${motion.easing}`;
10355
+ node.style.removeProperty("--cc-toast-stack-offset");
10356
+ window.setTimeout(() => {
10357
+ node.style.transition = "";
10358
+ node.style.willChange = "";
10359
+ }, motion.duration);
10360
+ });
10361
+ flipFrame = 0;
10362
+ });
10363
+ rects = nextRects;
10364
+ };
9498
10365
  const syncRenderedItems = (nextItems) => {
9499
10366
  if (frame)
9500
10367
  cancelAnimationFrame(frame);
10368
+ const motion = resolveAnimation(props.animation, "slide");
9501
10369
  const currentIds = new Set(renderedItems.value.map(({ item }) => item.id));
9502
10370
  const incomingIds = new Set(nextItems.map((item) => item.id));
10371
+ const incomingById = new Map(nextItems.map((item) => [item.id, item]));
9503
10372
  const enteringIds = nextItems
9504
10373
  .filter((item) => !currentIds.has(item.id))
9505
10374
  .map((item) => item.id);
9506
- const next = nextItems.map((item) => ({
9507
- item,
9508
- state: currentIds.has(item.id) ? "enter" : "exit",
10375
+ const retainedOrExiting = renderedItems.value.map(({ item }) => ({
10376
+ item: incomingById.get(item.id) ?? item,
10377
+ motion: !incomingIds.has(item.id),
10378
+ state: incomingIds.has(item.id)
10379
+ ? "enter"
10380
+ : "exit",
9509
10381
  }));
9510
- const exiting = renderedItems.value
9511
- .filter(({ item }) => !incomingIds.has(item.id))
9512
- .map(({ item }) => ({ item, state: "exit" }));
9513
- renderedItems.value = [...next, ...exiting];
10382
+ const entering = nextItems
10383
+ .filter((item) => !currentIds.has(item.id))
10384
+ .map((item) => ({ item, motion: true, state: "prepare" }));
10385
+ renderedItems.value = [...retainedOrExiting, ...entering];
10386
+ void runFlip(motion);
9514
10387
  if (enteringIds.length) {
9515
10388
  frame = requestAnimationFrame(() => {
9516
10389
  renderedItems.value = renderedItems.value.map((entry) => enteringIds.includes(entry.item.id)
9517
10390
  ? { ...entry, state: "enter" }
9518
10391
  : entry);
9519
10392
  });
10393
+ const clearMotion = () => {
10394
+ renderedItems.value = renderedItems.value.map((entry) => enteringIds.includes(entry.item.id) && entry.state === "enter"
10395
+ ? { ...entry, motion: false }
10396
+ : entry);
10397
+ };
10398
+ if (!motion.enabled || motion.duration <= 0)
10399
+ clearMotion();
10400
+ else
10401
+ setTimeout(clearMotion, motion.duration);
9520
10402
  }
9521
- if (!exiting.length)
10403
+ if (!retainedOrExiting.some((entry) => entry.state === "exit"))
9522
10404
  return;
9523
- const motion = resolveAnimation(props.animation, "slide");
9524
10405
  if (timer)
9525
10406
  clearTimeout(timer);
9526
10407
  if (!motion.enabled || motion.duration <= 0) {
@@ -9531,37 +10412,57 @@ const ClassToastViewport = /*#__PURE__*/ vue.defineComponent({
9531
10412
  renderedItems.value = renderedItems.value.filter((entry) => entry.state !== "exit");
9532
10413
  }, motion.duration);
9533
10414
  };
9534
- const unsubscribe = manager.subscribe((nextItems) => {
9535
- items.value = nextItems;
9536
- syncRenderedItems(getVisibleItems(nextItems));
10415
+ let unsubscribe = () => { };
10416
+ const subscribeManager = (nextManager) => {
10417
+ unsubscribe();
10418
+ activeManager.value = nextManager;
10419
+ items.value = nextManager.getToasts();
10420
+ syncRenderedItems(getVisibleItems(items.value));
10421
+ unsubscribe = nextManager.subscribe((nextItems) => {
10422
+ items.value = nextItems;
10423
+ syncRenderedItems(getVisibleItems(nextItems));
10424
+ });
10425
+ };
10426
+ subscribeManager(activeManager.value);
10427
+ vue.watch(() => props.manager, (nextManager) => {
10428
+ subscribeManager(nextManager ?? defaultToastManager);
9537
10429
  });
9538
- vue.watch(() => props.position, () => syncRenderedItems(getVisibleItems(items.value)));
10430
+ vue.watch(() => [props.position, props.maxVisible], () => syncRenderedItems(getVisibleItems(items.value)));
9539
10431
  vue.onBeforeUnmount(() => {
9540
10432
  if (timer)
9541
10433
  clearTimeout(timer);
9542
10434
  if (frame)
9543
10435
  cancelAnimationFrame(frame);
10436
+ if (flipFrame)
10437
+ cancelAnimationFrame(flipFrame);
9544
10438
  unsubscribe();
9545
10439
  });
9546
10440
  return () => {
9547
10441
  const motion = resolveAnimation(props.animation, "slide");
9548
- return vue.h("div", {
10442
+ const viewportNode = vue.h("div", {
9549
10443
  ...attrs,
9550
10444
  "aria-live": "polite",
9551
10445
  class: [props.className, `cc-toast-viewport--${props.position}`],
9552
10446
  role: "status",
9553
10447
  style: animationStyle(motion),
9554
- }, renderedItems.value.map(({ item, state }) => slots.default
10448
+ }, renderedItems.value.map(({ item, motion: isMotionActive, state }, index) => slots.default
9555
10449
  ? slots.default({
9556
10450
  item,
9557
- dismiss: () => manager.dismiss(item.id),
10451
+ dismiss: () => activeManager.value.dismiss(item.id),
9558
10452
  state,
9559
10453
  })
9560
10454
  : vue.h("article", {
9561
10455
  class: `cc-toast cc-toast--${item.tone}`,
9562
10456
  "data-animation": motion.name,
10457
+ "data-motion": isMotionActive ? "true" : "false",
9563
10458
  "data-state": state,
9564
10459
  key: item.id,
10460
+ style: {
10461
+ "--cc-toast-stack-index": index,
10462
+ },
10463
+ ref: (node) => {
10464
+ setToastNode(item.id, node instanceof Element ? node : null);
10465
+ },
9565
10466
  }, [
9566
10467
  item.title
9567
10468
  ? vue.h("strong", { class: "cc-toast__title" }, item.title)
@@ -9571,9 +10472,10 @@ const ClassToastViewport = /*#__PURE__*/ vue.defineComponent({
9571
10472
  "aria-label": "Dismiss toast",
9572
10473
  class: "cc-toast__close",
9573
10474
  type: "button",
9574
- onClick: () => manager.dismiss(item.id),
9575
- }, "x"),
10475
+ onClick: () => activeManager.value.dismiss(item.id),
10476
+ }, classIcon("x")),
9576
10477
  ])));
10478
+ return vue.h(vue.Teleport, { to: "body" }, viewportNode);
9577
10479
  };
9578
10480
  },
9579
10481
  });
@@ -11099,6 +12001,10 @@ Object.defineProperty(exports, "ChatVirtualListController", {
11099
12001
  enumerable: true,
11100
12002
  get: function () { return core.ChatVirtualListController; }
11101
12003
  });
12004
+ Object.defineProperty(exports, "CodePreviewController", {
12005
+ enumerable: true,
12006
+ get: function () { return core.CodePreviewController; }
12007
+ });
11102
12008
  Object.defineProperty(exports, "ColorPickerController", {
11103
12009
  enumerable: true,
11104
12010
  get: function () { return core.ColorPickerController; }
@@ -11155,6 +12061,10 @@ Object.defineProperty(exports, "GradientTextController", {
11155
12061
  enumerable: true,
11156
12062
  get: function () { return core.GradientTextController; }
11157
12063
  });
12064
+ Object.defineProperty(exports, "HeightTransitionController", {
12065
+ enumerable: true,
12066
+ get: function () { return core.HeightTransitionController; }
12067
+ });
11158
12068
  Object.defineProperty(exports, "LazyImageController", {
11159
12069
  enumerable: true,
11160
12070
  get: function () { return core.LazyImageController; }
@@ -11167,6 +12077,10 @@ Object.defineProperty(exports, "MasonryVirtualListController", {
11167
12077
  enumerable: true,
11168
12078
  get: function () { return core.MasonryVirtualListController; }
11169
12079
  });
12080
+ Object.defineProperty(exports, "MenuController", {
12081
+ enumerable: true,
12082
+ get: function () { return core.MenuController; }
12083
+ });
11170
12084
  Object.defineProperty(exports, "ModalController", {
11171
12085
  enumerable: true,
11172
12086
  get: function () { return core.ModalController; }
@@ -11179,6 +12093,10 @@ Object.defineProperty(exports, "NovelReaderController", {
11179
12093
  enumerable: true,
11180
12094
  get: function () { return core.NovelReaderController; }
11181
12095
  });
12096
+ Object.defineProperty(exports, "OrbitalSphereController", {
12097
+ enumerable: true,
12098
+ get: function () { return core.OrbitalSphereController; }
12099
+ });
11182
12100
  Object.defineProperty(exports, "PaginationController", {
11183
12101
  enumerable: true,
11184
12102
  get: function () { return core.PaginationController; }
@@ -11292,9 +12210,11 @@ exports.ClassButton = ClassButton;
11292
12210
  exports.ClassCalendar = ClassCalendar;
11293
12211
  exports.ClassCanvasEditor = ClassCanvasEditor;
11294
12212
  exports.ClassCanvasImage = ClassCanvasImage;
12213
+ exports.ClassChatTextarea = ClassChatTextarea;
11295
12214
  exports.ClassChatVirtualList = ClassChatVirtualList;
11296
12215
  exports.ClassCheckbox = ClassCheckbox;
11297
12216
  exports.ClassChecked = ClassChecked;
12217
+ exports.ClassCodePreview = ClassCodePreview;
11298
12218
  exports.ClassColorPicker = ClassColorPicker;
11299
12219
  exports.ClassComicReader = ClassComicReader;
11300
12220
  exports.ClassConfigProvider = ClassConfigProvider;
@@ -11313,16 +12233,19 @@ exports.ClassFilePreview = ClassFilePreview;
11313
12233
  exports.ClassFloatingBall = ClassFloatingBall;
11314
12234
  exports.ClassForm = ClassForm;
11315
12235
  exports.ClassGradientText = ClassGradientText;
12236
+ exports.ClassHeightTransition = ClassHeightTransition;
11316
12237
  exports.ClassInput = ClassInput;
11317
12238
  exports.ClassLazyImage = ClassLazyImage;
11318
12239
  exports.ClassLiveRoom = ClassLiveRoom;
11319
12240
  exports.ClassLoading = ClassLoading;
11320
12241
  exports.ClassMarquee = ClassMarquee;
11321
12242
  exports.ClassMasonryVirtualList = ClassMasonryVirtualList;
12243
+ exports.ClassMenu = ClassMenu;
11322
12244
  exports.ClassModal = ClassModal;
11323
12245
  exports.ClassMultiColumnPicker = ClassMultiColumnPicker;
11324
12246
  exports.ClassNovelReader = ClassNovelReader;
11325
12247
  exports.ClassNumberInput = ClassNumberInput;
12248
+ exports.ClassOrbitalSphere = ClassOrbitalSphere;
11326
12249
  exports.ClassPagination = ClassPagination;
11327
12250
  exports.ClassPasswordInput = ClassPasswordInput;
11328
12251
  exports.ClassPopconfirm = ClassPopconfirm;