@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.
- package/CHANGELOG.md +7 -0
- package/LICENSE +20 -2
- package/README.md +10 -2
- package/dist/components/affix.cjs.map +1 -1
- package/dist/components/affix.js.map +1 -1
- package/dist/components/backtop.cjs.map +1 -1
- package/dist/components/backtop.js.map +1 -1
- package/dist/components/badge.cjs.map +1 -1
- package/dist/components/badge.js.map +1 -1
- package/dist/components/barcode.cjs.map +1 -1
- package/dist/components/barcode.js.map +1 -1
- package/dist/components/breadcrumb.cjs.map +1 -1
- package/dist/components/breadcrumb.js.map +1 -1
- package/dist/components/button.cjs.map +1 -1
- package/dist/components/button.js.map +1 -1
- package/dist/components/calendar.cjs.map +1 -1
- package/dist/components/calendar.js.map +1 -1
- package/dist/components/canvas-editor.cjs.map +1 -1
- package/dist/components/canvas-editor.js.map +1 -1
- package/dist/components/canvas-image.cjs.map +1 -1
- package/dist/components/canvas-image.js.map +1 -1
- package/dist/components/chat-textarea.cjs +103 -0
- package/dist/components/chat-textarea.cjs.map +1 -0
- package/dist/components/chat-textarea.d.ts +3 -0
- package/dist/components/chat-textarea.d.ts.map +1 -0
- package/dist/components/chat-textarea.js +101 -0
- package/dist/components/chat-textarea.js.map +1 -0
- package/dist/components/chat-virtual-list.cjs +91 -6
- package/dist/components/chat-virtual-list.cjs.map +1 -1
- package/dist/components/chat-virtual-list.js +91 -6
- package/dist/components/chat-virtual-list.js.map +1 -1
- package/dist/components/checkbox.cjs.map +1 -1
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/checked.cjs.map +1 -1
- package/dist/components/checked.js.map +1 -1
- package/dist/components/code-preview.cjs +190 -0
- package/dist/components/code-preview.cjs.map +1 -0
- package/dist/components/code-preview.d.ts +3 -0
- package/dist/components/code-preview.d.ts.map +1 -0
- package/dist/components/code-preview.js +188 -0
- package/dist/components/code-preview.js.map +1 -0
- package/dist/components/color-picker.cjs +2 -2
- package/dist/components/color-picker.cjs.map +1 -1
- package/dist/components/color-picker.js +2 -2
- package/dist/components/color-picker.js.map +1 -1
- package/dist/components/comic-reader.cjs.map +1 -1
- package/dist/components/comic-reader.js.map +1 -1
- package/dist/components/config-provider.cjs.map +1 -1
- package/dist/components/config-provider.js.map +1 -1
- package/dist/components/config-table.cjs.map +1 -1
- package/dist/components/config-table.js.map +1 -1
- package/dist/components/countdown.cjs.map +1 -1
- package/dist/components/countdown.js.map +1 -1
- package/dist/components/danmaku.cjs.map +1 -1
- package/dist/components/danmaku.js.map +1 -1
- package/dist/components/date-picker.cjs.map +1 -1
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/date-range-picker.cjs.map +1 -1
- package/dist/components/date-range-picker.js.map +1 -1
- package/dist/components/design-effect.cjs.map +1 -1
- package/dist/components/design-effect.js.map +1 -1
- package/dist/components/drag-drop-board.cjs +24 -0
- package/dist/components/drag-drop-board.cjs.map +1 -1
- package/dist/components/drag-drop-board.js +24 -0
- package/dist/components/drag-drop-board.js.map +1 -1
- package/dist/components/draggable.cjs.map +1 -1
- package/dist/components/draggable.js.map +1 -1
- package/dist/components/ellipsis-text.cjs.map +1 -1
- package/dist/components/ellipsis-text.js.map +1 -1
- package/dist/components/empty.cjs.map +1 -1
- package/dist/components/empty.js.map +1 -1
- package/dist/components/field.cjs.map +1 -1
- package/dist/components/field.js.map +1 -1
- package/dist/components/file-preview.cjs.map +1 -1
- package/dist/components/file-preview.js.map +1 -1
- package/dist/components/floating-ball.cjs.map +1 -1
- package/dist/components/floating-ball.js.map +1 -1
- package/dist/components/form.cjs.map +1 -1
- package/dist/components/form.js.map +1 -1
- package/dist/components/gradient-text.cjs.map +1 -1
- package/dist/components/gradient-text.js.map +1 -1
- package/dist/components/height-transition.cjs +35 -0
- package/dist/components/height-transition.cjs.map +1 -0
- package/dist/components/height-transition.d.ts +3 -0
- package/dist/components/height-transition.d.ts.map +1 -0
- package/dist/components/height-transition.js +33 -0
- package/dist/components/height-transition.js.map +1 -0
- package/dist/components/input.cjs.map +1 -1
- package/dist/components/input.js.map +1 -1
- package/dist/components/lazy-image.cjs.map +1 -1
- package/dist/components/lazy-image.js.map +1 -1
- package/dist/components/live-room.cjs.map +1 -1
- package/dist/components/live-room.js.map +1 -1
- package/dist/components/loading.cjs.map +1 -1
- package/dist/components/loading.js.map +1 -1
- package/dist/components/marquee.cjs.map +1 -1
- package/dist/components/marquee.js.map +1 -1
- package/dist/components/masonry-virtual-list.cjs.map +1 -1
- package/dist/components/masonry-virtual-list.js.map +1 -1
- package/dist/components/menu.cjs +100 -0
- package/dist/components/menu.cjs.map +1 -0
- package/dist/components/menu.d.ts +3 -0
- package/dist/components/menu.d.ts.map +1 -0
- package/dist/components/menu.js +98 -0
- package/dist/components/menu.js.map +1 -0
- package/dist/components/modal.cjs.map +1 -1
- package/dist/components/modal.js.map +1 -1
- package/dist/components/multi-column-picker.cjs.map +1 -1
- package/dist/components/multi-column-picker.js.map +1 -1
- package/dist/components/novel-reader.cjs.map +1 -1
- package/dist/components/novel-reader.js.map +1 -1
- package/dist/components/number-input.cjs.map +1 -1
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/orbital-sphere.cjs +40 -0
- package/dist/components/orbital-sphere.cjs.map +1 -0
- package/dist/components/orbital-sphere.d.ts +3 -0
- package/dist/components/orbital-sphere.d.ts.map +1 -0
- package/dist/components/orbital-sphere.js +38 -0
- package/dist/components/orbital-sphere.js.map +1 -0
- package/dist/components/pagination.cjs.map +1 -1
- package/dist/components/pagination.js.map +1 -1
- package/dist/components/password-input.cjs.map +1 -1
- package/dist/components/password-input.js.map +1 -1
- package/dist/components/popconfirm.cjs +40 -6
- package/dist/components/popconfirm.cjs.map +1 -1
- package/dist/components/popconfirm.js +41 -7
- package/dist/components/popconfirm.js.map +1 -1
- package/dist/components/popup.cjs +2 -1
- package/dist/components/popup.cjs.map +1 -1
- package/dist/components/popup.js +2 -1
- package/dist/components/popup.js.map +1 -1
- package/dist/components/progress-bar.cjs.map +1 -1
- package/dist/components/progress-bar.js.map +1 -1
- package/dist/components/qr-code.cjs.map +1 -1
- package/dist/components/qr-code.js.map +1 -1
- package/dist/components/radio-group.cjs.map +1 -1
- package/dist/components/radio-group.js.map +1 -1
- package/dist/components/rating.cjs.map +1 -1
- package/dist/components/rating.js.map +1 -1
- package/dist/components/rolling-number.cjs.map +1 -1
- package/dist/components/rolling-number.js.map +1 -1
- package/dist/components/select.cjs.map +1 -1
- package/dist/components/select.js.map +1 -1
- package/dist/components/signature.cjs +1 -1
- package/dist/components/signature.cjs.map +1 -1
- package/dist/components/signature.js +1 -1
- package/dist/components/signature.js.map +1 -1
- package/dist/components/skeleton.cjs.map +1 -1
- package/dist/components/skeleton.js.map +1 -1
- package/dist/components/slide-captcha.cjs.map +1 -1
- package/dist/components/slide-captcha.js.map +1 -1
- package/dist/components/swiper.cjs.map +1 -1
- package/dist/components/swiper.js.map +1 -1
- package/dist/components/switch.cjs.map +1 -1
- package/dist/components/switch.js.map +1 -1
- package/dist/components/table.cjs.map +1 -1
- package/dist/components/table.js.map +1 -1
- package/dist/components/tabs.cjs.map +1 -1
- package/dist/components/tabs.js.map +1 -1
- package/dist/components/tag.cjs.map +1 -1
- package/dist/components/tag.js.map +1 -1
- package/dist/components/textarea.cjs.map +1 -1
- package/dist/components/textarea.js.map +1 -1
- package/dist/components/tilt-card.cjs.map +1 -1
- package/dist/components/tilt-card.js.map +1 -1
- package/dist/components/timeline.cjs.map +1 -1
- package/dist/components/timeline.js.map +1 -1
- package/dist/components/toast.cjs +146 -14
- package/dist/components/toast.cjs.map +1 -1
- package/dist/components/toast.d.ts +1 -1
- package/dist/components/toast.d.ts.map +1 -1
- package/dist/components/toast.js +144 -15
- package/dist/components/toast.js.map +1 -1
- package/dist/components/tooltip.cjs +38 -5
- package/dist/components/tooltip.cjs.map +1 -1
- package/dist/components/tooltip.js +39 -6
- package/dist/components/tooltip.js.map +1 -1
- package/dist/components/typewriter-text.cjs.map +1 -1
- package/dist/components/typewriter-text.js.map +1 -1
- package/dist/components/upload.cjs.map +1 -1
- package/dist/components/upload.js.map +1 -1
- package/dist/components/verification-code.cjs.map +1 -1
- package/dist/components/verification-code.js.map +1 -1
- package/dist/components/video-detail-transition.cjs.map +1 -1
- package/dist/components/video-detail-transition.js.map +1 -1
- package/dist/components/video-player.cjs.map +1 -1
- package/dist/components/video-player.js.map +1 -1
- package/dist/components/virtual-list.cjs.map +1 -1
- package/dist/components/virtual-list.js.map +1 -1
- package/dist/components/virtual-select.cjs.map +1 -1
- package/dist/components/virtual-select.js.map +1 -1
- package/dist/components/virtual-table.cjs.map +1 -1
- package/dist/components/virtual-table.js.map +1 -1
- package/dist/{import-transform-jqLjtD6M.js → import-transform-Cw4K2Iky.js} +7 -1
- package/dist/import-transform-Cw4K2Iky.js.map +1 -0
- package/dist/{import-transform-DIRVOYvz.js → import-transform-ieMdZBuN.js} +7 -1
- package/dist/import-transform-ieMdZBuN.js.map +1 -0
- package/dist/import-transform.d.ts.map +1 -1
- package/dist/index.cjs +657 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +71 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +635 -38
- package/dist/index.js.map +1 -1
- package/dist/styles/base.css +168 -41
- package/dist/styles/components/barcode.css +206 -0
- package/dist/styles/components/button.css +7 -2
- package/dist/styles/components/calendar.css +0 -23
- package/dist/styles/components/canvas-editor.css +18 -21
- package/dist/styles/components/canvas-image.css +0 -23
- package/dist/styles/components/chat-textarea.css +124 -0
- package/dist/styles/components/chat-virtual-list.css +15 -26
- package/dist/styles/components/checkbox.css +39 -23
- package/dist/styles/components/checked.css +39 -23
- package/dist/styles/components/code-preview.css +208 -0
- package/dist/styles/components/color-picker.css +46 -27
- package/dist/styles/components/config-table.css +0 -23
- package/dist/styles/components/date-picker.css +39 -23
- package/dist/styles/components/date-range-picker.css +39 -23
- package/dist/styles/components/design-effect.css +5 -1
- package/dist/styles/components/drag-drop-board.css +6 -1
- package/dist/styles/components/field.css +39 -23
- package/dist/styles/components/form.css +39 -23
- package/dist/styles/components/gradient-text.css +4 -0
- package/dist/styles/components/height-transition.css +50 -0
- package/dist/styles/components/input.css +39 -23
- package/dist/styles/components/loading.css +47 -0
- package/dist/styles/components/menu.css +286 -0
- package/dist/styles/components/modal.css +2 -23
- package/dist/styles/components/number-input.css +39 -23
- package/dist/styles/components/orbital-sphere.css +224 -0
- package/dist/styles/components/password-input.css +39 -23
- package/dist/styles/components/popconfirm.css +5 -0
- package/dist/styles/components/popup.css +2 -23
- package/dist/styles/components/qr-code.css +206 -0
- package/dist/styles/components/radio-group.css +39 -23
- package/dist/styles/components/rating.css +39 -23
- package/dist/styles/components/select.css +39 -23
- package/dist/styles/components/signature.css +39 -23
- package/dist/styles/components/switch.css +39 -23
- package/dist/styles/components/table.css +0 -23
- package/dist/styles/components/tabs.css +10 -0
- package/dist/styles/components/textarea.css +39 -23
- package/dist/styles/components/tilt-card.css +2 -23
- package/dist/styles/components/toast.css +109 -48
- package/dist/styles/components/tooltip.css +8 -23
- package/dist/styles/components/typewriter-text.css +4 -0
- package/dist/styles/components/upload.css +39 -23
- package/dist/styles/components/verification-code.css +39 -23
- package/dist/styles/components/virtual-select.css +39 -23
- package/dist/styles/components/virtual-table.css +0 -23
- package/dist/styles/components.css +1250 -165
- package/dist/styles/themes/business-blue.css +375 -0
- package/dist/styles/themes/cartoon-3d.css +695 -0
- package/dist/styles/themes/creative-purple.css +376 -0
- package/dist/styles/themes/dark-tech.css +495 -0
- package/dist/styles/themes/liquid-glass.css +526 -21
- package/dist/styles/themes/minimal.css +406 -14
- package/dist/styles/themes/soft-pink.css +376 -0
- package/dist/styles.css +1250 -165
- package/dist/vite.cjs +1 -1
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.ts +1 -1
- package/dist/vite.js +1 -1
- package/dist/vite.js.map +1 -1
- package/dist/webpack-loader.cjs +1 -1
- package/dist/webpack-loader.js +1 -1
- package/package.json +4 -4
- package/dist/import-transform-DIRVOYvz.js.map +0 -1
- package/dist/import-transform-jqLjtD6M.js.map +0 -1
- package/dist/styles/themes/amber.css +0 -19
- package/dist/styles/themes/emerald.css +0 -19
- package/dist/styles/themes/rose.css +0 -19
- package/dist/styles/themes/sky.css +0 -19
- package/dist/styles/themes/violet.css +0 -19
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import React, { useEffect, useMemo, useContext, useSyncExternalStore, createContext } from 'react';
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
|
-
import { ToastManager, configureClassComponents, FormController, getClassComponentsLocale, PasswordInputController, ColorPickerController, DatePickerController, DateRangePickerController, VerificationCodeController, SlideCaptchaController, VirtualSelectController, VirtualListController, BadgeController, TagController, SkeletonController, BreadcrumbController, PaginationController, getSafeTooltipPlacement, BacktopController, AffixController, ModalController, PopupController, TooltipController, TabsController, RollingNumberController, CountdownController, CalendarController, TypewriterTextController, DesignEffectController, GradientTextController, LazyImageController, TiltCardController, MarqueeController, ProgressController, SignatureController, VideoPlayerController, VideoDetailTransitionController, FilePreviewController, CanvasImageController, CanvasEditorController, TimelineController, DragController, DropController, GestureController, FloatingBallController, MultiColumnPickerController, SwiperController, MasonryVirtualListController, TableController, UploadController, NovelReaderController, ComicReaderController, DanmakuController, LiveRoomController, ChatVirtualListController } from '@class-kit/core';
|
|
5
|
-
export { AffixController, BacktopController, BadgeController, BreadcrumbController, CalendarController, CanvasEditorController, CanvasImageController, ChatVirtualListController, ColorPickerController, ComicReaderController, CountdownController, DanmakuController, DatePickerController, DateRangePickerController, DesignEffectController, DragController, DropController, FilePreviewController, FloatingBallController, FormController, GestureController, GradientTextController, LazyImageController, LiveRoomController, MasonryVirtualListController, ModalController, MultiColumnPickerController, NovelReaderController, PaginationController, PasswordInputController, PopupController, ProgressController, SignatureController, SkeletonController, SlideCaptchaController, SwiperController, TableController, TabsController, TagController, TiltCardController, TimelineController, ToastManager, TooltipController, TypewriterTextController, UploadController, VerificationCodeController, VideoDetailTransitionController, VideoPlayerController, VirtualListController, VirtualSelectController, configureClassComponents, getClassComponentsConfig, getClassComponentsLocale, resetClassComponentsConfig } from '@class-kit/core';
|
|
4
|
+
import { ToastManager, configureClassComponents, FormController, getClassComponentsLocale, PasswordInputController, ColorPickerController, DatePickerController, DateRangePickerController, VerificationCodeController, SlideCaptchaController, ChatTextareaController, VirtualSelectController, VirtualListController, BadgeController, TagController, SkeletonController, BreadcrumbController, MenuController, PaginationController, getSafeTooltipPlacement, BacktopController, AffixController, ModalController, PopupController, TooltipController, TabsController, RollingNumberController, CountdownController, CalendarController, TypewriterTextController, DesignEffectController, GradientTextController, LazyImageController, TiltCardController, OrbitalSphereController, HeightTransitionController, CodePreviewController, MarqueeController, ProgressController, SignatureController, VideoPlayerController, VideoDetailTransitionController, FilePreviewController, CanvasImageController, CanvasEditorController, TimelineController, DragController, DropController, GestureController, FloatingBallController, MultiColumnPickerController, SwiperController, MasonryVirtualListController, TableController, UploadController, NovelReaderController, ComicReaderController, DanmakuController, LiveRoomController, ChatVirtualListController } from '@class-kit/core';
|
|
5
|
+
export { AffixController, BacktopController, BadgeController, BreadcrumbController, CalendarController, CanvasEditorController, CanvasImageController, ChatTextareaController, ChatVirtualListController, CodePreviewController, ColorPickerController, ComicReaderController, CountdownController, DanmakuController, DatePickerController, DateRangePickerController, DesignEffectController, DragController, DropController, FilePreviewController, FloatingBallController, FormController, GestureController, GradientTextController, HeightTransitionController, LazyImageController, LiveRoomController, MasonryVirtualListController, MenuController, ModalController, MultiColumnPickerController, NovelReaderController, OrbitalSphereController, PaginationController, PasswordInputController, PopupController, ProgressController, SignatureController, SkeletonController, SlideCaptchaController, SwiperController, TableController, TabsController, TagController, TiltCardController, TimelineController, ToastManager, TooltipController, TypewriterTextController, UploadController, VerificationCodeController, VideoDetailTransitionController, VideoPlayerController, VirtualListController, VirtualSelectController, configureClassComponents, getClassComponentsConfig, getClassComponentsLocale, resetClassComponentsConfig } from '@class-kit/core';
|
|
6
6
|
|
|
7
7
|
const FormContext = /*#__PURE__*/ createContext(null);
|
|
8
8
|
const defaultToastManager = /*#__PURE__*/ new ToastManager();
|
|
@@ -174,23 +174,27 @@ function usePresence(open, duration) {
|
|
|
174
174
|
return [mounted, state];
|
|
175
175
|
}
|
|
176
176
|
function useAnimatedToasts(items, duration) {
|
|
177
|
-
const [rendered, setRendered] = React.useState(() => items.map((item) => ({ item, state: "enter" })));
|
|
177
|
+
const [rendered, setRendered] = React.useState(() => items.map((item) => ({ item, motion: false, state: "enter" })));
|
|
178
178
|
useEffect(() => {
|
|
179
179
|
let enteringIds = [];
|
|
180
180
|
setRendered((current) => {
|
|
181
181
|
const currentIds = new Set(current.map(({ item }) => item.id));
|
|
182
182
|
const incomingIds = new Set(items.map((item) => item.id));
|
|
183
|
+
const incomingById = new Map(items.map((item) => [item.id, item]));
|
|
183
184
|
enteringIds = items
|
|
184
185
|
.filter((item) => !currentIds.has(item.id))
|
|
185
186
|
.map((item) => item.id);
|
|
186
|
-
const
|
|
187
|
-
item,
|
|
188
|
-
|
|
187
|
+
const retainedOrExiting = current.map(({ item }) => ({
|
|
188
|
+
item: incomingById.get(item.id) ?? item,
|
|
189
|
+
motion: !incomingIds.has(item.id),
|
|
190
|
+
state: incomingIds.has(item.id)
|
|
191
|
+
? "enter"
|
|
192
|
+
: "exit",
|
|
189
193
|
}));
|
|
190
|
-
const
|
|
191
|
-
.filter((
|
|
192
|
-
.map((
|
|
193
|
-
return [...
|
|
194
|
+
const entering = items
|
|
195
|
+
.filter((item) => !currentIds.has(item.id))
|
|
196
|
+
.map((item) => ({ item, motion: true, state: "prepare" }));
|
|
197
|
+
return [...retainedOrExiting, ...entering];
|
|
194
198
|
});
|
|
195
199
|
if (!enteringIds.length)
|
|
196
200
|
return undefined;
|
|
@@ -201,6 +205,22 @@ function useAnimatedToasts(items, duration) {
|
|
|
201
205
|
});
|
|
202
206
|
return () => window.cancelAnimationFrame(frame);
|
|
203
207
|
}, [items]);
|
|
208
|
+
useEffect(() => {
|
|
209
|
+
if (!rendered.some((entry) => entry.motion && entry.state === "enter"))
|
|
210
|
+
return;
|
|
211
|
+
if (duration <= 0) {
|
|
212
|
+
setRendered((current) => current.map((entry) => entry.motion && entry.state === "enter"
|
|
213
|
+
? { ...entry, motion: false }
|
|
214
|
+
: entry));
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
const timer = window.setTimeout(() => {
|
|
218
|
+
setRendered((current) => current.map((entry) => entry.motion && entry.state === "enter"
|
|
219
|
+
? { ...entry, motion: false }
|
|
220
|
+
: entry));
|
|
221
|
+
}, duration);
|
|
222
|
+
return () => window.clearTimeout(timer);
|
|
223
|
+
}, [duration, rendered]);
|
|
204
224
|
useEffect(() => {
|
|
205
225
|
if (!rendered.some((entry) => entry.state === "exit"))
|
|
206
226
|
return;
|
|
@@ -215,6 +235,80 @@ function useAnimatedToasts(items, duration) {
|
|
|
215
235
|
}, [duration, rendered]);
|
|
216
236
|
return rendered;
|
|
217
237
|
}
|
|
238
|
+
function normalizeToastMaxVisible(maxVisible) {
|
|
239
|
+
if (typeof maxVisible !== "number" || !Number.isFinite(maxVisible))
|
|
240
|
+
return 3;
|
|
241
|
+
return Math.max(1, Math.min(6, Math.floor(maxVisible)));
|
|
242
|
+
}
|
|
243
|
+
function isToastTopPosition(position) {
|
|
244
|
+
return (position === "top" || position === "top-left" || position === "top-right");
|
|
245
|
+
}
|
|
246
|
+
function useToastFlip(entries, duration, easing) {
|
|
247
|
+
const nodeMapRef = React.useRef(new Map());
|
|
248
|
+
const rectMapRef = React.useRef(new Map());
|
|
249
|
+
const frameRef = React.useRef(0);
|
|
250
|
+
const setNode = React.useCallback((id, node) => {
|
|
251
|
+
if (node)
|
|
252
|
+
nodeMapRef.current.set(id, node);
|
|
253
|
+
else
|
|
254
|
+
nodeMapRef.current.delete(id);
|
|
255
|
+
}, []);
|
|
256
|
+
React.useLayoutEffect(() => {
|
|
257
|
+
if (frameRef.current)
|
|
258
|
+
window.cancelAnimationFrame(frameRef.current);
|
|
259
|
+
const previousRects = rectMapRef.current;
|
|
260
|
+
const nextRects = new Map();
|
|
261
|
+
const activeIds = new Set(entries
|
|
262
|
+
.filter((entry) => entry.motion && entry.state !== "exit")
|
|
263
|
+
.map((entry) => entry.item.id));
|
|
264
|
+
nodeMapRef.current.forEach((node, id) => {
|
|
265
|
+
if (!activeIds.has(id))
|
|
266
|
+
return;
|
|
267
|
+
const rect = node.getBoundingClientRect();
|
|
268
|
+
nextRects.set(id, rect);
|
|
269
|
+
const previous = previousRects.get(id);
|
|
270
|
+
if (!previous)
|
|
271
|
+
return;
|
|
272
|
+
const deltaY = previous.top - rect.top;
|
|
273
|
+
if (Math.abs(deltaY) < 1)
|
|
274
|
+
return;
|
|
275
|
+
node.style.transition = "none";
|
|
276
|
+
node.style.setProperty("--cc-toast-stack-offset", `${deltaY}px`);
|
|
277
|
+
node.style.willChange = "transform, opacity";
|
|
278
|
+
});
|
|
279
|
+
frameRef.current = window.requestAnimationFrame(() => {
|
|
280
|
+
nodeMapRef.current.forEach((node, id) => {
|
|
281
|
+
if (!nextRects.has(id))
|
|
282
|
+
return;
|
|
283
|
+
node.style.transition = `transform ${duration}ms ${easing}, opacity ${duration}ms ${easing}, margin ${duration}ms ${easing}`;
|
|
284
|
+
node.style.removeProperty("--cc-toast-stack-offset");
|
|
285
|
+
window.setTimeout(() => {
|
|
286
|
+
node.style.transition = "";
|
|
287
|
+
node.style.willChange = "";
|
|
288
|
+
}, duration);
|
|
289
|
+
});
|
|
290
|
+
frameRef.current = 0;
|
|
291
|
+
});
|
|
292
|
+
rectMapRef.current = nextRects;
|
|
293
|
+
return () => {
|
|
294
|
+
if (frameRef.current)
|
|
295
|
+
window.cancelAnimationFrame(frameRef.current);
|
|
296
|
+
};
|
|
297
|
+
}, [duration, easing, entries]);
|
|
298
|
+
return setNode;
|
|
299
|
+
}
|
|
300
|
+
function useToastItems(manager) {
|
|
301
|
+
const snapshotRef = React.useRef(manager.getToasts());
|
|
302
|
+
const managerRef = React.useRef(manager);
|
|
303
|
+
if (managerRef.current !== manager) {
|
|
304
|
+
managerRef.current = manager;
|
|
305
|
+
snapshotRef.current = manager.getToasts();
|
|
306
|
+
}
|
|
307
|
+
return useSyncExternalStore(React.useCallback((notify) => manager.subscribe((items) => {
|
|
308
|
+
snapshotRef.current = items;
|
|
309
|
+
notify();
|
|
310
|
+
}), [manager]), React.useCallback(() => snapshotRef.current, [manager]), React.useCallback(() => snapshotRef.current, [manager]));
|
|
311
|
+
}
|
|
218
312
|
function resolveTabsDirection(tabs, previousId, nextId, direction) {
|
|
219
313
|
if (direction === "none")
|
|
220
314
|
return "none";
|
|
@@ -390,12 +484,12 @@ function PasswordInput({ name, label, className = "cc-field cc-password-field",
|
|
|
390
484
|
const Field = Input;
|
|
391
485
|
function ColorPicker({ name, label, className = "cc-field cc-color-picker", disabled, panelClassName = "cc-color-picker__panel", readOnly, initialValue, rules, showInputSteppers = false, validateOn, onChange, ...props }) {
|
|
392
486
|
const field = useOptionalField(name, {
|
|
393
|
-
initialValue: initialValue ?? "#
|
|
487
|
+
initialValue: initialValue ?? "#1d2129",
|
|
394
488
|
rules,
|
|
395
489
|
validateOn,
|
|
396
490
|
});
|
|
397
491
|
const interactivity = resolveFieldInteractivity(useOptionalFormInteractivity(), disabled, readOnly);
|
|
398
|
-
const controller = React.useMemo(() => new ColorPickerController(String(field.value || "#
|
|
492
|
+
const controller = React.useMemo(() => new ColorPickerController(String(field.value || "#1d2129")), [field.value]);
|
|
399
493
|
const state = controller.getState();
|
|
400
494
|
const rootRef = React.useRef(null);
|
|
401
495
|
const panelRef = React.useRef(null);
|
|
@@ -1079,6 +1173,82 @@ function Textarea({ name, label, className = "cc-field", labelClassName = "cc-fi
|
|
|
1079
1173
|
field.setValue(event.currentTarget.value);
|
|
1080
1174
|
}, ...options }), canClear ? (jsx("button", { "aria-label": clearLabel, className: "cc-field__clear cc-field__clear--textarea", type: "button", onClick: () => field.setValue(""), children: clearIcon })) : null] }), jsx(FieldError, { className: errorClassName, errorId: errorId, errors: field.errors })] }));
|
|
1081
1175
|
}
|
|
1176
|
+
function getTextareaMetrics(element) {
|
|
1177
|
+
const computed = window.getComputedStyle(element);
|
|
1178
|
+
const fontSize = Number.parseFloat(computed.fontSize) || 14;
|
|
1179
|
+
const lineHeight = Number.parseFloat(computed.lineHeight) || fontSize * 1.5;
|
|
1180
|
+
const paddingY = (Number.parseFloat(computed.paddingTop) || 0) +
|
|
1181
|
+
(Number.parseFloat(computed.paddingBottom) || 0);
|
|
1182
|
+
const borderY = (Number.parseFloat(computed.borderTopWidth) || 0) +
|
|
1183
|
+
(Number.parseFloat(computed.borderBottomWidth) || 0);
|
|
1184
|
+
return { borderY, lineHeight, paddingY };
|
|
1185
|
+
}
|
|
1186
|
+
const ChatTextarea = /*#__PURE__*/ React.forwardRef(function ChatTextarea({ className = "cc-chat-textarea", clearable = true, clearIcon = jsx(ClassIcon, { name: "x" }), clearLabel = getClassComponentsLocale().inputClearLabel, defaultValue = "", disabled, maxRows = 3, minRows = 1, onValueChange, placeholder, readOnly, style, textareaClassName = "cc-chat-textarea__control", textareaStyle, value, ...props }, ref) {
|
|
1187
|
+
const textareaRef = React.useRef(null);
|
|
1188
|
+
const controllerRef = React.useRef(new ChatTextareaController({
|
|
1189
|
+
maxRows,
|
|
1190
|
+
minRows,
|
|
1191
|
+
value: value ?? defaultValue,
|
|
1192
|
+
}));
|
|
1193
|
+
const controlled = value !== undefined;
|
|
1194
|
+
const [state, setState] = React.useState(() => controllerRef.current.getState());
|
|
1195
|
+
const resize = React.useCallback(() => {
|
|
1196
|
+
const element = textareaRef.current;
|
|
1197
|
+
if (!element || typeof window === "undefined")
|
|
1198
|
+
return;
|
|
1199
|
+
const { borderY, lineHeight, paddingY } = getTextareaMetrics(element);
|
|
1200
|
+
const minHeight = lineHeight * state.minRows + paddingY + borderY;
|
|
1201
|
+
const maxHeight = lineHeight * state.maxRows + paddingY + borderY;
|
|
1202
|
+
element.style.height = "auto";
|
|
1203
|
+
const nextHeight = Math.min(Math.max(element.scrollHeight, minHeight), maxHeight);
|
|
1204
|
+
element.style.height = `${nextHeight}px`;
|
|
1205
|
+
element.style.overflowY =
|
|
1206
|
+
element.scrollHeight > maxHeight + 1 ? "auto" : "hidden";
|
|
1207
|
+
}, [state.maxRows, state.minRows, state.value]);
|
|
1208
|
+
React.useImperativeHandle(ref, () => ({
|
|
1209
|
+
blur: () => textareaRef.current?.blur(),
|
|
1210
|
+
focus: () => textareaRef.current?.focus(),
|
|
1211
|
+
getElement: () => textareaRef.current,
|
|
1212
|
+
}), []);
|
|
1213
|
+
React.useEffect(() => {
|
|
1214
|
+
const next = controllerRef.current.update({
|
|
1215
|
+
maxRows,
|
|
1216
|
+
minRows,
|
|
1217
|
+
value: controlled ? value : state.value,
|
|
1218
|
+
});
|
|
1219
|
+
setState(next);
|
|
1220
|
+
}, [controlled, maxRows, minRows, value]);
|
|
1221
|
+
React.useLayoutEffect(() => {
|
|
1222
|
+
resize();
|
|
1223
|
+
}, [resize]);
|
|
1224
|
+
React.useEffect(() => {
|
|
1225
|
+
if (typeof ResizeObserver === "undefined" || !textareaRef.current)
|
|
1226
|
+
return undefined;
|
|
1227
|
+
const observer = new ResizeObserver(resize);
|
|
1228
|
+
observer.observe(textareaRef.current);
|
|
1229
|
+
return () => observer.disconnect();
|
|
1230
|
+
}, [resize]);
|
|
1231
|
+
const commit = (nextValue, event) => {
|
|
1232
|
+
const nextState = controllerRef.current.setValue(nextValue);
|
|
1233
|
+
if (!controlled)
|
|
1234
|
+
setState(nextState);
|
|
1235
|
+
onValueChange?.(nextValue, event);
|
|
1236
|
+
};
|
|
1237
|
+
const currentValue = controlled ? (value ?? "") : state.value;
|
|
1238
|
+
const canClear = clearable && currentValue !== "" && !disabled && !readOnly;
|
|
1239
|
+
return (jsxs("div", { className: className, "data-disabled": Boolean(disabled), "data-readonly": Boolean(readOnly), "data-scrollable": currentValue.length > 0, style: style, children: [jsx("textarea", { ...props, className: `${textareaClassName}${canClear ? " cc-chat-textarea__control--clearable" : ""}`, disabled: disabled, placeholder: placeholder, readOnly: readOnly, ref: textareaRef, rows: state.minRows, style: {
|
|
1240
|
+
"--cc-chat-textarea-max-rows": state.maxRows,
|
|
1241
|
+
"--cc-chat-textarea-min-rows": state.minRows,
|
|
1242
|
+
...textareaStyle,
|
|
1243
|
+
}, value: currentValue, onChange: (event) => {
|
|
1244
|
+
if (readOnly)
|
|
1245
|
+
return;
|
|
1246
|
+
commit(event.currentTarget.value, event);
|
|
1247
|
+
} }), canClear ? (jsx("button", { "aria-label": clearLabel, className: "cc-chat-textarea__clear", type: "button", onClick: (event) => {
|
|
1248
|
+
commit("", event);
|
|
1249
|
+
textareaRef.current?.focus();
|
|
1250
|
+
}, children: clearIcon })) : null] }));
|
|
1251
|
+
});
|
|
1082
1252
|
function getSelectMenuPosition(trigger, preferredHeight, anchorTopPlacement = false) {
|
|
1083
1253
|
if (!trigger || typeof window === "undefined") {
|
|
1084
1254
|
return { placement: "bottom", style: {} };
|
|
@@ -1495,6 +1665,53 @@ function Breadcrumb({ className = "cc-breadcrumb", items, separator = "/", ...pr
|
|
|
1495
1665
|
const state = useMemo(() => new BreadcrumbController(items).getState(), [items]);
|
|
1496
1666
|
return (jsx("nav", { className: className, "aria-label": "Breadcrumb", ...props, children: state.items.map((item, index) => (jsxs("span", { className: "cc-breadcrumb__item", children: [index > 0 ? (jsx("span", { className: "cc-breadcrumb__separator", children: separator })) : null, item.href && !item.disabled ? (jsx("a", { href: item.href, children: item.label })) : (jsx("span", { "data-disabled": item.disabled, children: item.label }))] }, String(item.key)))) }));
|
|
1497
1667
|
}
|
|
1668
|
+
function renderMenuIcon(item, collapsed, iconRender) {
|
|
1669
|
+
const rendered = iconRender?.(item);
|
|
1670
|
+
if (rendered !== undefined)
|
|
1671
|
+
return rendered;
|
|
1672
|
+
if (item.icon)
|
|
1673
|
+
return item.icon;
|
|
1674
|
+
return collapsed ? item.label.slice(0, 1) : null;
|
|
1675
|
+
}
|
|
1676
|
+
function renderMenuItems(items, collapsed, iconRender, onToggle, onSelect) {
|
|
1677
|
+
return items.map((item) => {
|
|
1678
|
+
const hasChildren = item.children.length > 0;
|
|
1679
|
+
const icon = renderMenuIcon(item, collapsed, iconRender);
|
|
1680
|
+
return (jsxs("li", { className: "cc-menu__item", "data-active": item.isActive, "data-disabled": item.disabled, "data-expanded": item.expanded, "data-level": item.level, children: [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: () => {
|
|
1681
|
+
if (hasChildren && !collapsed)
|
|
1682
|
+
onToggle(item.key);
|
|
1683
|
+
onSelect(item.key, item);
|
|
1684
|
+
}, children: [icon ? (jsx("span", { className: "cc-menu__icon", "aria-hidden": "true", children: icon })) : null, jsx("span", { className: "cc-menu__label", children: item.label }), hasChildren ? (jsx(ClassIcon, { className: "cc-menu__arrow", name: "chevronDown" })) : null] }), hasChildren ? (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: jsx("ul", { className: "cc-menu__list cc-menu__list--child", children: renderMenuItems(item.children, collapsed, iconRender, onToggle, onSelect) }) })) : null] }, item.key));
|
|
1685
|
+
});
|
|
1686
|
+
}
|
|
1687
|
+
function Menu({ activeKey, className = "cc-menu", collapsed, collapsible = true, defaultExpandedKeys = [], iconRender, items, onCollapsedChange, onSelect, ...props }) {
|
|
1688
|
+
const controller = React.useMemo(() => new MenuController({
|
|
1689
|
+
activeKey,
|
|
1690
|
+
collapsed,
|
|
1691
|
+
defaultExpandedKeys,
|
|
1692
|
+
items,
|
|
1693
|
+
}), []);
|
|
1694
|
+
const [state, setState] = React.useState(() => controller.getState());
|
|
1695
|
+
React.useEffect(() => {
|
|
1696
|
+
setState(controller.update({
|
|
1697
|
+
activeKey,
|
|
1698
|
+
collapsed,
|
|
1699
|
+
defaultExpandedKeys,
|
|
1700
|
+
items,
|
|
1701
|
+
}));
|
|
1702
|
+
}, [activeKey, collapsed, controller, defaultExpandedKeys, items]);
|
|
1703
|
+
const commitSelect = React.useCallback((key, item) => {
|
|
1704
|
+
setState(controller.activate(key));
|
|
1705
|
+
onSelect?.(key, item);
|
|
1706
|
+
}, [controller, onSelect]);
|
|
1707
|
+
const toggleExpanded = React.useCallback((key) => setState(controller.toggleExpanded(key)), [controller]);
|
|
1708
|
+
const toggleCollapsed = React.useCallback(() => {
|
|
1709
|
+
const next = controller.toggleCollapsed();
|
|
1710
|
+
setState(next);
|
|
1711
|
+
onCollapsedChange?.(next.collapsed);
|
|
1712
|
+
}, [controller, onCollapsedChange]);
|
|
1713
|
+
return (jsxs("nav", { className: className, "data-collapsed": state.collapsed, "data-collapsible": collapsible, ...props, children: [collapsible ? (jsx("button", { "aria-label": state.collapsed ? "展开菜单" : "收起菜单", className: "cc-menu__collapse", type: "button", onClick: toggleCollapsed, children: jsx(ClassIcon, { name: state.collapsed ? "chevronRight" : "chevronLeft" }) })) : null, jsx("ul", { className: "cc-menu__list", children: renderMenuItems(state.items, state.collapsed, iconRender, toggleExpanded, commitSelect) })] }));
|
|
1714
|
+
}
|
|
1498
1715
|
function Pagination({ boundaryCount = 1, className = "cc-pagination", current = 1, pageSize = 10, siblingCount = 1, total = 0, previousIcon = jsx(ClassIcon, { name: "chevronLeft" }), nextIcon = jsx(ClassIcon, { name: "chevronRight" }), onChange, ...props }) {
|
|
1499
1716
|
const state = useMemo(() => new PaginationController({
|
|
1500
1717
|
boundaryCount,
|
|
@@ -1505,14 +1722,29 @@ function Pagination({ boundaryCount = 1, className = "cc-pagination", current =
|
|
|
1505
1722
|
}).getState(), [boundaryCount, current, pageSize, siblingCount, total]);
|
|
1506
1723
|
return (jsxs("div", { className: className, ...props, children: [jsx("button", { disabled: state.current <= 1, type: "button", onClick: () => onChange?.(state.current - 1), children: previousIcon }), state.pages.map((page, index) => page === "ellipsis" ? (jsx("span", { "aria-hidden": "true", className: "cc-pagination__ellipsis", children: "\u2022\u2022\u2022" }, `ellipsis-${index}`)) : (jsx("button", { "data-active": page === state.current, type: "button", onClick: () => onChange?.(page), children: page }, page))), jsx("button", { disabled: state.current >= state.pageCount, type: "button", onClick: () => onChange?.(state.current + 1), children: nextIcon })] }));
|
|
1507
1724
|
}
|
|
1508
|
-
function Popconfirm({ children, animation, autoAdjust = true, placement = "top", content = getClassComponentsLocale().popconfirmContent, confirmText = getClassComponentsLocale().popconfirmConfirmText, cancelText = getClassComponentsLocale().popconfirmCancelText, closeOnEsc = true, closeOnOutsideClick = true, onConfirm, }) {
|
|
1725
|
+
function Popconfirm({ children, animation, autoAdjust = true, placement = "top", content = getClassComponentsLocale().popconfirmContent, confirmText = getClassComponentsLocale().popconfirmConfirmText, cancelText = getClassComponentsLocale().popconfirmCancelText, closeOnEsc = true, closeOnOutsideClick = true, onConfirm, portal = true, }) {
|
|
1509
1726
|
const rootRef = React.useRef(null);
|
|
1510
1727
|
const panelRef = React.useRef(null);
|
|
1511
1728
|
const [open, setOpen] = React.useState(false);
|
|
1512
1729
|
const [safePlacement, setSafePlacement] = React.useState(placement);
|
|
1730
|
+
const [anchorStyle, setAnchorStyle] = React.useState({
|
|
1731
|
+
height: 0,
|
|
1732
|
+
left: -9999,
|
|
1733
|
+
top: -9999,
|
|
1734
|
+
width: 0,
|
|
1735
|
+
});
|
|
1513
1736
|
const motion = resolveAnimation(animation, "scale");
|
|
1514
1737
|
const [mounted, presence] = usePresence(open, motion.enabled ? motion.duration : 0);
|
|
1515
1738
|
const updatePlacement = React.useCallback(() => {
|
|
1739
|
+
if (rootRef.current) {
|
|
1740
|
+
const rect = rootRef.current.getBoundingClientRect();
|
|
1741
|
+
setAnchorStyle({
|
|
1742
|
+
height: rect.height,
|
|
1743
|
+
left: rect.left,
|
|
1744
|
+
top: rect.top,
|
|
1745
|
+
width: rect.width,
|
|
1746
|
+
});
|
|
1747
|
+
}
|
|
1516
1748
|
if (!autoAdjust || !rootRef.current || !panelRef.current) {
|
|
1517
1749
|
setSafePlacement(placement);
|
|
1518
1750
|
return;
|
|
@@ -1525,7 +1757,8 @@ function Popconfirm({ children, animation, autoAdjust = true, placement = "top",
|
|
|
1525
1757
|
requestAnimationFrame(updatePlacement);
|
|
1526
1758
|
const close = (event) => {
|
|
1527
1759
|
if (!closeOnOutsideClick ||
|
|
1528
|
-
rootRef.current?.contains(event.target)
|
|
1760
|
+
rootRef.current?.contains(event.target) ||
|
|
1761
|
+
panelRef.current?.contains(event.target))
|
|
1529
1762
|
return;
|
|
1530
1763
|
setOpen(false);
|
|
1531
1764
|
};
|
|
@@ -1550,10 +1783,27 @@ function Popconfirm({ children, animation, autoAdjust = true, placement = "top",
|
|
|
1550
1783
|
if (open)
|
|
1551
1784
|
updatePlacement();
|
|
1552
1785
|
}, [open, placement, updatePlacement]);
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1786
|
+
const rootClassName = [
|
|
1787
|
+
"cc-popconfirm",
|
|
1788
|
+
`cc-popconfirm--${safePlacement}`,
|
|
1789
|
+
].join(" ");
|
|
1790
|
+
const panelNode = mounted ? (jsxs("span", { className: "cc-popconfirm__panel", "data-state": presence, ref: panelRef, role: "dialog", children: [jsx("span", { children: content }), jsxs("span", { className: "cc-popconfirm__actions", children: [jsx("button", { type: "button", onClick: () => setOpen(false), children: cancelText }), jsx("button", { type: "button", onClick: () => {
|
|
1791
|
+
onConfirm?.();
|
|
1792
|
+
setOpen(false);
|
|
1793
|
+
}, children: confirmText })] })] })) : null;
|
|
1794
|
+
const rootNode = (jsxs("span", { className: rootClassName, "data-animation": motion.name, ref: rootRef, style: animationStyle(motion), children: [jsx("span", { onClick: () => setOpen(true), children: children }), portal ? null : panelNode] }));
|
|
1795
|
+
if (!portal)
|
|
1796
|
+
return rootNode;
|
|
1797
|
+
const portalNode = mounted ? (jsx("span", { className: `${rootClassName} cc-popconfirm--portal`, "data-animation": motion.name, style: {
|
|
1798
|
+
...animationStyle(motion),
|
|
1799
|
+
height: `${anchorStyle.height}px`,
|
|
1800
|
+
left: `${anchorStyle.left}px`,
|
|
1801
|
+
top: `${anchorStyle.top}px`,
|
|
1802
|
+
width: `${anchorStyle.width}px`,
|
|
1803
|
+
}, children: panelNode })) : null;
|
|
1804
|
+
return (jsxs(Fragment, { children: [rootNode, portalNode && typeof document !== "undefined"
|
|
1805
|
+
? createPortal(portalNode, document.body)
|
|
1806
|
+
: null] }));
|
|
1557
1807
|
}
|
|
1558
1808
|
function getBacktopTarget(target) {
|
|
1559
1809
|
if (typeof target === "string")
|
|
@@ -1785,13 +2035,14 @@ function Popup({ open, controller, placement = "bottom", title, children, animat
|
|
|
1785
2035
|
}, []);
|
|
1786
2036
|
if (!mounted)
|
|
1787
2037
|
return null;
|
|
1788
|
-
const popupContainer = containerRef?.current ??
|
|
2038
|
+
const popupContainer = containerRef?.current ??
|
|
2039
|
+
(typeof document !== "undefined" ? document.body : null);
|
|
1789
2040
|
const popupElement = (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: [jsx("button", { "aria-label": "Close popup", className: overlayClassName, type: "button", onClick: closeOnOverlayClick ? close : undefined }), jsxs("section", { "aria-modal": "true", className: panelClassName, ref: panelRef, role: "dialog", tabIndex: -1, children: [title ? (jsxs("header", { className: "cc-popup__header", children: [jsx("span", { children: title }), jsx("button", { "aria-label": "Close popup", className: "cc-popup__close", type: "button", onClick: close, children: closeIcon })] })) : null, jsx("div", { className: "cc-popup__body", children: children })] })] }));
|
|
1790
2041
|
return popupContainer
|
|
1791
2042
|
? createPortal(popupElement, popupContainer)
|
|
1792
2043
|
: popupElement;
|
|
1793
2044
|
}
|
|
1794
|
-
function Tooltip({ content, children, animation, placement = "top", trigger = "hover", autoAdjust = true, closeOnEsc = true, closeOnOutsideClick = true, className, id, style, ...props }) {
|
|
2045
|
+
function Tooltip({ content, children, animation, placement = "top", trigger = "hover", autoAdjust = true, closeOnEsc = true, closeOnOutsideClick = true, portal = true, className, id, style, ...props }) {
|
|
1795
2046
|
const rootRef = React.useRef(null);
|
|
1796
2047
|
const contentRef = React.useRef(null);
|
|
1797
2048
|
const generatedId = React.useId();
|
|
@@ -1799,6 +2050,7 @@ function Tooltip({ content, children, animation, placement = "top", trigger = "h
|
|
|
1799
2050
|
const tooltipController = React.useMemo(() => new TooltipController(), []);
|
|
1800
2051
|
const [open, setOpen] = React.useState(() => tooltipController.isOpen());
|
|
1801
2052
|
const [safePlacement, setSafePlacement] = React.useState(placement);
|
|
2053
|
+
const [anchorStyle, setAnchorStyle] = React.useState(null);
|
|
1802
2054
|
const motion = resolveAnimation(animation, "fade");
|
|
1803
2055
|
useEffect(() => {
|
|
1804
2056
|
const unsubscribe = tooltipController.subscribe((state) => {
|
|
@@ -1810,6 +2062,15 @@ function Tooltip({ content, children, animation, placement = "top", trigger = "h
|
|
|
1810
2062
|
};
|
|
1811
2063
|
}, [tooltipController]);
|
|
1812
2064
|
const updatePlacement = React.useCallback(() => {
|
|
2065
|
+
if (rootRef.current) {
|
|
2066
|
+
const rect = rootRef.current.getBoundingClientRect();
|
|
2067
|
+
setAnchorStyle({
|
|
2068
|
+
height: rect.height,
|
|
2069
|
+
left: rect.left,
|
|
2070
|
+
top: rect.top,
|
|
2071
|
+
width: rect.width,
|
|
2072
|
+
});
|
|
2073
|
+
}
|
|
1813
2074
|
if (!autoAdjust || !rootRef.current || !contentRef.current) {
|
|
1814
2075
|
setSafePlacement(placement);
|
|
1815
2076
|
return;
|
|
@@ -1832,7 +2093,8 @@ function Tooltip({ content, children, animation, placement = "top", trigger = "h
|
|
|
1832
2093
|
return undefined;
|
|
1833
2094
|
const handlePointerDown = (event) => {
|
|
1834
2095
|
if (!closeOnOutsideClick ||
|
|
1835
|
-
rootRef.current?.contains(event.target)
|
|
2096
|
+
rootRef.current?.contains(event.target) ||
|
|
2097
|
+
contentRef.current?.contains(event.target))
|
|
1836
2098
|
return;
|
|
1837
2099
|
tooltipController.close();
|
|
1838
2100
|
};
|
|
@@ -1859,19 +2121,45 @@ function Tooltip({ content, children, animation, placement = "top", trigger = "h
|
|
|
1859
2121
|
onMouseEnter: () => tooltipController.open(),
|
|
1860
2122
|
onMouseLeave: () => tooltipController.close(),
|
|
1861
2123
|
};
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
2124
|
+
const rootClassName = [
|
|
2125
|
+
"cc-tooltip",
|
|
2126
|
+
`cc-tooltip--${safePlacement}`,
|
|
2127
|
+
className,
|
|
2128
|
+
]
|
|
2129
|
+
.filter(Boolean)
|
|
2130
|
+
.join(" ");
|
|
2131
|
+
const tooltipContent = (jsx("span", { className: "cc-tooltip__content", id: contentId, ref: contentRef, role: "tooltip", children: content }));
|
|
2132
|
+
const rootNode = (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] }));
|
|
2133
|
+
if (!portal || typeof document === "undefined")
|
|
2134
|
+
return rootNode;
|
|
2135
|
+
const portalNode = open || anchorStyle ? (jsx("span", { className: `${rootClassName} cc-tooltip--portal`, "data-animation": motion.name, "data-open": open, style: {
|
|
2136
|
+
...animationStyle(motion),
|
|
2137
|
+
height: anchorStyle?.height ?? 0,
|
|
2138
|
+
left: anchorStyle?.left ?? -9999,
|
|
2139
|
+
top: anchorStyle?.top ?? -9999,
|
|
2140
|
+
width: anchorStyle?.width ?? 0,
|
|
2141
|
+
}, children: tooltipContent })) : null;
|
|
2142
|
+
return (jsxs(Fragment, { children: [rootNode, portalNode ? renderBodyPortal(portalNode) : null] }));
|
|
1865
2143
|
}
|
|
1866
|
-
function ToastViewport({ animation, manager = defaultToastManager, className = "cc-toast-viewport", position = "top-right", renderToast, style, ...props }) {
|
|
1867
|
-
const
|
|
2144
|
+
function ToastViewport({ animation, manager = defaultToastManager, className = "cc-toast-viewport", maxVisible, portal = false, position = "top-right", renderToast, style, ...props }) {
|
|
2145
|
+
const items = useToastItems(manager);
|
|
1868
2146
|
const motion = resolveAnimation(animation, "slide");
|
|
1869
|
-
const
|
|
2147
|
+
const resolvedMaxVisible = normalizeToastMaxVisible(maxVisible);
|
|
2148
|
+
const visibleItems = React.useMemo(() => {
|
|
2149
|
+
const positionItems = items.filter((item) => item.position === position);
|
|
2150
|
+
const visible = positionItems.slice(Math.max(0, positionItems.length - resolvedMaxVisible));
|
|
2151
|
+
return isToastTopPosition(position) ? [...visible].reverse() : visible;
|
|
2152
|
+
}, [items, position, resolvedMaxVisible]);
|
|
1870
2153
|
const renderedItems = useAnimatedToasts(visibleItems, motion.enabled ? motion.duration : 0);
|
|
1871
|
-
|
|
1872
|
-
|
|
2154
|
+
const setToastNode = useToastFlip(renderedItems, motion.enabled ? motion.duration : 0, motion.easing);
|
|
2155
|
+
const viewportNode = (jsx("div", { className: [className, `cc-toast-viewport--${position}`]
|
|
1873
2156
|
.filter(Boolean)
|
|
1874
|
-
.join(" "), role: "status", "aria-live": "polite", style: animationStyle(motion, style), ...props, children: renderedItems.map(({ item, state }) => (jsx(React.Fragment, { children: renderToast ? (renderToast(item, (id) => manager.dismiss(id), state)) : (jsxs("article", { className: `cc-toast cc-toast--${item.tone}`, "data-animation": motion.name, "data-
|
|
2157
|
+
.join(" "), role: "status", "aria-live": "polite", style: animationStyle(motion, style), ...props, children: renderedItems.map(({ item, motion: isMotionActive, state }, index) => (jsx(React.Fragment, { children: renderToast ? (renderToast(item, (id) => manager.dismiss(id), state)) : (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: {
|
|
2158
|
+
"--cc-toast-stack-index": index,
|
|
2159
|
+
}, children: [item.title ? (jsx("strong", { className: "cc-toast__title", children: item.title })) : null, jsx("span", { className: "cc-toast__message", children: item.message }), jsx("button", { "aria-label": "Dismiss toast", className: "cc-toast__close", type: "button", onClick: () => manager.dismiss(item.id), children: jsx(ClassIcon, { name: "x" }) })] })) }, item.id))) }));
|
|
2160
|
+
return portal
|
|
2161
|
+
? renderBodyPortal(viewportNode)
|
|
2162
|
+
: viewportNode;
|
|
1875
2163
|
}
|
|
1876
2164
|
function resolveTabsFlag(source, activeId) {
|
|
1877
2165
|
if (!source)
|
|
@@ -2265,6 +2553,212 @@ function TiltCard({ children, className = "cc-tilt-card", contentClassName = "cc
|
|
|
2265
2553
|
...style,
|
|
2266
2554
|
}, onPointerEnter: handlePointerEnter, onPointerLeave: handlePointerLeave, onPointerMove: handlePointerMove, ...props, children: jsxs("div", { className: surfaceClassName, children: [jsx("div", { className: contentClassName, children: children }), state.glare ? (jsx("span", { "aria-hidden": "true", className: glareClassName })) : null] }) }));
|
|
2267
2555
|
}
|
|
2556
|
+
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 }) {
|
|
2557
|
+
const state = React.useMemo(() => new OrbitalSphereController({
|
|
2558
|
+
animated,
|
|
2559
|
+
cycleDuration,
|
|
2560
|
+
depth,
|
|
2561
|
+
disabled,
|
|
2562
|
+
duration,
|
|
2563
|
+
itemSize,
|
|
2564
|
+
items,
|
|
2565
|
+
radius,
|
|
2566
|
+
size,
|
|
2567
|
+
spread,
|
|
2568
|
+
visibleCount,
|
|
2569
|
+
}).getState(), [
|
|
2570
|
+
animated,
|
|
2571
|
+
cycleDuration,
|
|
2572
|
+
depth,
|
|
2573
|
+
disabled,
|
|
2574
|
+
duration,
|
|
2575
|
+
itemSize,
|
|
2576
|
+
items,
|
|
2577
|
+
radius,
|
|
2578
|
+
size,
|
|
2579
|
+
spread,
|
|
2580
|
+
visibleCount,
|
|
2581
|
+
]);
|
|
2582
|
+
return (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: [jsx("span", { "aria-hidden": "true", className: shellClassName }), jsx("div", { className: stageClassName, children: state.items.map((item) => (jsx("button", { "aria-label": item.label, className: itemClassName, "data-tone": item.tone, disabled: state.disabled, style: {
|
|
2583
|
+
"--cc-orbital-index": item.index,
|
|
2584
|
+
...item.styleVars,
|
|
2585
|
+
}, type: "button", onClick: (event) => onItemClick?.(item, event), children: jsx("span", { className: itemContentClassName, children: renderItem?.(item) ?? item.content }) }, item.id))) })] }));
|
|
2586
|
+
}
|
|
2587
|
+
function HeightTransition({ children, className = "cc-height-transition", contentClassName = "cc-height-transition__content", duration = 220, easing, expanded = false, mode = "auto", style, ...props }) {
|
|
2588
|
+
const contentRef = React.useRef(null);
|
|
2589
|
+
const controller = React.useMemo(() => new HeightTransitionController({ duration, easing, expanded, mode }), []);
|
|
2590
|
+
const [state, setState] = React.useState(() => controller.getState());
|
|
2591
|
+
const [height, setHeight] = React.useState(0);
|
|
2592
|
+
React.useEffect(() => {
|
|
2593
|
+
setState(controller.update({ duration, easing, expanded, mode }));
|
|
2594
|
+
}, [controller, duration, easing, expanded, mode]);
|
|
2595
|
+
React.useLayoutEffect(() => {
|
|
2596
|
+
const element = contentRef.current;
|
|
2597
|
+
if (!element || typeof ResizeObserver === "undefined") {
|
|
2598
|
+
setHeight(element?.scrollHeight ?? 0);
|
|
2599
|
+
return undefined;
|
|
2600
|
+
}
|
|
2601
|
+
const observer = new ResizeObserver(() => setHeight(element.scrollHeight));
|
|
2602
|
+
observer.observe(element);
|
|
2603
|
+
setHeight(element.scrollHeight);
|
|
2604
|
+
return () => observer.disconnect();
|
|
2605
|
+
}, [children]);
|
|
2606
|
+
return (jsx("div", { className: className, "data-expanded": state.expanded, "data-mode": state.mode, style: {
|
|
2607
|
+
"--cc-height-transition-duration": `${state.duration}ms`,
|
|
2608
|
+
"--cc-height-transition-easing": state.easing,
|
|
2609
|
+
"--cc-height-transition-height": `${height}px`,
|
|
2610
|
+
...style,
|
|
2611
|
+
}, ...props, children: jsx("div", { className: contentClassName, ref: contentRef, children: children }) }));
|
|
2612
|
+
}
|
|
2613
|
+
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 }) {
|
|
2614
|
+
const rootRef = React.useRef(null);
|
|
2615
|
+
const panelRef = React.useRef(null);
|
|
2616
|
+
const controller = React.useMemo(() => new CodePreviewController({
|
|
2617
|
+
code,
|
|
2618
|
+
defaultExpanded,
|
|
2619
|
+
language,
|
|
2620
|
+
placement,
|
|
2621
|
+
title: String(title),
|
|
2622
|
+
}), []);
|
|
2623
|
+
const [state, setState] = React.useState(() => controller.getState());
|
|
2624
|
+
const [panelStyle, setPanelStyle] = React.useState();
|
|
2625
|
+
React.useEffect(() => {
|
|
2626
|
+
setState(controller.update({ code, language, placement, title: String(title) }));
|
|
2627
|
+
}, [code, controller, language, placement, title]);
|
|
2628
|
+
const updatePanelPosition = React.useCallback((estimate = false) => {
|
|
2629
|
+
const root = rootRef.current;
|
|
2630
|
+
const panel = panelRef.current;
|
|
2631
|
+
if (!root || (!panel && !estimate) || typeof window === "undefined")
|
|
2632
|
+
return undefined;
|
|
2633
|
+
const rect = root.getBoundingClientRect();
|
|
2634
|
+
const padding = 10;
|
|
2635
|
+
const gap = 10;
|
|
2636
|
+
const viewportWidth = document.documentElement.clientWidth || window.innerWidth;
|
|
2637
|
+
const viewportHeight = document.documentElement.clientHeight || window.innerHeight;
|
|
2638
|
+
const maxPanelHeight = Math.max(160, viewportHeight - padding * 2);
|
|
2639
|
+
const maxPanelWidth = Math.max(160, viewportWidth - padding * 2);
|
|
2640
|
+
const minPanelHeight = Math.min(160, maxPanelHeight);
|
|
2641
|
+
const panelContent = panel?.querySelector("pre");
|
|
2642
|
+
const measuredPanelHeight = Math.max(panel?.offsetHeight ?? 0, panel?.scrollHeight ?? 0, panelContent?.scrollHeight ?? 0, estimate ? 420 : 0);
|
|
2643
|
+
const preferredPanelHeight = Math.min(Math.max(160, measuredPanelHeight || 420), maxPanelHeight);
|
|
2644
|
+
const panelWidth = Math.min(Math.max(rect.width, panel?.offsetWidth || 720), maxPanelWidth);
|
|
2645
|
+
const availableBelow = Math.max(minPanelHeight, viewportHeight - rect.bottom - gap - padding);
|
|
2646
|
+
const availableAbove = Math.max(minPanelHeight, rect.top - gap - padding);
|
|
2647
|
+
const placementHeight = Math.min(preferredPanelHeight, Math.max(availableBelow, availableAbove));
|
|
2648
|
+
const next = controller.resolvePlacement({
|
|
2649
|
+
anchorBottom: rect.bottom,
|
|
2650
|
+
anchorLeft: rect.left,
|
|
2651
|
+
anchorRight: rect.right,
|
|
2652
|
+
anchorTop: rect.top,
|
|
2653
|
+
panelHeight: placementHeight,
|
|
2654
|
+
panelWidth,
|
|
2655
|
+
viewportHeight,
|
|
2656
|
+
viewportWidth,
|
|
2657
|
+
});
|
|
2658
|
+
setState(next);
|
|
2659
|
+
if (strategy !== "fixed") {
|
|
2660
|
+
setPanelStyle(undefined);
|
|
2661
|
+
return;
|
|
2662
|
+
}
|
|
2663
|
+
const clamp = (value, min, max) => Math.min(Math.max(min, value), max);
|
|
2664
|
+
const width = panelWidth;
|
|
2665
|
+
const maxLeft = Math.max(padding, viewportWidth - width - padding);
|
|
2666
|
+
const viewportPanelHeight = Math.min(preferredPanelHeight, maxPanelHeight);
|
|
2667
|
+
const maxTop = Math.max(padding, viewportHeight - viewportPanelHeight - padding);
|
|
2668
|
+
let left = clamp(rect.left, padding, maxLeft);
|
|
2669
|
+
let top = rect.bottom + gap;
|
|
2670
|
+
let maxHeight = Math.min(preferredPanelHeight, Math.max(minPanelHeight, viewportHeight - top - padding));
|
|
2671
|
+
let transformOrigin = "top left";
|
|
2672
|
+
if (next.resolvedPlacement === "top") {
|
|
2673
|
+
maxHeight = Math.min(preferredPanelHeight, availableAbove);
|
|
2674
|
+
top = Math.max(padding, rect.top - gap - maxHeight);
|
|
2675
|
+
transformOrigin = "bottom left";
|
|
2676
|
+
}
|
|
2677
|
+
else if (next.resolvedPlacement === "right") {
|
|
2678
|
+
left = clamp(rect.right + gap, padding, maxLeft);
|
|
2679
|
+
top = clamp(rect.top, padding, maxTop);
|
|
2680
|
+
maxHeight = viewportPanelHeight;
|
|
2681
|
+
transformOrigin = "top left";
|
|
2682
|
+
}
|
|
2683
|
+
else if (next.resolvedPlacement === "left") {
|
|
2684
|
+
left = clamp(rect.left - width - gap, padding, maxLeft);
|
|
2685
|
+
top = clamp(rect.top, padding, maxTop);
|
|
2686
|
+
maxHeight = viewportPanelHeight;
|
|
2687
|
+
transformOrigin = "top right";
|
|
2688
|
+
}
|
|
2689
|
+
setPanelStyle({
|
|
2690
|
+
left,
|
|
2691
|
+
maxHeight,
|
|
2692
|
+
top,
|
|
2693
|
+
transformOrigin,
|
|
2694
|
+
width,
|
|
2695
|
+
});
|
|
2696
|
+
return next;
|
|
2697
|
+
}, [controller, strategy]);
|
|
2698
|
+
const updatePanelPositionFromViewport = React.useCallback(() => {
|
|
2699
|
+
updatePanelPosition();
|
|
2700
|
+
}, [updatePanelPosition]);
|
|
2701
|
+
React.useLayoutEffect(() => {
|
|
2702
|
+
if (!state.expanded) {
|
|
2703
|
+
setPanelStyle(undefined);
|
|
2704
|
+
return undefined;
|
|
2705
|
+
}
|
|
2706
|
+
updatePanelPosition();
|
|
2707
|
+
window.addEventListener("resize", updatePanelPositionFromViewport);
|
|
2708
|
+
window.addEventListener("scroll", updatePanelPositionFromViewport, true);
|
|
2709
|
+
return () => {
|
|
2710
|
+
window.removeEventListener("resize", updatePanelPositionFromViewport);
|
|
2711
|
+
window.removeEventListener("scroll", updatePanelPositionFromViewport, true);
|
|
2712
|
+
};
|
|
2713
|
+
}, [
|
|
2714
|
+
code,
|
|
2715
|
+
state.expanded,
|
|
2716
|
+
updatePanelPosition,
|
|
2717
|
+
updatePanelPositionFromViewport,
|
|
2718
|
+
]);
|
|
2719
|
+
React.useEffect(() => {
|
|
2720
|
+
if (!state.expanded || typeof document === "undefined")
|
|
2721
|
+
return undefined;
|
|
2722
|
+
const close = () => {
|
|
2723
|
+
setPanelStyle(undefined);
|
|
2724
|
+
setState(controller.close());
|
|
2725
|
+
};
|
|
2726
|
+
const closeOnOutside = (event) => {
|
|
2727
|
+
const target = event.target;
|
|
2728
|
+
if (target &&
|
|
2729
|
+
(rootRef.current?.contains(target) ||
|
|
2730
|
+
panelRef.current?.contains(target)))
|
|
2731
|
+
return;
|
|
2732
|
+
close();
|
|
2733
|
+
};
|
|
2734
|
+
const closeOnEscape = (event) => {
|
|
2735
|
+
if (event.key === "Escape")
|
|
2736
|
+
close();
|
|
2737
|
+
};
|
|
2738
|
+
document.addEventListener("pointerdown", closeOnOutside, true);
|
|
2739
|
+
document.addEventListener("keydown", closeOnEscape, true);
|
|
2740
|
+
return () => {
|
|
2741
|
+
document.removeEventListener("pointerdown", closeOnOutside, true);
|
|
2742
|
+
document.removeEventListener("keydown", closeOnEscape, true);
|
|
2743
|
+
};
|
|
2744
|
+
}, [controller, state.expanded]);
|
|
2745
|
+
const copy = async () => {
|
|
2746
|
+
await (onCopy ? onCopy(code) : navigator.clipboard?.writeText(code));
|
|
2747
|
+
setState(controller.copied());
|
|
2748
|
+
window.setTimeout(() => setState(controller.resetCopied()), 1200);
|
|
2749
|
+
};
|
|
2750
|
+
const panel = (jsx("div", { className: "cc-code-preview__panel", "data-placement": state.resolvedPlacement, "data-strategy": strategy, "data-expanded": state.expanded, ref: panelRef, style: panelStyle, children: 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: jsx("pre", { children: jsx("code", { children: state.code }) }) }) }));
|
|
2751
|
+
return (jsxs("div", { className: className, "data-expanded": state.expanded, "data-placement": state.resolvedPlacement, "data-strategy": strategy, ref: rootRef, ...props, children: [jsxs("div", { className: "cc-code-preview__bar", children: [jsxs("div", { className: "cc-code-preview__meta", children: [jsx("span", { className: "cc-code-preview__title", children: title }), jsx("span", { className: "cc-code-preview__lang", children: state.language })] }), jsxs("div", { className: "cc-code-preview__actions", children: [jsx("button", { type: "button", onClick: () => {
|
|
2752
|
+
const next = controller.toggle();
|
|
2753
|
+
if (!next.expanded) {
|
|
2754
|
+
setPanelStyle(undefined);
|
|
2755
|
+
setState(next);
|
|
2756
|
+
return;
|
|
2757
|
+
}
|
|
2758
|
+
setState(updatePanelPosition(true) ?? next);
|
|
2759
|
+
window.requestAnimationFrame(() => updatePanelPosition());
|
|
2760
|
+
}, children: state.expanded ? "收起" : "展开" }), jsx("button", { type: "button", onClick: () => void copy(), children: state.copied ? "已复制" : "复制" })] })] }), strategy === "fixed" ? renderBodyPortal(panel) : panel] }));
|
|
2761
|
+
}
|
|
2268
2762
|
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 }) {
|
|
2269
2763
|
const [svg, setSvg] = React.useState("");
|
|
2270
2764
|
const [error, setError] = React.useState(null);
|
|
@@ -2700,7 +3194,7 @@ function signaturePointFromEvent(canvas, event) {
|
|
|
2700
3194
|
y: event.clientY - rect.top,
|
|
2701
3195
|
};
|
|
2702
3196
|
}
|
|
2703
|
-
const Signature = /*#__PURE__*/ React.forwardRef(function Signature({ backgroundColor, canvasClassName = "cc-signature__canvas", className = "cc-signature", clearText = 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 = "#
|
|
3197
|
+
const Signature = /*#__PURE__*/ React.forwardRef(function Signature({ backgroundColor, canvasClassName = "cc-signature__canvas", className = "cc-signature", clearText = 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 = getClassComponentsLocale().signatureUndoText, validateOn, width = "100%", onChange, onClear, onEnd, onUndo, ...props }, ref) {
|
|
2704
3198
|
const formContext = React.useContext(FormContext);
|
|
2705
3199
|
const formState = useSyncExternalStore((listener) => formContext
|
|
2706
3200
|
? formContext.controller.subscribe(listener)
|
|
@@ -3483,6 +3977,28 @@ function Draggable({ axis = "xy", boundaryRef, children, className = "cc-draggab
|
|
|
3483
3977
|
? children({ dragging: state.dragging, position: state.position })
|
|
3484
3978
|
: children }));
|
|
3485
3979
|
}
|
|
3980
|
+
function readDragDropPreviewStyleVars(element) {
|
|
3981
|
+
if (!element || typeof window === "undefined")
|
|
3982
|
+
return {};
|
|
3983
|
+
const styles = window.getComputedStyle(element);
|
|
3984
|
+
const read = (name) => styles.getPropertyValue(name).trim();
|
|
3985
|
+
const slotDraggingBackground = read("--cc-drag-drop-slot-dragging-background");
|
|
3986
|
+
const slotDraggingBorderColor = read("--cc-drag-drop-slot-dragging-border-color");
|
|
3987
|
+
const previewBackground = read("--cc-drag-drop-preview-background");
|
|
3988
|
+
const previewBorderColor = read("--cc-drag-drop-preview-border-color");
|
|
3989
|
+
const values = {
|
|
3990
|
+
"--cc-drag-drop-preview-background": previewBackground && !previewBackground.includes("var(")
|
|
3991
|
+
? previewBackground
|
|
3992
|
+
: slotDraggingBackground,
|
|
3993
|
+
"--cc-drag-drop-preview-border-color": previewBorderColor && !previewBorderColor.includes("var(")
|
|
3994
|
+
? previewBorderColor
|
|
3995
|
+
: slotDraggingBorderColor,
|
|
3996
|
+
"--cc-drag-drop-preview-color": read("--cc-drag-drop-preview-color"),
|
|
3997
|
+
"--cc-drag-drop-preview-shadow": read("--cc-drag-drop-preview-shadow"),
|
|
3998
|
+
"--cc-drag-drop-motion-duration": read("--cc-drag-drop-motion-duration"),
|
|
3999
|
+
};
|
|
4000
|
+
return Object.fromEntries(Object.entries(values).filter(([, value]) => value.length > 0));
|
|
4001
|
+
}
|
|
3486
4002
|
function reorderDropItems(items, fromIndex, toIndex, mode) {
|
|
3487
4003
|
if (fromIndex < 0 || toIndex < 0 || fromIndex === toIndex)
|
|
3488
4004
|
return [...items];
|
|
@@ -3749,6 +4265,7 @@ function DragDropBoard({ columns, items, mode = "insert", renderItem, className
|
|
|
3749
4265
|
offsetY: event.clientY - rect.top,
|
|
3750
4266
|
originX: rect.left,
|
|
3751
4267
|
originY: rect.top,
|
|
4268
|
+
styleVars: readDragDropPreviewStyleVars(boardRef.current),
|
|
3752
4269
|
width: rect.width,
|
|
3753
4270
|
x: rect.left,
|
|
3754
4271
|
y: rect.top,
|
|
@@ -3796,6 +4313,7 @@ function DragDropBoard({ columns, items, mode = "insert", renderItem, className
|
|
|
3796
4313
|
}, onPointerUp: endDrag, onPointerCancel: cancelDrag, children: jsx("div", { className: "cc-drag-drop-board__item", children: renderItem(item, { dragging, over }) }) }, item.id));
|
|
3797
4314
|
}), preview
|
|
3798
4315
|
? renderBodyPortal(jsx("div", { "aria-hidden": "true", className: "cc-drag-drop-board__preview", "data-dropping": preview.dropping, "data-returning": preview.returning, ref: previewRef, style: {
|
|
4316
|
+
...preview.styleVars,
|
|
3799
4317
|
height: preview.height,
|
|
3800
4318
|
transform: `translate3d(${preview.x}px, ${preview.y}px, 0)`,
|
|
3801
4319
|
width: preview.width,
|
|
@@ -4650,7 +5168,9 @@ function MasonryVirtualList({ columns, data, estimateSize = 220, gap = 16, heade
|
|
|
4650
5168
|
item,
|
|
4651
5169
|
}) }, item.key))) })] }) }));
|
|
4652
5170
|
}
|
|
4653
|
-
|
|
5171
|
+
const CHAT_PREPEND_MOMENTUM_LOCK_MS = 420;
|
|
5172
|
+
const CHAT_PREPEND_STABILIZE_FRAMES = 24;
|
|
5173
|
+
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) {
|
|
4654
5174
|
const viewportRef = React.useRef(null);
|
|
4655
5175
|
const pullUpRef = React.useRef(null);
|
|
4656
5176
|
const observersRef = React.useRef(new Map());
|
|
@@ -4668,6 +5188,7 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
|
|
|
4668
5188
|
const bottomFrameRef = React.useRef();
|
|
4669
5189
|
const bottomTimerRef = React.useRef();
|
|
4670
5190
|
const prependFrameRef = React.useRef();
|
|
5191
|
+
const prependStabilizeFrameRef = React.useRef();
|
|
4671
5192
|
const prependTimerRef = React.useRef();
|
|
4672
5193
|
const topLoadingFallbackTimerRef = React.useRef();
|
|
4673
5194
|
const chatControllerRef = React.useRef(new ChatVirtualListController({ bottomThreshold, topThreshold }));
|
|
@@ -4702,14 +5223,68 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
|
|
|
4702
5223
|
}
|
|
4703
5224
|
releaseTopLoadingLock();
|
|
4704
5225
|
}, [releaseTopLoadingLock]);
|
|
4705
|
-
const clearPendingPrependAnchor = React.useCallback(() => {
|
|
5226
|
+
const clearPendingPrependAnchor = React.useCallback((force = false) => {
|
|
5227
|
+
const pendingAnchor = pendingPrependAnchorRef.current;
|
|
5228
|
+
if (!force && pendingAnchor) {
|
|
5229
|
+
const remaining = pendingAnchor.releaseAt - Date.now();
|
|
5230
|
+
if (remaining > 0) {
|
|
5231
|
+
if (prependTimerRef.current !== undefined)
|
|
5232
|
+
window.clearTimeout(prependTimerRef.current);
|
|
5233
|
+
prependTimerRef.current = window.setTimeout(() => {
|
|
5234
|
+
clearPendingPrependAnchor(true);
|
|
5235
|
+
}, remaining);
|
|
5236
|
+
return;
|
|
5237
|
+
}
|
|
5238
|
+
}
|
|
4706
5239
|
pendingPrependAnchorRef.current = null;
|
|
5240
|
+
if (prependStabilizeFrameRef.current !== undefined) {
|
|
5241
|
+
window.cancelAnimationFrame(prependStabilizeFrameRef.current);
|
|
5242
|
+
prependStabilizeFrameRef.current = undefined;
|
|
5243
|
+
}
|
|
4707
5244
|
if (prependTimerRef.current !== undefined) {
|
|
4708
5245
|
window.clearTimeout(prependTimerRef.current);
|
|
4709
5246
|
prependTimerRef.current = undefined;
|
|
4710
5247
|
}
|
|
4711
5248
|
maybeReleaseTopLoadingLock();
|
|
4712
5249
|
}, [maybeReleaseTopLoadingLock]);
|
|
5250
|
+
const applyPendingPrependAnchor = React.useCallback(() => {
|
|
5251
|
+
const pendingAnchor = pendingPrependAnchorRef.current;
|
|
5252
|
+
const viewport = viewportRef.current;
|
|
5253
|
+
if (!pendingAnchor || !viewport)
|
|
5254
|
+
return false;
|
|
5255
|
+
const anchorIndex = keys.findIndex((itemKey) => Object.is(itemKey, pendingAnchor.anchorKey));
|
|
5256
|
+
const nextScrollTop = anchorIndex >= 0
|
|
5257
|
+
? Math.max(0, listControllerRef.current.getItem(anchorIndex).start -
|
|
5258
|
+
pendingAnchor.anchorOffset)
|
|
5259
|
+
: pendingAnchor.targetScrollTop;
|
|
5260
|
+
viewport.scrollTop = nextScrollTop;
|
|
5261
|
+
setScrollOffset(nextScrollTop);
|
|
5262
|
+
previousScrollTopRef.current = nextScrollTop;
|
|
5263
|
+
previousScrollHeightRef.current = viewport.scrollHeight;
|
|
5264
|
+
return true;
|
|
5265
|
+
}, [keys]);
|
|
5266
|
+
const schedulePrependStabilization = React.useCallback(() => {
|
|
5267
|
+
if (prependStabilizeFrameRef.current !== undefined) {
|
|
5268
|
+
window.cancelAnimationFrame(prependStabilizeFrameRef.current);
|
|
5269
|
+
}
|
|
5270
|
+
let remainingFrames = CHAT_PREPEND_STABILIZE_FRAMES;
|
|
5271
|
+
const stabilize = () => {
|
|
5272
|
+
const pendingAnchor = pendingPrependAnchorRef.current;
|
|
5273
|
+
if (!pendingAnchor) {
|
|
5274
|
+
prependStabilizeFrameRef.current = undefined;
|
|
5275
|
+
return;
|
|
5276
|
+
}
|
|
5277
|
+
applyPendingPrependAnchor();
|
|
5278
|
+
remainingFrames -= 1;
|
|
5279
|
+
if (remainingFrames <= 0 && pendingAnchor.releaseAt <= Date.now()) {
|
|
5280
|
+
prependStabilizeFrameRef.current = undefined;
|
|
5281
|
+
return;
|
|
5282
|
+
}
|
|
5283
|
+
prependStabilizeFrameRef.current =
|
|
5284
|
+
window.requestAnimationFrame(stabilize);
|
|
5285
|
+
};
|
|
5286
|
+
prependStabilizeFrameRef.current = window.requestAnimationFrame(stabilize);
|
|
5287
|
+
}, [applyPendingPrependAnchor]);
|
|
4713
5288
|
const scheduleTopLoadingFallback = React.useCallback(() => {
|
|
4714
5289
|
if (topLoadingFallbackTimerRef.current !== undefined) {
|
|
4715
5290
|
window.clearTimeout(topLoadingFallbackTimerRef.current);
|
|
@@ -4855,8 +5430,12 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
|
|
|
4855
5430
|
anchorOffset: previousAnchor.offset,
|
|
4856
5431
|
measuredKeys: new Set(),
|
|
4857
5432
|
prependKeys: new Set(keys.slice(0, prependCount)),
|
|
5433
|
+
releaseAt: Date.now() + CHAT_PREPEND_MOMENTUM_LOCK_MS,
|
|
5434
|
+
targetScrollTop: nextScrollTop,
|
|
4858
5435
|
}
|
|
4859
5436
|
: null;
|
|
5437
|
+
if (pendingPrependAnchorRef.current)
|
|
5438
|
+
schedulePrependStabilization();
|
|
4860
5439
|
if (prependFrameRef.current !== undefined)
|
|
4861
5440
|
window.cancelAnimationFrame(prependFrameRef.current);
|
|
4862
5441
|
if (prependTimerRef.current !== undefined)
|
|
@@ -4906,6 +5485,7 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
|
|
|
4906
5485
|
viewportHeight,
|
|
4907
5486
|
scrollToBottom,
|
|
4908
5487
|
clearPendingPrependAnchor,
|
|
5488
|
+
schedulePrependStabilization,
|
|
4909
5489
|
maybeReleaseTopLoadingLock,
|
|
4910
5490
|
]);
|
|
4911
5491
|
useEffect(() => {
|
|
@@ -4936,6 +5516,8 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
|
|
|
4936
5516
|
window.clearTimeout(bottomTimerRef.current);
|
|
4937
5517
|
if (prependFrameRef.current !== undefined)
|
|
4938
5518
|
window.cancelAnimationFrame(prependFrameRef.current);
|
|
5519
|
+
if (prependStabilizeFrameRef.current !== undefined)
|
|
5520
|
+
window.cancelAnimationFrame(prependStabilizeFrameRef.current);
|
|
4939
5521
|
if (prependTimerRef.current !== undefined)
|
|
4940
5522
|
window.clearTimeout(prependTimerRef.current);
|
|
4941
5523
|
if (topLoadingFallbackTimerRef.current !== undefined)
|
|
@@ -5015,12 +5597,19 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
|
|
|
5015
5597
|
useEffect(() => {
|
|
5016
5598
|
onRangeChange?.({ endIndex: range.endIndex, startIndex: range.startIndex });
|
|
5017
5599
|
}, [onRangeChange, range.endIndex, range.startIndex]);
|
|
5600
|
+
const hasPendingKeySync = () => {
|
|
5601
|
+
const previousKeys = previousKeysRef.current;
|
|
5602
|
+
return (previousKeys.length !== keys.length ||
|
|
5603
|
+
previousKeys.some((itemKey, index) => !Object.is(itemKey, keys[index])));
|
|
5604
|
+
};
|
|
5018
5605
|
const observeItem = (index, key, element) => {
|
|
5019
5606
|
observersRef.current.get(key)?.disconnect();
|
|
5020
5607
|
observersRef.current.delete(key);
|
|
5021
5608
|
if (!element)
|
|
5022
5609
|
return;
|
|
5023
5610
|
const measure = () => {
|
|
5611
|
+
if (!pendingPrependAnchorRef.current && hasPendingKeySync())
|
|
5612
|
+
return;
|
|
5024
5613
|
const previousTotal = listControllerRef.current.getTotalSize();
|
|
5025
5614
|
const previousItem = listControllerRef.current.getItem(index);
|
|
5026
5615
|
const viewport = viewportRef.current;
|
|
@@ -5039,12 +5628,15 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
|
|
|
5039
5628
|
const anchorItem = listControllerRef.current.getItem(anchorIndex);
|
|
5040
5629
|
const nextItem = listControllerRef.current.getItem(index);
|
|
5041
5630
|
const delta = nextItem.size - previousItem.size;
|
|
5042
|
-
|
|
5631
|
+
const nextScrollTop = Math.max(0, index < anchorIndex && delta !== 0
|
|
5043
5632
|
? previousScrollTop + delta
|
|
5044
5633
|
: anchorItem.start - pendingAnchor.anchorOffset);
|
|
5045
|
-
|
|
5046
|
-
|
|
5634
|
+
pendingAnchor.targetScrollTop = nextScrollTop;
|
|
5635
|
+
viewport.scrollTop = nextScrollTop;
|
|
5636
|
+
setScrollOffset(nextScrollTop);
|
|
5637
|
+
previousScrollTopRef.current = nextScrollTop;
|
|
5047
5638
|
previousScrollHeightRef.current = viewport.scrollHeight;
|
|
5639
|
+
schedulePrependStabilization();
|
|
5048
5640
|
}
|
|
5049
5641
|
if (pendingAnchor.measuredKeys.size >= pendingAnchor.prependKeys.size) {
|
|
5050
5642
|
clearPendingPrependAnchor();
|
|
@@ -5080,7 +5672,12 @@ function ChatVirtualListInner({ data, bottomBuffer = 8, bottomThreshold = 64, de
|
|
|
5080
5672
|
return (jsxs("div", { className: className, "data-top-loading": topLoadingPending ? "true" : undefined, style: {
|
|
5081
5673
|
"--cc-chat-virtual-list-height": resolvedHeight,
|
|
5082
5674
|
...style,
|
|
5083
|
-
}, ...props, children: [jsx(
|
|
5675
|
+
}, ...props, children: [jsx(Loading, { "aria-hidden": !topLoadingPending, className: topLoadingClassName, "data-active": topLoadingPending ? "true" : "false", role: topLoadingPending ? "status" : undefined, text: topLoadingContent }), jsxs("div", { className: viewportClassName, "data-top-loading": topLoadingPending ? "true" : undefined, ref: viewportRef, onScroll: (event) => {
|
|
5676
|
+
if (pendingPrependAnchorRef.current) {
|
|
5677
|
+
const stabilized = applyPendingPrependAnchor();
|
|
5678
|
+
if (stabilized)
|
|
5679
|
+
return;
|
|
5680
|
+
}
|
|
5084
5681
|
const nextScrollTop = event.currentTarget.scrollTop;
|
|
5085
5682
|
previousScrollTopRef.current = nextScrollTop;
|
|
5086
5683
|
previousScrollHeightRef.current = event.currentTarget.scrollHeight;
|
|
@@ -5822,5 +6419,5 @@ function LiveRoom({ chats = EMPTY_LIVE_CHATS, className = "cc-live-room", danmak
|
|
|
5822
6419
|
} }), jsx("button", { "aria-label": getClassComponentsLocale().liveRoomSendLabel, title: getClassComponentsLocale().liveRoomSendLabel, type: "button", onClick: send, children: jsx(LiveRoomIcon, { name: "send" }) })] })] })] }));
|
|
5823
6420
|
}
|
|
5824
6421
|
|
|
5825
|
-
export { Affix, Backtop, Badge, Barcode, Breadcrumb, Button, Calendar, CanvasEditor, CanvasImage, ChatVirtualList, Checkbox, Checked, ClassConfigProvider, ColorPicker, ComicReader, ConfigTable, Countdown, Danmaku, DatePicker, DateRangePicker, DesignEffect, DragDropBoard, Draggable, EllipsisText, Empty, Field, FilePreview, FloatingBall, FormProvider, GradientText, Input, LazyImage, LiveRoom, Loading, Marquee, MasonryVirtualList, Modal, MultiColumnPicker, NovelReader, NumberInput, Pagination, PasswordInput, Popconfirm, Popup, ProgressBar, QRCode, RadioGroup, Rating, RollingNumber, Select, Signature, Skeleton, SlideCaptcha, Swiper, Switch, Table, Tabs, Tag, Textarea, TiltCard, Timeline, ToastViewport, Tooltip, TypewriterText, Upload, VerificationCode, VideoDetailTransition, VideoPlayer, VirtualList, VirtualSelect, VirtualTable, defaultToastManager, useField, useForm, useFormState };
|
|
6422
|
+
export { Affix, Backtop, Badge, Barcode, Breadcrumb, Button, Calendar, CanvasEditor, CanvasImage, ChatTextarea, ChatVirtualList, Checkbox, Checked, ClassConfigProvider, CodePreview, ColorPicker, ComicReader, ConfigTable, Countdown, Danmaku, DatePicker, DateRangePicker, DesignEffect, DragDropBoard, Draggable, EllipsisText, Empty, Field, FilePreview, FloatingBall, FormProvider, GradientText, HeightTransition, Input, LazyImage, LiveRoom, Loading, Marquee, MasonryVirtualList, Menu, Modal, MultiColumnPicker, NovelReader, NumberInput, OrbitalSphere, Pagination, PasswordInput, Popconfirm, Popup, ProgressBar, QRCode, RadioGroup, Rating, RollingNumber, Select, Signature, Skeleton, SlideCaptcha, Swiper, Switch, Table, Tabs, Tag, Textarea, TiltCard, Timeline, ToastViewport, Tooltip, TypewriterText, Upload, VerificationCode, VideoDetailTransition, VideoPlayer, VirtualList, VirtualSelect, VirtualTable, defaultToastManager, useField, useForm, useFormState };
|
|
5826
6423
|
//# sourceMappingURL=index.js.map
|