@class-kit/react 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 +10 -2
  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 +103 -0
  23. package/dist/components/chat-textarea.cjs.map +1 -0
  24. package/dist/components/chat-textarea.d.ts +3 -0
  25. package/dist/components/chat-textarea.d.ts.map +1 -0
  26. package/dist/components/chat-textarea.js +101 -0
  27. package/dist/components/chat-textarea.js.map +1 -0
  28. package/dist/components/chat-virtual-list.cjs +91 -6
  29. package/dist/components/chat-virtual-list.cjs.map +1 -1
  30. package/dist/components/chat-virtual-list.js +91 -6
  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 +190 -0
  37. package/dist/components/code-preview.cjs.map +1 -0
  38. package/dist/components/code-preview.d.ts +3 -0
  39. package/dist/components/code-preview.d.ts.map +1 -0
  40. package/dist/components/code-preview.js +188 -0
  41. package/dist/components/code-preview.js.map +1 -0
  42. package/dist/components/color-picker.cjs +2 -2
  43. package/dist/components/color-picker.cjs.map +1 -1
  44. package/dist/components/color-picker.js +2 -2
  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 +35 -0
  83. package/dist/components/height-transition.cjs.map +1 -0
  84. package/dist/components/height-transition.d.ts +3 -0
  85. package/dist/components/height-transition.d.ts.map +1 -0
  86. package/dist/components/height-transition.js +33 -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 +100 -0
  101. package/dist/components/menu.cjs.map +1 -0
  102. package/dist/components/menu.d.ts +3 -0
  103. package/dist/components/menu.d.ts.map +1 -0
  104. package/dist/components/menu.js +98 -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 +40 -0
  115. package/dist/components/orbital-sphere.cjs.map +1 -0
  116. package/dist/components/orbital-sphere.d.ts +3 -0
  117. package/dist/components/orbital-sphere.d.ts.map +1 -0
  118. package/dist/components/orbital-sphere.js +38 -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 +40 -6
  125. package/dist/components/popconfirm.cjs.map +1 -1
  126. package/dist/components/popconfirm.js +41 -7
  127. package/dist/components/popconfirm.js.map +1 -1
  128. package/dist/components/popup.cjs +2 -1
  129. package/dist/components/popup.cjs.map +1 -1
  130. package/dist/components/popup.js +2 -1
  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 +146 -14
  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 +144 -15
  173. package/dist/components/toast.js.map +1 -1
  174. package/dist/components/tooltip.cjs +38 -5
  175. package/dist/components/tooltip.cjs.map +1 -1
  176. package/dist/components/tooltip.js +39 -6
  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-jqLjtD6M.js → import-transform-Cw4K2Iky.js} +7 -1
  195. package/dist/import-transform-Cw4K2Iky.js.map +1 -0
  196. package/dist/{import-transform-DIRVOYvz.js → import-transform-ieMdZBuN.js} +7 -1
  197. package/dist/import-transform-ieMdZBuN.js.map +1 -0
  198. package/dist/import-transform.d.ts.map +1 -1
  199. package/dist/index.cjs +657 -35
  200. package/dist/index.cjs.map +1 -1
  201. package/dist/index.d.ts +71 -8
  202. package/dist/index.d.ts.map +1 -1
  203. package/dist/index.js +635 -38
  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-DIRVOYvz.js.map +0 -1
  270. package/dist/import-transform-jqLjtD6M.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
@@ -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());
@@ -4669,6 +5189,7 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
4669
5189
  const bottomFrameRef = React.useRef();
4670
5190
  const bottomTimerRef = React.useRef();
4671
5191
  const prependFrameRef = React.useRef();
5192
+ const prependStabilizeFrameRef = React.useRef();
4672
5193
  const prependTimerRef = React.useRef();
4673
5194
  const topLoadingFallbackTimerRef = React.useRef();
4674
5195
  const chatControllerRef = React.useRef(new core.ChatVirtualListController({ bottomThreshold, topThreshold }));
@@ -4703,14 +5224,68 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
4703
5224
  }
4704
5225
  releaseTopLoadingLock();
4705
5226
  }, [releaseTopLoadingLock]);
4706
- 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
+ }
4707
5240
  pendingPrependAnchorRef.current = null;
5241
+ if (prependStabilizeFrameRef.current !== undefined) {
5242
+ window.cancelAnimationFrame(prependStabilizeFrameRef.current);
5243
+ prependStabilizeFrameRef.current = undefined;
5244
+ }
4708
5245
  if (prependTimerRef.current !== undefined) {
4709
5246
  window.clearTimeout(prependTimerRef.current);
4710
5247
  prependTimerRef.current = undefined;
4711
5248
  }
4712
5249
  maybeReleaseTopLoadingLock();
4713
5250
  }, [maybeReleaseTopLoadingLock]);
5251
+ const applyPendingPrependAnchor = React.useCallback(() => {
5252
+ const pendingAnchor = pendingPrependAnchorRef.current;
5253
+ const viewport = viewportRef.current;
5254
+ if (!pendingAnchor || !viewport)
5255
+ return false;
5256
+ const anchorIndex = keys.findIndex((itemKey) => Object.is(itemKey, pendingAnchor.anchorKey));
5257
+ const nextScrollTop = anchorIndex >= 0
5258
+ ? Math.max(0, listControllerRef.current.getItem(anchorIndex).start -
5259
+ pendingAnchor.anchorOffset)
5260
+ : pendingAnchor.targetScrollTop;
5261
+ viewport.scrollTop = nextScrollTop;
5262
+ setScrollOffset(nextScrollTop);
5263
+ previousScrollTopRef.current = nextScrollTop;
5264
+ previousScrollHeightRef.current = viewport.scrollHeight;
5265
+ return true;
5266
+ }, [keys]);
5267
+ const schedulePrependStabilization = React.useCallback(() => {
5268
+ if (prependStabilizeFrameRef.current !== undefined) {
5269
+ window.cancelAnimationFrame(prependStabilizeFrameRef.current);
5270
+ }
5271
+ let remainingFrames = CHAT_PREPEND_STABILIZE_FRAMES;
5272
+ const stabilize = () => {
5273
+ const pendingAnchor = pendingPrependAnchorRef.current;
5274
+ if (!pendingAnchor) {
5275
+ prependStabilizeFrameRef.current = undefined;
5276
+ return;
5277
+ }
5278
+ applyPendingPrependAnchor();
5279
+ remainingFrames -= 1;
5280
+ if (remainingFrames <= 0 && pendingAnchor.releaseAt <= Date.now()) {
5281
+ prependStabilizeFrameRef.current = undefined;
5282
+ return;
5283
+ }
5284
+ prependStabilizeFrameRef.current =
5285
+ window.requestAnimationFrame(stabilize);
5286
+ };
5287
+ prependStabilizeFrameRef.current = window.requestAnimationFrame(stabilize);
5288
+ }, [applyPendingPrependAnchor]);
4714
5289
  const scheduleTopLoadingFallback = React.useCallback(() => {
4715
5290
  if (topLoadingFallbackTimerRef.current !== undefined) {
4716
5291
  window.clearTimeout(topLoadingFallbackTimerRef.current);
@@ -4856,8 +5431,12 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
4856
5431
  anchorOffset: previousAnchor.offset,
4857
5432
  measuredKeys: new Set(),
4858
5433
  prependKeys: new Set(keys.slice(0, prependCount)),
5434
+ releaseAt: Date.now() + CHAT_PREPEND_MOMENTUM_LOCK_MS,
5435
+ targetScrollTop: nextScrollTop,
4859
5436
  }
4860
5437
  : null;
5438
+ if (pendingPrependAnchorRef.current)
5439
+ schedulePrependStabilization();
4861
5440
  if (prependFrameRef.current !== undefined)
4862
5441
  window.cancelAnimationFrame(prependFrameRef.current);
4863
5442
  if (prependTimerRef.current !== undefined)
@@ -4907,6 +5486,7 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
4907
5486
  viewportHeight,
4908
5487
  scrollToBottom,
4909
5488
  clearPendingPrependAnchor,
5489
+ schedulePrependStabilization,
4910
5490
  maybeReleaseTopLoadingLock,
4911
5491
  ]);
4912
5492
  React.useEffect(() => {
@@ -4937,6 +5517,8 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
4937
5517
  window.clearTimeout(bottomTimerRef.current);
4938
5518
  if (prependFrameRef.current !== undefined)
4939
5519
  window.cancelAnimationFrame(prependFrameRef.current);
5520
+ if (prependStabilizeFrameRef.current !== undefined)
5521
+ window.cancelAnimationFrame(prependStabilizeFrameRef.current);
4940
5522
  if (prependTimerRef.current !== undefined)
4941
5523
  window.clearTimeout(prependTimerRef.current);
4942
5524
  if (topLoadingFallbackTimerRef.current !== undefined)
@@ -5016,12 +5598,19 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
5016
5598
  React.useEffect(() => {
5017
5599
  onRangeChange?.({ endIndex: range.endIndex, startIndex: range.startIndex });
5018
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
+ };
5019
5606
  const observeItem = (index, key, element) => {
5020
5607
  observersRef.current.get(key)?.disconnect();
5021
5608
  observersRef.current.delete(key);
5022
5609
  if (!element)
5023
5610
  return;
5024
5611
  const measure = () => {
5612
+ if (!pendingPrependAnchorRef.current && hasPendingKeySync())
5613
+ return;
5025
5614
  const previousTotal = listControllerRef.current.getTotalSize();
5026
5615
  const previousItem = listControllerRef.current.getItem(index);
5027
5616
  const viewport = viewportRef.current;
@@ -5040,12 +5629,15 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
5040
5629
  const anchorItem = listControllerRef.current.getItem(anchorIndex);
5041
5630
  const nextItem = listControllerRef.current.getItem(index);
5042
5631
  const delta = nextItem.size - previousItem.size;
5043
- viewport.scrollTop = Math.max(0, index < anchorIndex && delta !== 0
5632
+ const nextScrollTop = Math.max(0, index < anchorIndex && delta !== 0
5044
5633
  ? previousScrollTop + delta
5045
5634
  : anchorItem.start - pendingAnchor.anchorOffset);
5046
- setScrollOffset(viewport.scrollTop);
5047
- previousScrollTopRef.current = viewport.scrollTop;
5635
+ pendingAnchor.targetScrollTop = nextScrollTop;
5636
+ viewport.scrollTop = nextScrollTop;
5637
+ setScrollOffset(nextScrollTop);
5638
+ previousScrollTopRef.current = nextScrollTop;
5048
5639
  previousScrollHeightRef.current = viewport.scrollHeight;
5640
+ schedulePrependStabilization();
5049
5641
  }
5050
5642
  if (pendingAnchor.measuredKeys.size >= pendingAnchor.prependKeys.size) {
5051
5643
  clearPendingPrependAnchor();
@@ -5081,7 +5673,12 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
5081
5673
  return (jsxRuntime.jsxs("div", { className: className, "data-top-loading": topLoadingPending ? "true" : undefined, style: {
5082
5674
  "--cc-chat-virtual-list-height": resolvedHeight,
5083
5675
  ...style,
5084
- }, ...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) => {
5677
+ if (pendingPrependAnchorRef.current) {
5678
+ const stabilized = applyPendingPrependAnchor();
5679
+ if (stabilized)
5680
+ return;
5681
+ }
5085
5682
  const nextScrollTop = event.currentTarget.scrollTop;
5086
5683
  previousScrollTopRef.current = nextScrollTop;
5087
5684
  previousScrollHeightRef.current = event.currentTarget.scrollHeight;
@@ -5851,10 +6448,18 @@ Object.defineProperty(exports, "CanvasImageController", {
5851
6448
  enumerable: true,
5852
6449
  get: function () { return core.CanvasImageController; }
5853
6450
  });
6451
+ Object.defineProperty(exports, "ChatTextareaController", {
6452
+ enumerable: true,
6453
+ get: function () { return core.ChatTextareaController; }
6454
+ });
5854
6455
  Object.defineProperty(exports, "ChatVirtualListController", {
5855
6456
  enumerable: true,
5856
6457
  get: function () { return core.ChatVirtualListController; }
5857
6458
  });
6459
+ Object.defineProperty(exports, "CodePreviewController", {
6460
+ enumerable: true,
6461
+ get: function () { return core.CodePreviewController; }
6462
+ });
5858
6463
  Object.defineProperty(exports, "ColorPickerController", {
5859
6464
  enumerable: true,
5860
6465
  get: function () { return core.ColorPickerController; }
@@ -5911,6 +6516,10 @@ Object.defineProperty(exports, "GradientTextController", {
5911
6516
  enumerable: true,
5912
6517
  get: function () { return core.GradientTextController; }
5913
6518
  });
6519
+ Object.defineProperty(exports, "HeightTransitionController", {
6520
+ enumerable: true,
6521
+ get: function () { return core.HeightTransitionController; }
6522
+ });
5914
6523
  Object.defineProperty(exports, "LazyImageController", {
5915
6524
  enumerable: true,
5916
6525
  get: function () { return core.LazyImageController; }
@@ -5923,6 +6532,10 @@ Object.defineProperty(exports, "MasonryVirtualListController", {
5923
6532
  enumerable: true,
5924
6533
  get: function () { return core.MasonryVirtualListController; }
5925
6534
  });
6535
+ Object.defineProperty(exports, "MenuController", {
6536
+ enumerable: true,
6537
+ get: function () { return core.MenuController; }
6538
+ });
5926
6539
  Object.defineProperty(exports, "ModalController", {
5927
6540
  enumerable: true,
5928
6541
  get: function () { return core.ModalController; }
@@ -5935,6 +6548,10 @@ Object.defineProperty(exports, "NovelReaderController", {
5935
6548
  enumerable: true,
5936
6549
  get: function () { return core.NovelReaderController; }
5937
6550
  });
6551
+ Object.defineProperty(exports, "OrbitalSphereController", {
6552
+ enumerable: true,
6553
+ get: function () { return core.OrbitalSphereController; }
6554
+ });
5938
6555
  Object.defineProperty(exports, "PaginationController", {
5939
6556
  enumerable: true,
5940
6557
  get: function () { return core.PaginationController; }
@@ -6048,10 +6665,12 @@ exports.Button = Button;
6048
6665
  exports.Calendar = Calendar;
6049
6666
  exports.CanvasEditor = CanvasEditor;
6050
6667
  exports.CanvasImage = CanvasImage;
6668
+ exports.ChatTextarea = ChatTextarea;
6051
6669
  exports.ChatVirtualList = ChatVirtualList;
6052
6670
  exports.Checkbox = Checkbox;
6053
6671
  exports.Checked = Checked;
6054
6672
  exports.ClassConfigProvider = ClassConfigProvider;
6673
+ exports.CodePreview = CodePreview;
6055
6674
  exports.ColorPicker = ColorPicker;
6056
6675
  exports.ComicReader = ComicReader;
6057
6676
  exports.ConfigTable = ConfigTable;
@@ -6069,16 +6688,19 @@ exports.FilePreview = FilePreview;
6069
6688
  exports.FloatingBall = FloatingBall;
6070
6689
  exports.FormProvider = FormProvider;
6071
6690
  exports.GradientText = GradientText;
6691
+ exports.HeightTransition = HeightTransition;
6072
6692
  exports.Input = Input;
6073
6693
  exports.LazyImage = LazyImage;
6074
6694
  exports.LiveRoom = LiveRoom;
6075
6695
  exports.Loading = Loading;
6076
6696
  exports.Marquee = Marquee;
6077
6697
  exports.MasonryVirtualList = MasonryVirtualList;
6698
+ exports.Menu = Menu;
6078
6699
  exports.Modal = Modal;
6079
6700
  exports.MultiColumnPicker = MultiColumnPicker;
6080
6701
  exports.NovelReader = NovelReader;
6081
6702
  exports.NumberInput = NumberInput;
6703
+ exports.OrbitalSphere = OrbitalSphere;
6082
6704
  exports.Pagination = Pagination;
6083
6705
  exports.PasswordInput = PasswordInput;
6084
6706
  exports.Popconfirm = Popconfirm;