@class-kit/react 0.1.1 → 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 (274) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +10 -2
  3. package/dist/components/affix.cjs.map +1 -1
  4. package/dist/components/affix.js.map +1 -1
  5. package/dist/components/backtop.cjs.map +1 -1
  6. package/dist/components/backtop.js.map +1 -1
  7. package/dist/components/badge.cjs.map +1 -1
  8. package/dist/components/badge.js.map +1 -1
  9. package/dist/components/barcode.cjs.map +1 -1
  10. package/dist/components/barcode.js.map +1 -1
  11. package/dist/components/breadcrumb.cjs.map +1 -1
  12. package/dist/components/breadcrumb.js.map +1 -1
  13. package/dist/components/button.cjs.map +1 -1
  14. package/dist/components/button.js.map +1 -1
  15. package/dist/components/calendar.cjs.map +1 -1
  16. package/dist/components/calendar.js.map +1 -1
  17. package/dist/components/canvas-editor.cjs.map +1 -1
  18. package/dist/components/canvas-editor.js.map +1 -1
  19. package/dist/components/canvas-image.cjs.map +1 -1
  20. package/dist/components/canvas-image.js.map +1 -1
  21. package/dist/components/chat-textarea.cjs +103 -0
  22. package/dist/components/chat-textarea.cjs.map +1 -0
  23. package/dist/components/chat-textarea.d.ts +3 -0
  24. package/dist/components/chat-textarea.d.ts.map +1 -0
  25. package/dist/components/chat-textarea.js +101 -0
  26. package/dist/components/chat-textarea.js.map +1 -0
  27. package/dist/components/chat-virtual-list.cjs +39 -7
  28. package/dist/components/chat-virtual-list.cjs.map +1 -1
  29. package/dist/components/chat-virtual-list.js +39 -7
  30. package/dist/components/chat-virtual-list.js.map +1 -1
  31. package/dist/components/checkbox.cjs.map +1 -1
  32. package/dist/components/checkbox.js.map +1 -1
  33. package/dist/components/checked.cjs.map +1 -1
  34. package/dist/components/checked.js.map +1 -1
  35. package/dist/components/code-preview.cjs +190 -0
  36. package/dist/components/code-preview.cjs.map +1 -0
  37. package/dist/components/code-preview.d.ts +3 -0
  38. package/dist/components/code-preview.d.ts.map +1 -0
  39. package/dist/components/code-preview.js +188 -0
  40. package/dist/components/code-preview.js.map +1 -0
  41. package/dist/components/color-picker.cjs +2 -2
  42. package/dist/components/color-picker.cjs.map +1 -1
  43. package/dist/components/color-picker.js +2 -2
  44. package/dist/components/color-picker.js.map +1 -1
  45. package/dist/components/comic-reader.cjs.map +1 -1
  46. package/dist/components/comic-reader.js.map +1 -1
  47. package/dist/components/config-provider.cjs.map +1 -1
  48. package/dist/components/config-provider.js.map +1 -1
  49. package/dist/components/config-table.cjs.map +1 -1
  50. package/dist/components/config-table.js.map +1 -1
  51. package/dist/components/countdown.cjs.map +1 -1
  52. package/dist/components/countdown.js.map +1 -1
  53. package/dist/components/danmaku.cjs.map +1 -1
  54. package/dist/components/danmaku.js.map +1 -1
  55. package/dist/components/date-picker.cjs.map +1 -1
  56. package/dist/components/date-picker.js.map +1 -1
  57. package/dist/components/date-range-picker.cjs.map +1 -1
  58. package/dist/components/date-range-picker.js.map +1 -1
  59. package/dist/components/design-effect.cjs.map +1 -1
  60. package/dist/components/design-effect.js.map +1 -1
  61. package/dist/components/drag-drop-board.cjs +24 -0
  62. package/dist/components/drag-drop-board.cjs.map +1 -1
  63. package/dist/components/drag-drop-board.js +24 -0
  64. package/dist/components/drag-drop-board.js.map +1 -1
  65. package/dist/components/draggable.cjs.map +1 -1
  66. package/dist/components/draggable.js.map +1 -1
  67. package/dist/components/ellipsis-text.cjs.map +1 -1
  68. package/dist/components/ellipsis-text.js.map +1 -1
  69. package/dist/components/empty.cjs.map +1 -1
  70. package/dist/components/empty.js.map +1 -1
  71. package/dist/components/field.cjs.map +1 -1
  72. package/dist/components/field.js.map +1 -1
  73. package/dist/components/file-preview.cjs.map +1 -1
  74. package/dist/components/file-preview.js.map +1 -1
  75. package/dist/components/floating-ball.cjs.map +1 -1
  76. package/dist/components/floating-ball.js.map +1 -1
  77. package/dist/components/form.cjs.map +1 -1
  78. package/dist/components/form.js.map +1 -1
  79. package/dist/components/gradient-text.cjs.map +1 -1
  80. package/dist/components/gradient-text.js.map +1 -1
  81. package/dist/components/height-transition.cjs +35 -0
  82. package/dist/components/height-transition.cjs.map +1 -0
  83. package/dist/components/height-transition.d.ts +3 -0
  84. package/dist/components/height-transition.d.ts.map +1 -0
  85. package/dist/components/height-transition.js +33 -0
  86. package/dist/components/height-transition.js.map +1 -0
  87. package/dist/components/input.cjs.map +1 -1
  88. package/dist/components/input.js.map +1 -1
  89. package/dist/components/lazy-image.cjs.map +1 -1
  90. package/dist/components/lazy-image.js.map +1 -1
  91. package/dist/components/live-room.cjs.map +1 -1
  92. package/dist/components/live-room.js.map +1 -1
  93. package/dist/components/loading.cjs.map +1 -1
  94. package/dist/components/loading.js.map +1 -1
  95. package/dist/components/marquee.cjs.map +1 -1
  96. package/dist/components/marquee.js.map +1 -1
  97. package/dist/components/masonry-virtual-list.cjs.map +1 -1
  98. package/dist/components/masonry-virtual-list.js.map +1 -1
  99. package/dist/components/menu.cjs +100 -0
  100. package/dist/components/menu.cjs.map +1 -0
  101. package/dist/components/menu.d.ts +3 -0
  102. package/dist/components/menu.d.ts.map +1 -0
  103. package/dist/components/menu.js +98 -0
  104. package/dist/components/menu.js.map +1 -0
  105. package/dist/components/modal.cjs.map +1 -1
  106. package/dist/components/modal.js.map +1 -1
  107. package/dist/components/multi-column-picker.cjs.map +1 -1
  108. package/dist/components/multi-column-picker.js.map +1 -1
  109. package/dist/components/novel-reader.cjs.map +1 -1
  110. package/dist/components/novel-reader.js.map +1 -1
  111. package/dist/components/number-input.cjs.map +1 -1
  112. package/dist/components/number-input.js.map +1 -1
  113. package/dist/components/orbital-sphere.cjs +40 -0
  114. package/dist/components/orbital-sphere.cjs.map +1 -0
  115. package/dist/components/orbital-sphere.d.ts +3 -0
  116. package/dist/components/orbital-sphere.d.ts.map +1 -0
  117. package/dist/components/orbital-sphere.js +38 -0
  118. package/dist/components/orbital-sphere.js.map +1 -0
  119. package/dist/components/pagination.cjs.map +1 -1
  120. package/dist/components/pagination.js.map +1 -1
  121. package/dist/components/password-input.cjs.map +1 -1
  122. package/dist/components/password-input.js.map +1 -1
  123. package/dist/components/popconfirm.cjs +40 -6
  124. package/dist/components/popconfirm.cjs.map +1 -1
  125. package/dist/components/popconfirm.js +41 -7
  126. package/dist/components/popconfirm.js.map +1 -1
  127. package/dist/components/popup.cjs +2 -1
  128. package/dist/components/popup.cjs.map +1 -1
  129. package/dist/components/popup.js +2 -1
  130. package/dist/components/popup.js.map +1 -1
  131. package/dist/components/progress-bar.cjs.map +1 -1
  132. package/dist/components/progress-bar.js.map +1 -1
  133. package/dist/components/qr-code.cjs.map +1 -1
  134. package/dist/components/qr-code.js.map +1 -1
  135. package/dist/components/radio-group.cjs.map +1 -1
  136. package/dist/components/radio-group.js.map +1 -1
  137. package/dist/components/rating.cjs.map +1 -1
  138. package/dist/components/rating.js.map +1 -1
  139. package/dist/components/rolling-number.cjs.map +1 -1
  140. package/dist/components/rolling-number.js.map +1 -1
  141. package/dist/components/select.cjs.map +1 -1
  142. package/dist/components/select.js.map +1 -1
  143. package/dist/components/signature.cjs +1 -1
  144. package/dist/components/signature.cjs.map +1 -1
  145. package/dist/components/signature.js +1 -1
  146. package/dist/components/signature.js.map +1 -1
  147. package/dist/components/skeleton.cjs.map +1 -1
  148. package/dist/components/skeleton.js.map +1 -1
  149. package/dist/components/slide-captcha.cjs.map +1 -1
  150. package/dist/components/slide-captcha.js.map +1 -1
  151. package/dist/components/swiper.cjs.map +1 -1
  152. package/dist/components/swiper.js.map +1 -1
  153. package/dist/components/switch.cjs.map +1 -1
  154. package/dist/components/switch.js.map +1 -1
  155. package/dist/components/table.cjs.map +1 -1
  156. package/dist/components/table.js.map +1 -1
  157. package/dist/components/tabs.cjs.map +1 -1
  158. package/dist/components/tabs.js.map +1 -1
  159. package/dist/components/tag.cjs.map +1 -1
  160. package/dist/components/tag.js.map +1 -1
  161. package/dist/components/textarea.cjs.map +1 -1
  162. package/dist/components/textarea.js.map +1 -1
  163. package/dist/components/tilt-card.cjs.map +1 -1
  164. package/dist/components/tilt-card.js.map +1 -1
  165. package/dist/components/timeline.cjs.map +1 -1
  166. package/dist/components/timeline.js.map +1 -1
  167. package/dist/components/toast.cjs +146 -14
  168. package/dist/components/toast.cjs.map +1 -1
  169. package/dist/components/toast.d.ts +1 -1
  170. package/dist/components/toast.d.ts.map +1 -1
  171. package/dist/components/toast.js +144 -15
  172. package/dist/components/toast.js.map +1 -1
  173. package/dist/components/tooltip.cjs +38 -5
  174. package/dist/components/tooltip.cjs.map +1 -1
  175. package/dist/components/tooltip.js +39 -6
  176. package/dist/components/tooltip.js.map +1 -1
  177. package/dist/components/typewriter-text.cjs.map +1 -1
  178. package/dist/components/typewriter-text.js.map +1 -1
  179. package/dist/components/upload.cjs.map +1 -1
  180. package/dist/components/upload.js.map +1 -1
  181. package/dist/components/verification-code.cjs.map +1 -1
  182. package/dist/components/verification-code.js.map +1 -1
  183. package/dist/components/video-detail-transition.cjs.map +1 -1
  184. package/dist/components/video-detail-transition.js.map +1 -1
  185. package/dist/components/video-player.cjs.map +1 -1
  186. package/dist/components/video-player.js.map +1 -1
  187. package/dist/components/virtual-list.cjs.map +1 -1
  188. package/dist/components/virtual-list.js.map +1 -1
  189. package/dist/components/virtual-select.cjs.map +1 -1
  190. package/dist/components/virtual-select.js.map +1 -1
  191. package/dist/components/virtual-table.cjs.map +1 -1
  192. package/dist/components/virtual-table.js.map +1 -1
  193. package/dist/{import-transform-jqLjtD6M.js → import-transform-Cw4K2Iky.js} +7 -1
  194. package/dist/import-transform-Cw4K2Iky.js.map +1 -0
  195. package/dist/{import-transform-DIRVOYvz.js → import-transform-ieMdZBuN.js} +7 -1
  196. package/dist/import-transform-ieMdZBuN.js.map +1 -0
  197. package/dist/import-transform.d.ts.map +1 -1
  198. package/dist/index.cjs +605 -36
  199. package/dist/index.cjs.map +1 -1
  200. package/dist/index.d.ts +71 -8
  201. package/dist/index.d.ts.map +1 -1
  202. package/dist/index.js +583 -39
  203. package/dist/index.js.map +1 -1
  204. package/dist/styles/base.css +168 -41
  205. package/dist/styles/components/barcode.css +206 -0
  206. package/dist/styles/components/button.css +7 -2
  207. package/dist/styles/components/calendar.css +0 -23
  208. package/dist/styles/components/canvas-editor.css +18 -21
  209. package/dist/styles/components/canvas-image.css +0 -23
  210. package/dist/styles/components/chat-textarea.css +124 -0
  211. package/dist/styles/components/chat-virtual-list.css +15 -26
  212. package/dist/styles/components/checkbox.css +39 -23
  213. package/dist/styles/components/checked.css +39 -23
  214. package/dist/styles/components/code-preview.css +208 -0
  215. package/dist/styles/components/color-picker.css +46 -27
  216. package/dist/styles/components/config-table.css +0 -23
  217. package/dist/styles/components/date-picker.css +39 -23
  218. package/dist/styles/components/date-range-picker.css +39 -23
  219. package/dist/styles/components/design-effect.css +5 -1
  220. package/dist/styles/components/drag-drop-board.css +6 -1
  221. package/dist/styles/components/field.css +39 -23
  222. package/dist/styles/components/form.css +39 -23
  223. package/dist/styles/components/gradient-text.css +4 -0
  224. package/dist/styles/components/height-transition.css +50 -0
  225. package/dist/styles/components/input.css +39 -23
  226. package/dist/styles/components/loading.css +47 -0
  227. package/dist/styles/components/menu.css +286 -0
  228. package/dist/styles/components/modal.css +2 -23
  229. package/dist/styles/components/number-input.css +39 -23
  230. package/dist/styles/components/orbital-sphere.css +224 -0
  231. package/dist/styles/components/password-input.css +39 -23
  232. package/dist/styles/components/popconfirm.css +5 -0
  233. package/dist/styles/components/popup.css +2 -23
  234. package/dist/styles/components/qr-code.css +206 -0
  235. package/dist/styles/components/radio-group.css +39 -23
  236. package/dist/styles/components/rating.css +39 -23
  237. package/dist/styles/components/select.css +39 -23
  238. package/dist/styles/components/signature.css +39 -23
  239. package/dist/styles/components/switch.css +39 -23
  240. package/dist/styles/components/table.css +0 -23
  241. package/dist/styles/components/tabs.css +10 -0
  242. package/dist/styles/components/textarea.css +39 -23
  243. package/dist/styles/components/tilt-card.css +2 -23
  244. package/dist/styles/components/toast.css +109 -48
  245. package/dist/styles/components/tooltip.css +8 -23
  246. package/dist/styles/components/typewriter-text.css +4 -0
  247. package/dist/styles/components/upload.css +39 -23
  248. package/dist/styles/components/verification-code.css +39 -23
  249. package/dist/styles/components/virtual-select.css +39 -23
  250. package/dist/styles/components/virtual-table.css +0 -23
  251. package/dist/styles/components.css +1250 -165
  252. package/dist/styles/themes/business-blue.css +375 -0
  253. package/dist/styles/themes/cartoon-3d.css +695 -0
  254. package/dist/styles/themes/creative-purple.css +376 -0
  255. package/dist/styles/themes/dark-tech.css +495 -0
  256. package/dist/styles/themes/liquid-glass.css +526 -21
  257. package/dist/styles/themes/minimal.css +406 -14
  258. package/dist/styles/themes/soft-pink.css +376 -0
  259. package/dist/styles.css +1250 -165
  260. package/dist/vite.cjs +1 -1
  261. package/dist/vite.cjs.map +1 -1
  262. package/dist/vite.d.ts +1 -1
  263. package/dist/vite.js +1 -1
  264. package/dist/vite.js.map +1 -1
  265. package/dist/webpack-loader.cjs +1 -1
  266. package/dist/webpack-loader.js +1 -1
  267. package/package.json +3 -3
  268. package/dist/import-transform-DIRVOYvz.js.map +0 -1
  269. package/dist/import-transform-jqLjtD6M.js.map +0 -1
  270. package/dist/styles/themes/amber.css +0 -19
  271. package/dist/styles/themes/emerald.css +0 -19
  272. package/dist/styles/themes/rose.css +0 -19
  273. package/dist/styles/themes/sky.css +0 -19
  274. package/dist/styles/themes/violet.css +0 -19
package/dist/index.cjs CHANGED
@@ -175,23 +175,27 @@ function usePresence(open, duration) {
175
175
  return [mounted, state];
176
176
  }
177
177
  function useAnimatedToasts(items, duration) {
178
- const [rendered, setRendered] = React.useState(() => items.map((item) => ({ item, state: "enter" })));
178
+ const [rendered, setRendered] = React.useState(() => items.map((item) => ({ item, motion: false, state: "enter" })));
179
179
  React.useEffect(() => {
180
180
  let enteringIds = [];
181
181
  setRendered((current) => {
182
182
  const currentIds = new Set(current.map(({ item }) => item.id));
183
183
  const incomingIds = new Set(items.map((item) => item.id));
184
+ const incomingById = new Map(items.map((item) => [item.id, item]));
184
185
  enteringIds = items
185
186
  .filter((item) => !currentIds.has(item.id))
186
187
  .map((item) => item.id);
187
- const next = items.map((item) => ({
188
- item,
189
- state: currentIds.has(item.id) ? "enter" : "exit",
188
+ const retainedOrExiting = current.map(({ item }) => ({
189
+ item: incomingById.get(item.id) ?? item,
190
+ motion: !incomingIds.has(item.id),
191
+ state: incomingIds.has(item.id)
192
+ ? "enter"
193
+ : "exit",
190
194
  }));
191
- const exiting = current
192
- .filter(({ item }) => !incomingIds.has(item.id))
193
- .map(({ item }) => ({ item, state: "exit" }));
194
- return [...next, ...exiting];
195
+ const entering = items
196
+ .filter((item) => !currentIds.has(item.id))
197
+ .map((item) => ({ item, motion: true, state: "prepare" }));
198
+ return [...retainedOrExiting, ...entering];
195
199
  });
196
200
  if (!enteringIds.length)
197
201
  return undefined;
@@ -202,6 +206,22 @@ function useAnimatedToasts(items, duration) {
202
206
  });
203
207
  return () => window.cancelAnimationFrame(frame);
204
208
  }, [items]);
209
+ React.useEffect(() => {
210
+ if (!rendered.some((entry) => entry.motion && entry.state === "enter"))
211
+ return;
212
+ if (duration <= 0) {
213
+ setRendered((current) => current.map((entry) => entry.motion && entry.state === "enter"
214
+ ? { ...entry, motion: false }
215
+ : entry));
216
+ return;
217
+ }
218
+ const timer = window.setTimeout(() => {
219
+ setRendered((current) => current.map((entry) => entry.motion && entry.state === "enter"
220
+ ? { ...entry, motion: false }
221
+ : entry));
222
+ }, duration);
223
+ return () => window.clearTimeout(timer);
224
+ }, [duration, rendered]);
205
225
  React.useEffect(() => {
206
226
  if (!rendered.some((entry) => entry.state === "exit"))
207
227
  return;
@@ -216,6 +236,80 @@ function useAnimatedToasts(items, duration) {
216
236
  }, [duration, rendered]);
217
237
  return rendered;
218
238
  }
239
+ function normalizeToastMaxVisible(maxVisible) {
240
+ if (typeof maxVisible !== "number" || !Number.isFinite(maxVisible))
241
+ return 3;
242
+ return Math.max(1, Math.min(6, Math.floor(maxVisible)));
243
+ }
244
+ function isToastTopPosition(position) {
245
+ return (position === "top" || position === "top-left" || position === "top-right");
246
+ }
247
+ function useToastFlip(entries, duration, easing) {
248
+ const nodeMapRef = React.useRef(new Map());
249
+ const rectMapRef = React.useRef(new Map());
250
+ const frameRef = React.useRef(0);
251
+ const setNode = React.useCallback((id, node) => {
252
+ if (node)
253
+ nodeMapRef.current.set(id, node);
254
+ else
255
+ nodeMapRef.current.delete(id);
256
+ }, []);
257
+ React.useLayoutEffect(() => {
258
+ if (frameRef.current)
259
+ window.cancelAnimationFrame(frameRef.current);
260
+ const previousRects = rectMapRef.current;
261
+ const nextRects = new Map();
262
+ const activeIds = new Set(entries
263
+ .filter((entry) => entry.motion && entry.state !== "exit")
264
+ .map((entry) => entry.item.id));
265
+ nodeMapRef.current.forEach((node, id) => {
266
+ if (!activeIds.has(id))
267
+ return;
268
+ const rect = node.getBoundingClientRect();
269
+ nextRects.set(id, rect);
270
+ const previous = previousRects.get(id);
271
+ if (!previous)
272
+ return;
273
+ const deltaY = previous.top - rect.top;
274
+ if (Math.abs(deltaY) < 1)
275
+ return;
276
+ node.style.transition = "none";
277
+ node.style.setProperty("--cc-toast-stack-offset", `${deltaY}px`);
278
+ node.style.willChange = "transform, opacity";
279
+ });
280
+ frameRef.current = window.requestAnimationFrame(() => {
281
+ nodeMapRef.current.forEach((node, id) => {
282
+ if (!nextRects.has(id))
283
+ return;
284
+ node.style.transition = `transform ${duration}ms ${easing}, opacity ${duration}ms ${easing}, margin ${duration}ms ${easing}`;
285
+ node.style.removeProperty("--cc-toast-stack-offset");
286
+ window.setTimeout(() => {
287
+ node.style.transition = "";
288
+ node.style.willChange = "";
289
+ }, duration);
290
+ });
291
+ frameRef.current = 0;
292
+ });
293
+ rectMapRef.current = nextRects;
294
+ return () => {
295
+ if (frameRef.current)
296
+ window.cancelAnimationFrame(frameRef.current);
297
+ };
298
+ }, [duration, easing, entries]);
299
+ return setNode;
300
+ }
301
+ function useToastItems(manager) {
302
+ const snapshotRef = React.useRef(manager.getToasts());
303
+ const managerRef = React.useRef(manager);
304
+ if (managerRef.current !== manager) {
305
+ managerRef.current = manager;
306
+ snapshotRef.current = manager.getToasts();
307
+ }
308
+ return React.useSyncExternalStore(React.useCallback((notify) => manager.subscribe((items) => {
309
+ snapshotRef.current = items;
310
+ notify();
311
+ }), [manager]), React.useCallback(() => snapshotRef.current, [manager]), React.useCallback(() => snapshotRef.current, [manager]));
312
+ }
219
313
  function resolveTabsDirection(tabs, previousId, nextId, direction) {
220
314
  if (direction === "none")
221
315
  return "none";
@@ -391,12 +485,12 @@ function PasswordInput({ name, label, className = "cc-field cc-password-field",
391
485
  const Field = Input;
392
486
  function ColorPicker({ name, label, className = "cc-field cc-color-picker", disabled, panelClassName = "cc-color-picker__panel", readOnly, initialValue, rules, showInputSteppers = false, validateOn, onChange, ...props }) {
393
487
  const field = useOptionalField(name, {
394
- initialValue: initialValue ?? "#7c3aed",
488
+ initialValue: initialValue ?? "#1d2129",
395
489
  rules,
396
490
  validateOn,
397
491
  });
398
492
  const interactivity = resolveFieldInteractivity(useOptionalFormInteractivity(), disabled, readOnly);
399
- const controller = React.useMemo(() => new core.ColorPickerController(String(field.value || "#7c3aed")), [field.value]);
493
+ const controller = React.useMemo(() => new core.ColorPickerController(String(field.value || "#1d2129")), [field.value]);
400
494
  const state = controller.getState();
401
495
  const rootRef = React.useRef(null);
402
496
  const panelRef = React.useRef(null);
@@ -1080,6 +1174,82 @@ function Textarea({ name, label, className = "cc-field", labelClassName = "cc-fi
1080
1174
  field.setValue(event.currentTarget.value);
1081
1175
  }, ...options }), canClear ? (jsxRuntime.jsx("button", { "aria-label": clearLabel, className: "cc-field__clear cc-field__clear--textarea", type: "button", onClick: () => field.setValue(""), children: clearIcon })) : null] }), jsxRuntime.jsx(FieldError, { className: errorClassName, errorId: errorId, errors: field.errors })] }));
1082
1176
  }
1177
+ function getTextareaMetrics(element) {
1178
+ const computed = window.getComputedStyle(element);
1179
+ const fontSize = Number.parseFloat(computed.fontSize) || 14;
1180
+ const lineHeight = Number.parseFloat(computed.lineHeight) || fontSize * 1.5;
1181
+ const paddingY = (Number.parseFloat(computed.paddingTop) || 0) +
1182
+ (Number.parseFloat(computed.paddingBottom) || 0);
1183
+ const borderY = (Number.parseFloat(computed.borderTopWidth) || 0) +
1184
+ (Number.parseFloat(computed.borderBottomWidth) || 0);
1185
+ return { borderY, lineHeight, paddingY };
1186
+ }
1187
+ const ChatTextarea = /*#__PURE__*/ React.forwardRef(function ChatTextarea({ className = "cc-chat-textarea", clearable = true, clearIcon = jsxRuntime.jsx(ClassIcon, { name: "x" }), clearLabel = core.getClassComponentsLocale().inputClearLabel, defaultValue = "", disabled, maxRows = 3, minRows = 1, onValueChange, placeholder, readOnly, style, textareaClassName = "cc-chat-textarea__control", textareaStyle, value, ...props }, ref) {
1188
+ const textareaRef = React.useRef(null);
1189
+ const controllerRef = React.useRef(new core.ChatTextareaController({
1190
+ maxRows,
1191
+ minRows,
1192
+ value: value ?? defaultValue,
1193
+ }));
1194
+ const controlled = value !== undefined;
1195
+ const [state, setState] = React.useState(() => controllerRef.current.getState());
1196
+ const resize = React.useCallback(() => {
1197
+ const element = textareaRef.current;
1198
+ if (!element || typeof window === "undefined")
1199
+ return;
1200
+ const { borderY, lineHeight, paddingY } = getTextareaMetrics(element);
1201
+ const minHeight = lineHeight * state.minRows + paddingY + borderY;
1202
+ const maxHeight = lineHeight * state.maxRows + paddingY + borderY;
1203
+ element.style.height = "auto";
1204
+ const nextHeight = Math.min(Math.max(element.scrollHeight, minHeight), maxHeight);
1205
+ element.style.height = `${nextHeight}px`;
1206
+ element.style.overflowY =
1207
+ element.scrollHeight > maxHeight + 1 ? "auto" : "hidden";
1208
+ }, [state.maxRows, state.minRows, state.value]);
1209
+ React.useImperativeHandle(ref, () => ({
1210
+ blur: () => textareaRef.current?.blur(),
1211
+ focus: () => textareaRef.current?.focus(),
1212
+ getElement: () => textareaRef.current,
1213
+ }), []);
1214
+ React.useEffect(() => {
1215
+ const next = controllerRef.current.update({
1216
+ maxRows,
1217
+ minRows,
1218
+ value: controlled ? value : state.value,
1219
+ });
1220
+ setState(next);
1221
+ }, [controlled, maxRows, minRows, value]);
1222
+ React.useLayoutEffect(() => {
1223
+ resize();
1224
+ }, [resize]);
1225
+ React.useEffect(() => {
1226
+ if (typeof ResizeObserver === "undefined" || !textareaRef.current)
1227
+ return undefined;
1228
+ const observer = new ResizeObserver(resize);
1229
+ observer.observe(textareaRef.current);
1230
+ return () => observer.disconnect();
1231
+ }, [resize]);
1232
+ const commit = (nextValue, event) => {
1233
+ const nextState = controllerRef.current.setValue(nextValue);
1234
+ if (!controlled)
1235
+ setState(nextState);
1236
+ onValueChange?.(nextValue, event);
1237
+ };
1238
+ const currentValue = controlled ? (value ?? "") : state.value;
1239
+ const canClear = clearable && currentValue !== "" && !disabled && !readOnly;
1240
+ return (jsxRuntime.jsxs("div", { className: className, "data-disabled": Boolean(disabled), "data-readonly": Boolean(readOnly), "data-scrollable": currentValue.length > 0, style: style, children: [jsxRuntime.jsx("textarea", { ...props, className: `${textareaClassName}${canClear ? " cc-chat-textarea__control--clearable" : ""}`, disabled: disabled, placeholder: placeholder, readOnly: readOnly, ref: textareaRef, rows: state.minRows, style: {
1241
+ "--cc-chat-textarea-max-rows": state.maxRows,
1242
+ "--cc-chat-textarea-min-rows": state.minRows,
1243
+ ...textareaStyle,
1244
+ }, value: currentValue, onChange: (event) => {
1245
+ if (readOnly)
1246
+ return;
1247
+ commit(event.currentTarget.value, event);
1248
+ } }), canClear ? (jsxRuntime.jsx("button", { "aria-label": clearLabel, className: "cc-chat-textarea__clear", type: "button", onClick: (event) => {
1249
+ commit("", event);
1250
+ textareaRef.current?.focus();
1251
+ }, children: clearIcon })) : null] }));
1252
+ });
1083
1253
  function getSelectMenuPosition(trigger, preferredHeight, anchorTopPlacement = false) {
1084
1254
  if (!trigger || typeof window === "undefined") {
1085
1255
  return { placement: "bottom", style: {} };
@@ -1496,6 +1666,53 @@ function Breadcrumb({ className = "cc-breadcrumb", items, separator = "/", ...pr
1496
1666
  const state = React.useMemo(() => new core.BreadcrumbController(items).getState(), [items]);
1497
1667
  return (jsxRuntime.jsx("nav", { className: className, "aria-label": "Breadcrumb", ...props, children: state.items.map((item, index) => (jsxRuntime.jsxs("span", { className: "cc-breadcrumb__item", children: [index > 0 ? (jsxRuntime.jsx("span", { className: "cc-breadcrumb__separator", children: separator })) : null, item.href && !item.disabled ? (jsxRuntime.jsx("a", { href: item.href, children: item.label })) : (jsxRuntime.jsx("span", { "data-disabled": item.disabled, children: item.label }))] }, String(item.key)))) }));
1498
1668
  }
1669
+ function renderMenuIcon(item, collapsed, iconRender) {
1670
+ const rendered = iconRender?.(item);
1671
+ if (rendered !== undefined)
1672
+ return rendered;
1673
+ if (item.icon)
1674
+ return item.icon;
1675
+ return collapsed ? item.label.slice(0, 1) : null;
1676
+ }
1677
+ function renderMenuItems(items, collapsed, iconRender, onToggle, onSelect) {
1678
+ return items.map((item) => {
1679
+ const hasChildren = item.children.length > 0;
1680
+ const icon = renderMenuIcon(item, collapsed, iconRender);
1681
+ return (jsxRuntime.jsxs("li", { className: "cc-menu__item", "data-active": item.isActive, "data-disabled": item.disabled, "data-expanded": item.expanded, "data-level": item.level, children: [jsxRuntime.jsxs("button", { "aria-current": item.isActive ? "page" : undefined, "aria-expanded": hasChildren ? item.expanded : undefined, className: "cc-menu__button", disabled: item.disabled, title: collapsed ? item.label : undefined, type: "button", onClick: () => {
1682
+ if (hasChildren && !collapsed)
1683
+ onToggle(item.key);
1684
+ onSelect(item.key, item);
1685
+ }, children: [icon ? (jsxRuntime.jsx("span", { className: "cc-menu__icon", "aria-hidden": "true", children: icon })) : null, jsxRuntime.jsx("span", { className: "cc-menu__label", children: item.label }), hasChildren ? (jsxRuntime.jsx(ClassIcon, { className: "cc-menu__arrow", name: "chevronDown" })) : null] }), hasChildren ? (jsxRuntime.jsx(HeightTransition, { className: "cc-height-transition cc-menu__transition", contentClassName: "cc-height-transition__content cc-menu__transition-content", duration: 180, expanded: !collapsed && item.expanded, mode: "grid", children: jsxRuntime.jsx("ul", { className: "cc-menu__list cc-menu__list--child", children: renderMenuItems(item.children, collapsed, iconRender, onToggle, onSelect) }) })) : null] }, item.key));
1686
+ });
1687
+ }
1688
+ function Menu({ activeKey, className = "cc-menu", collapsed, collapsible = true, defaultExpandedKeys = [], iconRender, items, onCollapsedChange, onSelect, ...props }) {
1689
+ const controller = React.useMemo(() => new core.MenuController({
1690
+ activeKey,
1691
+ collapsed,
1692
+ defaultExpandedKeys,
1693
+ items,
1694
+ }), []);
1695
+ const [state, setState] = React.useState(() => controller.getState());
1696
+ React.useEffect(() => {
1697
+ setState(controller.update({
1698
+ activeKey,
1699
+ collapsed,
1700
+ defaultExpandedKeys,
1701
+ items,
1702
+ }));
1703
+ }, [activeKey, collapsed, controller, defaultExpandedKeys, items]);
1704
+ const commitSelect = React.useCallback((key, item) => {
1705
+ setState(controller.activate(key));
1706
+ onSelect?.(key, item);
1707
+ }, [controller, onSelect]);
1708
+ const toggleExpanded = React.useCallback((key) => setState(controller.toggleExpanded(key)), [controller]);
1709
+ const toggleCollapsed = React.useCallback(() => {
1710
+ const next = controller.toggleCollapsed();
1711
+ setState(next);
1712
+ onCollapsedChange?.(next.collapsed);
1713
+ }, [controller, onCollapsedChange]);
1714
+ return (jsxRuntime.jsxs("nav", { className: className, "data-collapsed": state.collapsed, "data-collapsible": collapsible, ...props, children: [collapsible ? (jsxRuntime.jsx("button", { "aria-label": state.collapsed ? "展开菜单" : "收起菜单", className: "cc-menu__collapse", type: "button", onClick: toggleCollapsed, children: jsxRuntime.jsx(ClassIcon, { name: state.collapsed ? "chevronRight" : "chevronLeft" }) })) : null, jsxRuntime.jsx("ul", { className: "cc-menu__list", children: renderMenuItems(state.items, state.collapsed, iconRender, toggleExpanded, commitSelect) })] }));
1715
+ }
1499
1716
  function Pagination({ boundaryCount = 1, className = "cc-pagination", current = 1, pageSize = 10, siblingCount = 1, total = 0, previousIcon = jsxRuntime.jsx(ClassIcon, { name: "chevronLeft" }), nextIcon = jsxRuntime.jsx(ClassIcon, { name: "chevronRight" }), onChange, ...props }) {
1500
1717
  const state = React.useMemo(() => new core.PaginationController({
1501
1718
  boundaryCount,
@@ -1506,14 +1723,29 @@ function Pagination({ boundaryCount = 1, className = "cc-pagination", current =
1506
1723
  }).getState(), [boundaryCount, current, pageSize, siblingCount, total]);
1507
1724
  return (jsxRuntime.jsxs("div", { className: className, ...props, children: [jsxRuntime.jsx("button", { disabled: state.current <= 1, type: "button", onClick: () => onChange?.(state.current - 1), children: previousIcon }), state.pages.map((page, index) => page === "ellipsis" ? (jsxRuntime.jsx("span", { "aria-hidden": "true", className: "cc-pagination__ellipsis", children: "\u2022\u2022\u2022" }, `ellipsis-${index}`)) : (jsxRuntime.jsx("button", { "data-active": page === state.current, type: "button", onClick: () => onChange?.(page), children: page }, page))), jsxRuntime.jsx("button", { disabled: state.current >= state.pageCount, type: "button", onClick: () => onChange?.(state.current + 1), children: nextIcon })] }));
1508
1725
  }
1509
- function Popconfirm({ children, animation, autoAdjust = true, placement = "top", content = core.getClassComponentsLocale().popconfirmContent, confirmText = core.getClassComponentsLocale().popconfirmConfirmText, cancelText = core.getClassComponentsLocale().popconfirmCancelText, closeOnEsc = true, closeOnOutsideClick = true, onConfirm, }) {
1726
+ function Popconfirm({ children, animation, autoAdjust = true, placement = "top", content = core.getClassComponentsLocale().popconfirmContent, confirmText = core.getClassComponentsLocale().popconfirmConfirmText, cancelText = core.getClassComponentsLocale().popconfirmCancelText, closeOnEsc = true, closeOnOutsideClick = true, onConfirm, portal = true, }) {
1510
1727
  const rootRef = React.useRef(null);
1511
1728
  const panelRef = React.useRef(null);
1512
1729
  const [open, setOpen] = React.useState(false);
1513
1730
  const [safePlacement, setSafePlacement] = React.useState(placement);
1731
+ const [anchorStyle, setAnchorStyle] = React.useState({
1732
+ height: 0,
1733
+ left: -9999,
1734
+ top: -9999,
1735
+ width: 0,
1736
+ });
1514
1737
  const motion = resolveAnimation(animation, "scale");
1515
1738
  const [mounted, presence] = usePresence(open, motion.enabled ? motion.duration : 0);
1516
1739
  const updatePlacement = React.useCallback(() => {
1740
+ if (rootRef.current) {
1741
+ const rect = rootRef.current.getBoundingClientRect();
1742
+ setAnchorStyle({
1743
+ height: rect.height,
1744
+ left: rect.left,
1745
+ top: rect.top,
1746
+ width: rect.width,
1747
+ });
1748
+ }
1517
1749
  if (!autoAdjust || !rootRef.current || !panelRef.current) {
1518
1750
  setSafePlacement(placement);
1519
1751
  return;
@@ -1526,7 +1758,8 @@ function Popconfirm({ children, animation, autoAdjust = true, placement = "top",
1526
1758
  requestAnimationFrame(updatePlacement);
1527
1759
  const close = (event) => {
1528
1760
  if (!closeOnOutsideClick ||
1529
- rootRef.current?.contains(event.target))
1761
+ rootRef.current?.contains(event.target) ||
1762
+ panelRef.current?.contains(event.target))
1530
1763
  return;
1531
1764
  setOpen(false);
1532
1765
  };
@@ -1551,10 +1784,27 @@ function Popconfirm({ children, animation, autoAdjust = true, placement = "top",
1551
1784
  if (open)
1552
1785
  updatePlacement();
1553
1786
  }, [open, placement, updatePlacement]);
1554
- return (jsxRuntime.jsxs("span", { className: ["cc-popconfirm", `cc-popconfirm--${safePlacement}`].join(" "), "data-animation": motion.name, ref: rootRef, style: animationStyle(motion), children: [jsxRuntime.jsx("span", { onClick: () => setOpen(true), children: children }), mounted ? (jsxRuntime.jsxs("span", { className: "cc-popconfirm__panel", "data-state": presence, ref: panelRef, role: "dialog", children: [jsxRuntime.jsx("span", { children: content }), jsxRuntime.jsxs("span", { className: "cc-popconfirm__actions", children: [jsxRuntime.jsx("button", { type: "button", onClick: () => setOpen(false), children: cancelText }), jsxRuntime.jsx("button", { type: "button", onClick: () => {
1555
- onConfirm?.();
1556
- setOpen(false);
1557
- }, children: confirmText })] })] })) : null] }));
1787
+ const rootClassName = [
1788
+ "cc-popconfirm",
1789
+ `cc-popconfirm--${safePlacement}`,
1790
+ ].join(" ");
1791
+ const panelNode = mounted ? (jsxRuntime.jsxs("span", { className: "cc-popconfirm__panel", "data-state": presence, ref: panelRef, role: "dialog", children: [jsxRuntime.jsx("span", { children: content }), jsxRuntime.jsxs("span", { className: "cc-popconfirm__actions", children: [jsxRuntime.jsx("button", { type: "button", onClick: () => setOpen(false), children: cancelText }), jsxRuntime.jsx("button", { type: "button", onClick: () => {
1792
+ onConfirm?.();
1793
+ setOpen(false);
1794
+ }, children: confirmText })] })] })) : null;
1795
+ const rootNode = (jsxRuntime.jsxs("span", { className: rootClassName, "data-animation": motion.name, ref: rootRef, style: animationStyle(motion), children: [jsxRuntime.jsx("span", { onClick: () => setOpen(true), children: children }), portal ? null : panelNode] }));
1796
+ if (!portal)
1797
+ return rootNode;
1798
+ const portalNode = mounted ? (jsxRuntime.jsx("span", { className: `${rootClassName} cc-popconfirm--portal`, "data-animation": motion.name, style: {
1799
+ ...animationStyle(motion),
1800
+ height: `${anchorStyle.height}px`,
1801
+ left: `${anchorStyle.left}px`,
1802
+ top: `${anchorStyle.top}px`,
1803
+ width: `${anchorStyle.width}px`,
1804
+ }, children: panelNode })) : null;
1805
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [rootNode, portalNode && typeof document !== "undefined"
1806
+ ? reactDom.createPortal(portalNode, document.body)
1807
+ : null] }));
1558
1808
  }
1559
1809
  function getBacktopTarget(target) {
1560
1810
  if (typeof target === "string")
@@ -1786,13 +2036,14 @@ function Popup({ open, controller, placement = "bottom", title, children, animat
1786
2036
  }, []);
1787
2037
  if (!mounted)
1788
2038
  return null;
1789
- const popupContainer = containerRef?.current ?? null;
2039
+ const popupContainer = containerRef?.current ??
2040
+ (typeof document !== "undefined" ? document.body : null);
1790
2041
  const popupElement = (jsxRuntime.jsxs("div", { className: className, "data-animation": motion.name, "data-contained": popupContainer ? "true" : "false", "data-placement": popupState.placement, "data-state": animationState, role: "presentation", style: animationStyle(motion, style), ...props, children: [jsxRuntime.jsx("button", { "aria-label": "Close popup", className: overlayClassName, type: "button", onClick: closeOnOverlayClick ? close : undefined }), jsxRuntime.jsxs("section", { "aria-modal": "true", className: panelClassName, ref: panelRef, role: "dialog", tabIndex: -1, children: [title ? (jsxRuntime.jsxs("header", { className: "cc-popup__header", children: [jsxRuntime.jsx("span", { children: title }), jsxRuntime.jsx("button", { "aria-label": "Close popup", className: "cc-popup__close", type: "button", onClick: close, children: closeIcon })] })) : null, jsxRuntime.jsx("div", { className: "cc-popup__body", children: children })] })] }));
1791
2042
  return popupContainer
1792
2043
  ? reactDom.createPortal(popupElement, popupContainer)
1793
2044
  : popupElement;
1794
2045
  }
1795
- function Tooltip({ content, children, animation, placement = "top", trigger = "hover", autoAdjust = true, closeOnEsc = true, closeOnOutsideClick = true, className, id, style, ...props }) {
2046
+ function Tooltip({ content, children, animation, placement = "top", trigger = "hover", autoAdjust = true, closeOnEsc = true, closeOnOutsideClick = true, portal = true, className, id, style, ...props }) {
1796
2047
  const rootRef = React.useRef(null);
1797
2048
  const contentRef = React.useRef(null);
1798
2049
  const generatedId = React.useId();
@@ -1800,6 +2051,7 @@ function Tooltip({ content, children, animation, placement = "top", trigger = "h
1800
2051
  const tooltipController = React.useMemo(() => new core.TooltipController(), []);
1801
2052
  const [open, setOpen] = React.useState(() => tooltipController.isOpen());
1802
2053
  const [safePlacement, setSafePlacement] = React.useState(placement);
2054
+ const [anchorStyle, setAnchorStyle] = React.useState(null);
1803
2055
  const motion = resolveAnimation(animation, "fade");
1804
2056
  React.useEffect(() => {
1805
2057
  const unsubscribe = tooltipController.subscribe((state) => {
@@ -1811,6 +2063,15 @@ function Tooltip({ content, children, animation, placement = "top", trigger = "h
1811
2063
  };
1812
2064
  }, [tooltipController]);
1813
2065
  const updatePlacement = React.useCallback(() => {
2066
+ if (rootRef.current) {
2067
+ const rect = rootRef.current.getBoundingClientRect();
2068
+ setAnchorStyle({
2069
+ height: rect.height,
2070
+ left: rect.left,
2071
+ top: rect.top,
2072
+ width: rect.width,
2073
+ });
2074
+ }
1814
2075
  if (!autoAdjust || !rootRef.current || !contentRef.current) {
1815
2076
  setSafePlacement(placement);
1816
2077
  return;
@@ -1833,7 +2094,8 @@ function Tooltip({ content, children, animation, placement = "top", trigger = "h
1833
2094
  return undefined;
1834
2095
  const handlePointerDown = (event) => {
1835
2096
  if (!closeOnOutsideClick ||
1836
- rootRef.current?.contains(event.target))
2097
+ rootRef.current?.contains(event.target) ||
2098
+ contentRef.current?.contains(event.target))
1837
2099
  return;
1838
2100
  tooltipController.close();
1839
2101
  };
@@ -1860,19 +2122,45 @@ function Tooltip({ content, children, animation, placement = "top", trigger = "h
1860
2122
  onMouseEnter: () => tooltipController.open(),
1861
2123
  onMouseLeave: () => tooltipController.close(),
1862
2124
  };
1863
- return (jsxRuntime.jsxs("span", { className: ["cc-tooltip", `cc-tooltip--${safePlacement}`, className]
1864
- .filter(Boolean)
1865
- .join(" "), "aria-describedby": open ? contentId : undefined, "data-animation": motion.name, "data-open": open, ref: rootRef, style: animationStyle(motion, style), tabIndex: trigger === "click" ? 0 : undefined, ...props, ...triggerProps, children: [children, jsxRuntime.jsx("span", { className: "cc-tooltip__content", id: contentId, ref: contentRef, role: "tooltip", children: content })] }));
2125
+ const rootClassName = [
2126
+ "cc-tooltip",
2127
+ `cc-tooltip--${safePlacement}`,
2128
+ className,
2129
+ ]
2130
+ .filter(Boolean)
2131
+ .join(" ");
2132
+ const tooltipContent = (jsxRuntime.jsx("span", { className: "cc-tooltip__content", id: contentId, ref: contentRef, role: "tooltip", children: content }));
2133
+ const rootNode = (jsxRuntime.jsxs("span", { className: rootClassName, "aria-describedby": open ? contentId : undefined, "data-animation": motion.name, "data-open": open, ref: rootRef, style: animationStyle(motion, style), tabIndex: trigger === "click" ? 0 : undefined, ...props, ...triggerProps, children: [children, portal ? null : tooltipContent] }));
2134
+ if (!portal || typeof document === "undefined")
2135
+ return rootNode;
2136
+ const portalNode = open || anchorStyle ? (jsxRuntime.jsx("span", { className: `${rootClassName} cc-tooltip--portal`, "data-animation": motion.name, "data-open": open, style: {
2137
+ ...animationStyle(motion),
2138
+ height: anchorStyle?.height ?? 0,
2139
+ left: anchorStyle?.left ?? -9999,
2140
+ top: anchorStyle?.top ?? -9999,
2141
+ width: anchorStyle?.width ?? 0,
2142
+ }, children: tooltipContent })) : null;
2143
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [rootNode, portalNode ? renderBodyPortal(portalNode) : null] }));
1866
2144
  }
1867
- function ToastViewport({ animation, manager = defaultToastManager, className = "cc-toast-viewport", position = "top-right", renderToast, style, ...props }) {
1868
- const [items, setItems] = React.useState(() => manager.getToasts());
2145
+ function ToastViewport({ animation, manager = defaultToastManager, className = "cc-toast-viewport", maxVisible, portal = false, position = "top-right", renderToast, style, ...props }) {
2146
+ const items = useToastItems(manager);
1869
2147
  const motion = resolveAnimation(animation, "slide");
1870
- const visibleItems = React.useMemo(() => items.filter((item) => item.position === position), [items, position]);
2148
+ const resolvedMaxVisible = normalizeToastMaxVisible(maxVisible);
2149
+ const visibleItems = React.useMemo(() => {
2150
+ const positionItems = items.filter((item) => item.position === position);
2151
+ const visible = positionItems.slice(Math.max(0, positionItems.length - resolvedMaxVisible));
2152
+ return isToastTopPosition(position) ? [...visible].reverse() : visible;
2153
+ }, [items, position, resolvedMaxVisible]);
1871
2154
  const renderedItems = useAnimatedToasts(visibleItems, motion.enabled ? motion.duration : 0);
1872
- React.useEffect(() => manager.subscribe(setItems), [manager]);
1873
- return (jsxRuntime.jsx("div", { className: [className, `cc-toast-viewport--${position}`]
2155
+ const setToastNode = useToastFlip(renderedItems, motion.enabled ? motion.duration : 0, motion.easing);
2156
+ const viewportNode = (jsxRuntime.jsx("div", { className: [className, `cc-toast-viewport--${position}`]
1874
2157
  .filter(Boolean)
1875
- .join(" "), role: "status", "aria-live": "polite", style: animationStyle(motion, style), ...props, children: renderedItems.map(({ item, state }) => (jsxRuntime.jsx(React.Fragment, { children: renderToast ? (renderToast(item, (id) => manager.dismiss(id), state)) : (jsxRuntime.jsxs("article", { className: `cc-toast cc-toast--${item.tone}`, "data-animation": motion.name, "data-state": state, children: [item.title ? (jsxRuntime.jsx("strong", { className: "cc-toast__title", children: item.title })) : null, jsxRuntime.jsx("span", { className: "cc-toast__message", children: item.message }), jsxRuntime.jsx("button", { "aria-label": "Dismiss toast", className: "cc-toast__close", type: "button", onClick: () => manager.dismiss(item.id), children: "x" })] })) }, item.id))) }));
2158
+ .join(" "), role: "status", "aria-live": "polite", style: animationStyle(motion, style), ...props, children: renderedItems.map(({ item, motion: isMotionActive, state }, index) => (jsxRuntime.jsx(React.Fragment, { children: renderToast ? (renderToast(item, (id) => manager.dismiss(id), state)) : (jsxRuntime.jsxs("article", { className: `cc-toast cc-toast--${item.tone}`, "data-animation": motion.name, "data-motion": isMotionActive ? "true" : "false", "data-state": state, ref: (node) => setToastNode(item.id, node), style: {
2159
+ "--cc-toast-stack-index": index,
2160
+ }, children: [item.title ? (jsxRuntime.jsx("strong", { className: "cc-toast__title", children: item.title })) : null, jsxRuntime.jsx("span", { className: "cc-toast__message", children: item.message }), jsxRuntime.jsx("button", { "aria-label": "Dismiss toast", className: "cc-toast__close", type: "button", onClick: () => manager.dismiss(item.id), children: jsxRuntime.jsx(ClassIcon, { name: "x" }) })] })) }, item.id))) }));
2161
+ return portal
2162
+ ? renderBodyPortal(viewportNode)
2163
+ : viewportNode;
1876
2164
  }
1877
2165
  function resolveTabsFlag(source, activeId) {
1878
2166
  if (!source)
@@ -2266,6 +2554,212 @@ function TiltCard({ children, className = "cc-tilt-card", contentClassName = "cc
2266
2554
  ...style,
2267
2555
  }, onPointerEnter: handlePointerEnter, onPointerLeave: handlePointerLeave, onPointerMove: handlePointerMove, ...props, children: jsxRuntime.jsxs("div", { className: surfaceClassName, children: [jsxRuntime.jsx("div", { className: contentClassName, children: children }), state.glare ? (jsxRuntime.jsx("span", { "aria-hidden": "true", className: glareClassName })) : null] }) }));
2268
2556
  }
2557
+ function OrbitalSphere({ animated = true, className = "cc-orbital-sphere", cycleDuration = 12000, depth = 0.72, disabled = false, duration = 9000, itemClassName = "cc-orbital-sphere__item", itemContentClassName = "cc-orbital-sphere__item-content", itemSize = 72, items, onItemClick, radius = "50%", renderItem, shellClassName = "cc-orbital-sphere__shell", size = "360px", spread = 0.86, stageClassName = "cc-orbital-sphere__stage", style, visibleCount = 10, ...props }) {
2558
+ const state = React.useMemo(() => new core.OrbitalSphereController({
2559
+ animated,
2560
+ cycleDuration,
2561
+ depth,
2562
+ disabled,
2563
+ duration,
2564
+ itemSize,
2565
+ items,
2566
+ radius,
2567
+ size,
2568
+ spread,
2569
+ visibleCount,
2570
+ }).getState(), [
2571
+ animated,
2572
+ cycleDuration,
2573
+ depth,
2574
+ disabled,
2575
+ duration,
2576
+ itemSize,
2577
+ items,
2578
+ radius,
2579
+ size,
2580
+ spread,
2581
+ visibleCount,
2582
+ ]);
2583
+ return (jsxRuntime.jsxs("div", { className: className, "data-animated": state.animated ? "true" : "false", "data-disabled": state.disabled ? "true" : "false", "data-overflow": state.items.length > state.visibleCount ? "true" : "false", style: { ...state.styleVars, ...style }, ...props, children: [jsxRuntime.jsx("span", { "aria-hidden": "true", className: shellClassName }), jsxRuntime.jsx("div", { className: stageClassName, children: state.items.map((item) => (jsxRuntime.jsx("button", { "aria-label": item.label, className: itemClassName, "data-tone": item.tone, disabled: state.disabled, style: {
2584
+ "--cc-orbital-index": item.index,
2585
+ ...item.styleVars,
2586
+ }, type: "button", onClick: (event) => onItemClick?.(item, event), children: jsxRuntime.jsx("span", { className: itemContentClassName, children: renderItem?.(item) ?? item.content }) }, item.id))) })] }));
2587
+ }
2588
+ function HeightTransition({ children, className = "cc-height-transition", contentClassName = "cc-height-transition__content", duration = 220, easing, expanded = false, mode = "auto", style, ...props }) {
2589
+ const contentRef = React.useRef(null);
2590
+ const controller = React.useMemo(() => new core.HeightTransitionController({ duration, easing, expanded, mode }), []);
2591
+ const [state, setState] = React.useState(() => controller.getState());
2592
+ const [height, setHeight] = React.useState(0);
2593
+ React.useEffect(() => {
2594
+ setState(controller.update({ duration, easing, expanded, mode }));
2595
+ }, [controller, duration, easing, expanded, mode]);
2596
+ React.useLayoutEffect(() => {
2597
+ const element = contentRef.current;
2598
+ if (!element || typeof ResizeObserver === "undefined") {
2599
+ setHeight(element?.scrollHeight ?? 0);
2600
+ return undefined;
2601
+ }
2602
+ const observer = new ResizeObserver(() => setHeight(element.scrollHeight));
2603
+ observer.observe(element);
2604
+ setHeight(element.scrollHeight);
2605
+ return () => observer.disconnect();
2606
+ }, [children]);
2607
+ return (jsxRuntime.jsx("div", { className: className, "data-expanded": state.expanded, "data-mode": state.mode, style: {
2608
+ "--cc-height-transition-duration": `${state.duration}ms`,
2609
+ "--cc-height-transition-easing": state.easing,
2610
+ "--cc-height-transition-height": `${height}px`,
2611
+ ...style,
2612
+ }, ...props, children: jsxRuntime.jsx("div", { className: contentClassName, ref: contentRef, children: children }) }));
2613
+ }
2614
+ function CodePreview({ className = "cc-code-preview", code, defaultExpanded = false, language = "Vue / TSX", onCopy, placement = "auto", strategy = "fixed", title = "示例源码", transitionDuration = 220, transitionEasing = "cubic-bezier(0.22, 0.8, 0.28, 1)", ...props }) {
2615
+ const rootRef = React.useRef(null);
2616
+ const panelRef = React.useRef(null);
2617
+ const controller = React.useMemo(() => new core.CodePreviewController({
2618
+ code,
2619
+ defaultExpanded,
2620
+ language,
2621
+ placement,
2622
+ title: String(title),
2623
+ }), []);
2624
+ const [state, setState] = React.useState(() => controller.getState());
2625
+ const [panelStyle, setPanelStyle] = React.useState();
2626
+ React.useEffect(() => {
2627
+ setState(controller.update({ code, language, placement, title: String(title) }));
2628
+ }, [code, controller, language, placement, title]);
2629
+ const updatePanelPosition = React.useCallback((estimate = false) => {
2630
+ const root = rootRef.current;
2631
+ const panel = panelRef.current;
2632
+ if (!root || (!panel && !estimate) || typeof window === "undefined")
2633
+ return undefined;
2634
+ const rect = root.getBoundingClientRect();
2635
+ const padding = 10;
2636
+ const gap = 10;
2637
+ const viewportWidth = document.documentElement.clientWidth || window.innerWidth;
2638
+ const viewportHeight = document.documentElement.clientHeight || window.innerHeight;
2639
+ const maxPanelHeight = Math.max(160, viewportHeight - padding * 2);
2640
+ const maxPanelWidth = Math.max(160, viewportWidth - padding * 2);
2641
+ const minPanelHeight = Math.min(160, maxPanelHeight);
2642
+ const panelContent = panel?.querySelector("pre");
2643
+ const measuredPanelHeight = Math.max(panel?.offsetHeight ?? 0, panel?.scrollHeight ?? 0, panelContent?.scrollHeight ?? 0, estimate ? 420 : 0);
2644
+ const preferredPanelHeight = Math.min(Math.max(160, measuredPanelHeight || 420), maxPanelHeight);
2645
+ const panelWidth = Math.min(Math.max(rect.width, panel?.offsetWidth || 720), maxPanelWidth);
2646
+ const availableBelow = Math.max(minPanelHeight, viewportHeight - rect.bottom - gap - padding);
2647
+ const availableAbove = Math.max(minPanelHeight, rect.top - gap - padding);
2648
+ const placementHeight = Math.min(preferredPanelHeight, Math.max(availableBelow, availableAbove));
2649
+ const next = controller.resolvePlacement({
2650
+ anchorBottom: rect.bottom,
2651
+ anchorLeft: rect.left,
2652
+ anchorRight: rect.right,
2653
+ anchorTop: rect.top,
2654
+ panelHeight: placementHeight,
2655
+ panelWidth,
2656
+ viewportHeight,
2657
+ viewportWidth,
2658
+ });
2659
+ setState(next);
2660
+ if (strategy !== "fixed") {
2661
+ setPanelStyle(undefined);
2662
+ return;
2663
+ }
2664
+ const clamp = (value, min, max) => Math.min(Math.max(min, value), max);
2665
+ const width = panelWidth;
2666
+ const maxLeft = Math.max(padding, viewportWidth - width - padding);
2667
+ const viewportPanelHeight = Math.min(preferredPanelHeight, maxPanelHeight);
2668
+ const maxTop = Math.max(padding, viewportHeight - viewportPanelHeight - padding);
2669
+ let left = clamp(rect.left, padding, maxLeft);
2670
+ let top = rect.bottom + gap;
2671
+ let maxHeight = Math.min(preferredPanelHeight, Math.max(minPanelHeight, viewportHeight - top - padding));
2672
+ let transformOrigin = "top left";
2673
+ if (next.resolvedPlacement === "top") {
2674
+ maxHeight = Math.min(preferredPanelHeight, availableAbove);
2675
+ top = Math.max(padding, rect.top - gap - maxHeight);
2676
+ transformOrigin = "bottom left";
2677
+ }
2678
+ else if (next.resolvedPlacement === "right") {
2679
+ left = clamp(rect.right + gap, padding, maxLeft);
2680
+ top = clamp(rect.top, padding, maxTop);
2681
+ maxHeight = viewportPanelHeight;
2682
+ transformOrigin = "top left";
2683
+ }
2684
+ else if (next.resolvedPlacement === "left") {
2685
+ left = clamp(rect.left - width - gap, padding, maxLeft);
2686
+ top = clamp(rect.top, padding, maxTop);
2687
+ maxHeight = viewportPanelHeight;
2688
+ transformOrigin = "top right";
2689
+ }
2690
+ setPanelStyle({
2691
+ left,
2692
+ maxHeight,
2693
+ top,
2694
+ transformOrigin,
2695
+ width,
2696
+ });
2697
+ return next;
2698
+ }, [controller, strategy]);
2699
+ const updatePanelPositionFromViewport = React.useCallback(() => {
2700
+ updatePanelPosition();
2701
+ }, [updatePanelPosition]);
2702
+ React.useLayoutEffect(() => {
2703
+ if (!state.expanded) {
2704
+ setPanelStyle(undefined);
2705
+ return undefined;
2706
+ }
2707
+ updatePanelPosition();
2708
+ window.addEventListener("resize", updatePanelPositionFromViewport);
2709
+ window.addEventListener("scroll", updatePanelPositionFromViewport, true);
2710
+ return () => {
2711
+ window.removeEventListener("resize", updatePanelPositionFromViewport);
2712
+ window.removeEventListener("scroll", updatePanelPositionFromViewport, true);
2713
+ };
2714
+ }, [
2715
+ code,
2716
+ state.expanded,
2717
+ updatePanelPosition,
2718
+ updatePanelPositionFromViewport,
2719
+ ]);
2720
+ React.useEffect(() => {
2721
+ if (!state.expanded || typeof document === "undefined")
2722
+ return undefined;
2723
+ const close = () => {
2724
+ setPanelStyle(undefined);
2725
+ setState(controller.close());
2726
+ };
2727
+ const closeOnOutside = (event) => {
2728
+ const target = event.target;
2729
+ if (target &&
2730
+ (rootRef.current?.contains(target) ||
2731
+ panelRef.current?.contains(target)))
2732
+ return;
2733
+ close();
2734
+ };
2735
+ const closeOnEscape = (event) => {
2736
+ if (event.key === "Escape")
2737
+ close();
2738
+ };
2739
+ document.addEventListener("pointerdown", closeOnOutside, true);
2740
+ document.addEventListener("keydown", closeOnEscape, true);
2741
+ return () => {
2742
+ document.removeEventListener("pointerdown", closeOnOutside, true);
2743
+ document.removeEventListener("keydown", closeOnEscape, true);
2744
+ };
2745
+ }, [controller, state.expanded]);
2746
+ const copy = async () => {
2747
+ await (onCopy ? onCopy(code) : navigator.clipboard?.writeText(code));
2748
+ setState(controller.copied());
2749
+ window.setTimeout(() => setState(controller.resetCopied()), 1200);
2750
+ };
2751
+ const panel = (jsxRuntime.jsx("div", { className: "cc-code-preview__panel", "data-placement": state.resolvedPlacement, "data-strategy": strategy, "data-expanded": state.expanded, ref: panelRef, style: panelStyle, children: jsxRuntime.jsx(HeightTransition, { className: "cc-height-transition cc-code-preview__transition", contentClassName: "cc-height-transition__content cc-code-preview__panel-content", duration: transitionDuration, easing: transitionEasing, expanded: state.expanded, mode: "auto", children: jsxRuntime.jsx("pre", { children: jsxRuntime.jsx("code", { children: state.code }) }) }) }));
2752
+ return (jsxRuntime.jsxs("div", { className: className, "data-expanded": state.expanded, "data-placement": state.resolvedPlacement, "data-strategy": strategy, ref: rootRef, ...props, children: [jsxRuntime.jsxs("div", { className: "cc-code-preview__bar", children: [jsxRuntime.jsxs("div", { className: "cc-code-preview__meta", children: [jsxRuntime.jsx("span", { className: "cc-code-preview__title", children: title }), jsxRuntime.jsx("span", { className: "cc-code-preview__lang", children: state.language })] }), jsxRuntime.jsxs("div", { className: "cc-code-preview__actions", children: [jsxRuntime.jsx("button", { type: "button", onClick: () => {
2753
+ const next = controller.toggle();
2754
+ if (!next.expanded) {
2755
+ setPanelStyle(undefined);
2756
+ setState(next);
2757
+ return;
2758
+ }
2759
+ setState(updatePanelPosition(true) ?? next);
2760
+ window.requestAnimationFrame(() => updatePanelPosition());
2761
+ }, children: state.expanded ? "收起" : "展开" }), jsxRuntime.jsx("button", { type: "button", onClick: () => void copy(), children: state.copied ? "已复制" : "复制" })] })] }), strategy === "fixed" ? renderBodyPortal(panel) : panel] }));
2762
+ }
2269
2763
  function QRCode({ value, size = 160, margin = 2, darkColor = "#1f1a2e", lightColor = "#ffffff", className = "cc-code cc-qr-code", errorCorrectionLevel = "M", errorText = "QR code unavailable", logoSrc, logoAlt = "QR code logo", logoSize = Math.round(size * 0.22), logoPadding = 6, logoRadius = 8, logoBackground = "#ffffff", renderError, ...props }) {
2270
2764
  const [svg, setSvg] = React.useState("");
2271
2765
  const [error, setError] = React.useState(null);
@@ -2701,7 +3195,7 @@ function signaturePointFromEvent(canvas, event) {
2701
3195
  y: event.clientY - rect.top,
2702
3196
  };
2703
3197
  }
2704
- const Signature = /*#__PURE__*/ React.forwardRef(function Signature({ backgroundColor, canvasClassName = "cc-signature__canvas", className = "cc-signature", clearText = core.getClassComponentsLocale().signatureClearText, disabled = false, errorClassName, exportType = "image/png", fieldClassName = "cc-field cc-signature-field", height = 220, initialValue, label, labelClassName = "cc-field__label", lineWidth = 3, name, penColor = "#111827", readOnly = false, rules, showToolbar = true, style, toolbarClassName = "cc-signature__toolbar", undoText = core.getClassComponentsLocale().signatureUndoText, validateOn, width = "100%", onChange, onClear, onEnd, onUndo, ...props }, ref) {
3198
+ const Signature = /*#__PURE__*/ React.forwardRef(function Signature({ backgroundColor, canvasClassName = "cc-signature__canvas", className = "cc-signature", clearText = core.getClassComponentsLocale().signatureClearText, disabled = false, errorClassName, exportType = "image/png", fieldClassName = "cc-field cc-signature-field", height = 220, initialValue, label, labelClassName = "cc-field__label", lineWidth = 3, name, penColor = "#1d2129", readOnly = false, rules, showToolbar = true, style, toolbarClassName = "cc-signature__toolbar", undoText = core.getClassComponentsLocale().signatureUndoText, validateOn, width = "100%", onChange, onClear, onEnd, onUndo, ...props }, ref) {
2705
3199
  const formContext = React.useContext(FormContext);
2706
3200
  const formState = React.useSyncExternalStore((listener) => formContext
2707
3201
  ? formContext.controller.subscribe(listener)
@@ -3484,6 +3978,28 @@ function Draggable({ axis = "xy", boundaryRef, children, className = "cc-draggab
3484
3978
  ? children({ dragging: state.dragging, position: state.position })
3485
3979
  : children }));
3486
3980
  }
3981
+ function readDragDropPreviewStyleVars(element) {
3982
+ if (!element || typeof window === "undefined")
3983
+ return {};
3984
+ const styles = window.getComputedStyle(element);
3985
+ const read = (name) => styles.getPropertyValue(name).trim();
3986
+ const slotDraggingBackground = read("--cc-drag-drop-slot-dragging-background");
3987
+ const slotDraggingBorderColor = read("--cc-drag-drop-slot-dragging-border-color");
3988
+ const previewBackground = read("--cc-drag-drop-preview-background");
3989
+ const previewBorderColor = read("--cc-drag-drop-preview-border-color");
3990
+ const values = {
3991
+ "--cc-drag-drop-preview-background": previewBackground && !previewBackground.includes("var(")
3992
+ ? previewBackground
3993
+ : slotDraggingBackground,
3994
+ "--cc-drag-drop-preview-border-color": previewBorderColor && !previewBorderColor.includes("var(")
3995
+ ? previewBorderColor
3996
+ : slotDraggingBorderColor,
3997
+ "--cc-drag-drop-preview-color": read("--cc-drag-drop-preview-color"),
3998
+ "--cc-drag-drop-preview-shadow": read("--cc-drag-drop-preview-shadow"),
3999
+ "--cc-drag-drop-motion-duration": read("--cc-drag-drop-motion-duration"),
4000
+ };
4001
+ return Object.fromEntries(Object.entries(values).filter(([, value]) => value.length > 0));
4002
+ }
3487
4003
  function reorderDropItems(items, fromIndex, toIndex, mode) {
3488
4004
  if (fromIndex < 0 || toIndex < 0 || fromIndex === toIndex)
3489
4005
  return [...items];
@@ -3750,6 +4266,7 @@ function DragDropBoard({ columns, items, mode = "insert", renderItem, className
3750
4266
  offsetY: event.clientY - rect.top,
3751
4267
  originX: rect.left,
3752
4268
  originY: rect.top,
4269
+ styleVars: readDragDropPreviewStyleVars(boardRef.current),
3753
4270
  width: rect.width,
3754
4271
  x: rect.left,
3755
4272
  y: rect.top,
@@ -3797,6 +4314,7 @@ function DragDropBoard({ columns, items, mode = "insert", renderItem, className
3797
4314
  }, onPointerUp: endDrag, onPointerCancel: cancelDrag, children: jsxRuntime.jsx("div", { className: "cc-drag-drop-board__item", children: renderItem(item, { dragging, over }) }) }, item.id));
3798
4315
  }), preview
3799
4316
  ? renderBodyPortal(jsxRuntime.jsx("div", { "aria-hidden": "true", className: "cc-drag-drop-board__preview", "data-dropping": preview.dropping, "data-returning": preview.returning, ref: previewRef, style: {
4317
+ ...preview.styleVars,
3800
4318
  height: preview.height,
3801
4319
  transform: `translate3d(${preview.x}px, ${preview.y}px, 0)`,
3802
4320
  width: preview.width,
@@ -4651,7 +5169,9 @@ function MasonryVirtualList({ columns, data, estimateSize = 220, gap = 16, heade
4651
5169
  item,
4652
5170
  }) }, item.key))) })] }) }));
4653
5171
  }
4654
- function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, defaultStickToBottom = true, enablePullUp = false, estimateSize = 72, getKey, height = 420, itemClassName = "cc-chat-virtual-list__item", itemContent, listClassName = "cc-chat-virtual-list__inner", appendScrollBehavior = "smooth", pullUpClassName = "cc-chat-virtual-list__pull-up", pullUpContent, pullUpLoading = false, pullUpMinDuration = 420, pullUpThreshold = 48, stickToBottomOnAppend = true, stickToBottomOnUpdate = true, topLoadingClassName = "cc-chat-virtual-list__top-loading", topLoadingContent = "正在加载历史消息...", topBuffer = 10, topThreshold = 96, className = "cc-chat-virtual-list", viewportClassName = "cc-chat-virtual-list__viewport", onPullUp, onReachTop, onRangeChange, style, ...props }, ref) {
5172
+ const CHAT_PREPEND_MOMENTUM_LOCK_MS = 420;
5173
+ const CHAT_PREPEND_STABILIZE_FRAMES = 24;
5174
+ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, defaultStickToBottom = true, enablePullUp = false, estimateSize = 72, getKey, height = 420, itemClassName = "cc-chat-virtual-list__item", itemContent, listClassName = "cc-chat-virtual-list__inner", appendScrollBehavior = "smooth", pullUpClassName = "cc-chat-virtual-list__pull-up", pullUpContent, pullUpLoading = false, pullUpMinDuration = 420, pullUpThreshold = 48, stickToBottomOnAppend = true, stickToBottomOnUpdate = true, topLoadingClassName = "cc-chat-virtual-list__top-loading", topLoadingContent = "", topBuffer = 10, topThreshold = 96, className = "cc-chat-virtual-list", viewportClassName = "cc-chat-virtual-list__viewport", onPullUp, onReachTop, onRangeChange, style, ...props }, ref) {
4655
5175
  const viewportRef = React.useRef(null);
4656
5176
  const pullUpRef = React.useRef(null);
4657
5177
  const observersRef = React.useRef(new Map());
@@ -4704,7 +5224,19 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
4704
5224
  }
4705
5225
  releaseTopLoadingLock();
4706
5226
  }, [releaseTopLoadingLock]);
4707
- const clearPendingPrependAnchor = React.useCallback(() => {
5227
+ const clearPendingPrependAnchor = React.useCallback((force = false) => {
5228
+ const pendingAnchor = pendingPrependAnchorRef.current;
5229
+ if (!force && pendingAnchor) {
5230
+ const remaining = pendingAnchor.releaseAt - Date.now();
5231
+ if (remaining > 0) {
5232
+ if (prependTimerRef.current !== undefined)
5233
+ window.clearTimeout(prependTimerRef.current);
5234
+ prependTimerRef.current = window.setTimeout(() => {
5235
+ clearPendingPrependAnchor(true);
5236
+ }, remaining);
5237
+ return;
5238
+ }
5239
+ }
4708
5240
  pendingPrependAnchorRef.current = null;
4709
5241
  if (prependStabilizeFrameRef.current !== undefined) {
4710
5242
  window.cancelAnimationFrame(prependStabilizeFrameRef.current);
@@ -4736,19 +5268,23 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
4736
5268
  if (prependStabilizeFrameRef.current !== undefined) {
4737
5269
  window.cancelAnimationFrame(prependStabilizeFrameRef.current);
4738
5270
  }
4739
- let remainingFrames = 8;
5271
+ let remainingFrames = CHAT_PREPEND_STABILIZE_FRAMES;
4740
5272
  const stabilize = () => {
4741
- if (!pendingPrependAnchorRef.current || remainingFrames <= 0) {
5273
+ const pendingAnchor = pendingPrependAnchorRef.current;
5274
+ if (!pendingAnchor) {
4742
5275
  prependStabilizeFrameRef.current = undefined;
4743
5276
  return;
4744
5277
  }
4745
5278
  applyPendingPrependAnchor();
4746
5279
  remainingFrames -= 1;
5280
+ if (remainingFrames <= 0 && pendingAnchor.releaseAt <= Date.now()) {
5281
+ prependStabilizeFrameRef.current = undefined;
5282
+ return;
5283
+ }
4747
5284
  prependStabilizeFrameRef.current =
4748
5285
  window.requestAnimationFrame(stabilize);
4749
5286
  };
4750
- prependStabilizeFrameRef.current =
4751
- window.requestAnimationFrame(stabilize);
5287
+ prependStabilizeFrameRef.current = window.requestAnimationFrame(stabilize);
4752
5288
  }, [applyPendingPrependAnchor]);
4753
5289
  const scheduleTopLoadingFallback = React.useCallback(() => {
4754
5290
  if (topLoadingFallbackTimerRef.current !== undefined) {
@@ -4895,6 +5431,7 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
4895
5431
  anchorOffset: previousAnchor.offset,
4896
5432
  measuredKeys: new Set(),
4897
5433
  prependKeys: new Set(keys.slice(0, prependCount)),
5434
+ releaseAt: Date.now() + CHAT_PREPEND_MOMENTUM_LOCK_MS,
4898
5435
  targetScrollTop: nextScrollTop,
4899
5436
  }
4900
5437
  : null;
@@ -5061,12 +5598,19 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
5061
5598
  React.useEffect(() => {
5062
5599
  onRangeChange?.({ endIndex: range.endIndex, startIndex: range.startIndex });
5063
5600
  }, [onRangeChange, range.endIndex, range.startIndex]);
5601
+ const hasPendingKeySync = () => {
5602
+ const previousKeys = previousKeysRef.current;
5603
+ return (previousKeys.length !== keys.length ||
5604
+ previousKeys.some((itemKey, index) => !Object.is(itemKey, keys[index])));
5605
+ };
5064
5606
  const observeItem = (index, key, element) => {
5065
5607
  observersRef.current.get(key)?.disconnect();
5066
5608
  observersRef.current.delete(key);
5067
5609
  if (!element)
5068
5610
  return;
5069
5611
  const measure = () => {
5612
+ if (!pendingPrependAnchorRef.current && hasPendingKeySync())
5613
+ return;
5070
5614
  const previousTotal = listControllerRef.current.getTotalSize();
5071
5615
  const previousItem = listControllerRef.current.getItem(index);
5072
5616
  const viewport = viewportRef.current;
@@ -5129,7 +5673,7 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
5129
5673
  return (jsxRuntime.jsxs("div", { className: className, "data-top-loading": topLoadingPending ? "true" : undefined, style: {
5130
5674
  "--cc-chat-virtual-list-height": resolvedHeight,
5131
5675
  ...style,
5132
- }, ...props, children: [jsxRuntime.jsx("div", { "aria-hidden": !topLoadingPending, className: topLoadingClassName, "data-active": topLoadingPending ? "true" : "false", role: topLoadingPending ? "status" : undefined, children: topLoadingContent }), jsxRuntime.jsxs("div", { className: viewportClassName, "data-top-loading": topLoadingPending ? "true" : undefined, ref: viewportRef, onScroll: (event) => {
5676
+ }, ...props, children: [jsxRuntime.jsx(Loading, { "aria-hidden": !topLoadingPending, className: topLoadingClassName, "data-active": topLoadingPending ? "true" : "false", role: topLoadingPending ? "status" : undefined, text: topLoadingContent }), jsxRuntime.jsxs("div", { className: viewportClassName, "data-top-loading": topLoadingPending ? "true" : undefined, ref: viewportRef, onScroll: (event) => {
5133
5677
  if (pendingPrependAnchorRef.current) {
5134
5678
  const stabilized = applyPendingPrependAnchor();
5135
5679
  if (stabilized)
@@ -5904,10 +6448,18 @@ Object.defineProperty(exports, "CanvasImageController", {
5904
6448
  enumerable: true,
5905
6449
  get: function () { return core.CanvasImageController; }
5906
6450
  });
6451
+ Object.defineProperty(exports, "ChatTextareaController", {
6452
+ enumerable: true,
6453
+ get: function () { return core.ChatTextareaController; }
6454
+ });
5907
6455
  Object.defineProperty(exports, "ChatVirtualListController", {
5908
6456
  enumerable: true,
5909
6457
  get: function () { return core.ChatVirtualListController; }
5910
6458
  });
6459
+ Object.defineProperty(exports, "CodePreviewController", {
6460
+ enumerable: true,
6461
+ get: function () { return core.CodePreviewController; }
6462
+ });
5911
6463
  Object.defineProperty(exports, "ColorPickerController", {
5912
6464
  enumerable: true,
5913
6465
  get: function () { return core.ColorPickerController; }
@@ -5964,6 +6516,10 @@ Object.defineProperty(exports, "GradientTextController", {
5964
6516
  enumerable: true,
5965
6517
  get: function () { return core.GradientTextController; }
5966
6518
  });
6519
+ Object.defineProperty(exports, "HeightTransitionController", {
6520
+ enumerable: true,
6521
+ get: function () { return core.HeightTransitionController; }
6522
+ });
5967
6523
  Object.defineProperty(exports, "LazyImageController", {
5968
6524
  enumerable: true,
5969
6525
  get: function () { return core.LazyImageController; }
@@ -5976,6 +6532,10 @@ Object.defineProperty(exports, "MasonryVirtualListController", {
5976
6532
  enumerable: true,
5977
6533
  get: function () { return core.MasonryVirtualListController; }
5978
6534
  });
6535
+ Object.defineProperty(exports, "MenuController", {
6536
+ enumerable: true,
6537
+ get: function () { return core.MenuController; }
6538
+ });
5979
6539
  Object.defineProperty(exports, "ModalController", {
5980
6540
  enumerable: true,
5981
6541
  get: function () { return core.ModalController; }
@@ -5988,6 +6548,10 @@ Object.defineProperty(exports, "NovelReaderController", {
5988
6548
  enumerable: true,
5989
6549
  get: function () { return core.NovelReaderController; }
5990
6550
  });
6551
+ Object.defineProperty(exports, "OrbitalSphereController", {
6552
+ enumerable: true,
6553
+ get: function () { return core.OrbitalSphereController; }
6554
+ });
5991
6555
  Object.defineProperty(exports, "PaginationController", {
5992
6556
  enumerable: true,
5993
6557
  get: function () { return core.PaginationController; }
@@ -6101,10 +6665,12 @@ exports.Button = Button;
6101
6665
  exports.Calendar = Calendar;
6102
6666
  exports.CanvasEditor = CanvasEditor;
6103
6667
  exports.CanvasImage = CanvasImage;
6668
+ exports.ChatTextarea = ChatTextarea;
6104
6669
  exports.ChatVirtualList = ChatVirtualList;
6105
6670
  exports.Checkbox = Checkbox;
6106
6671
  exports.Checked = Checked;
6107
6672
  exports.ClassConfigProvider = ClassConfigProvider;
6673
+ exports.CodePreview = CodePreview;
6108
6674
  exports.ColorPicker = ColorPicker;
6109
6675
  exports.ComicReader = ComicReader;
6110
6676
  exports.ConfigTable = ConfigTable;
@@ -6122,16 +6688,19 @@ exports.FilePreview = FilePreview;
6122
6688
  exports.FloatingBall = FloatingBall;
6123
6689
  exports.FormProvider = FormProvider;
6124
6690
  exports.GradientText = GradientText;
6691
+ exports.HeightTransition = HeightTransition;
6125
6692
  exports.Input = Input;
6126
6693
  exports.LazyImage = LazyImage;
6127
6694
  exports.LiveRoom = LiveRoom;
6128
6695
  exports.Loading = Loading;
6129
6696
  exports.Marquee = Marquee;
6130
6697
  exports.MasonryVirtualList = MasonryVirtualList;
6698
+ exports.Menu = Menu;
6131
6699
  exports.Modal = Modal;
6132
6700
  exports.MultiColumnPicker = MultiColumnPicker;
6133
6701
  exports.NovelReader = NovelReader;
6134
6702
  exports.NumberInput = NumberInput;
6703
+ exports.OrbitalSphere = OrbitalSphere;
6135
6704
  exports.Pagination = Pagination;
6136
6705
  exports.PasswordInput = PasswordInput;
6137
6706
  exports.Popconfirm = Popconfirm;