@canlooks/can-ui 0.0.115 → 0.0.117
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/dist/cjs/components/anchorList/anchorList.js +4 -4
- package/dist/cjs/components/deferred/deferred.js +4 -4
- package/dist/cjs/components/dialog/dialog.js +1 -1
- package/dist/cjs/components/loadingMask/loadingMask.js +4 -5
- package/dist/cjs/components/popper/popper.js +1 -6
- package/dist/cjs/components/popper/popperContext.js +4 -4
- package/dist/cjs/components/snackbarBase/snackbarBase.js +2 -4
- package/dist/cjs/components/tabs/tabs.js +11 -9
- package/dist/cjs/components/transitionBase/collapse.js +4 -4
- package/dist/cjs/components/waterfall/waterfall.js +3 -10
- package/dist/cjs/utils/hooks.d.ts +10 -6
- package/dist/cjs/utils/hooks.js +36 -13
- package/dist/cjs/utils/tree.js +29 -27
- package/dist/cjs/utils/utils.d.ts +1 -0
- package/dist/cjs/utils/utils.js +17 -0
- package/dist/esm/components/anchorList/anchorList.js +5 -5
- package/dist/esm/components/deferred/deferred.js +4 -4
- package/dist/esm/components/dialog/dialog.js +1 -1
- package/dist/esm/components/loadingMask/loadingMask.js +6 -7
- package/dist/esm/components/popper/popper.js +2 -7
- package/dist/esm/components/popper/popperContext.js +5 -5
- package/dist/esm/components/snackbarBase/snackbarBase.js +4 -6
- package/dist/esm/components/tabs/tabs.js +11 -9
- package/dist/esm/components/transitionBase/collapse.js +6 -6
- package/dist/esm/components/waterfall/waterfall.js +5 -12
- package/dist/esm/utils/hooks.d.ts +10 -6
- package/dist/esm/utils/hooks.js +34 -13
- package/dist/esm/utils/tree.js +29 -27
- package/dist/esm/utils/utils.d.ts +1 -0
- package/dist/esm/utils/utils.js +16 -0
- package/package.json +3 -1
|
@@ -13,10 +13,10 @@ exports.AnchorList = (0, react_1.memo)(({ anchors, renderAnchorItem, indent = 24
|
|
|
13
13
|
* ------------------------------------------------------------------------
|
|
14
14
|
* 初始化高亮与滚动位置
|
|
15
15
|
*/
|
|
16
|
-
const
|
|
17
|
-
(0,
|
|
16
|
+
const mounted = (0, react_1.useRef)(false);
|
|
17
|
+
(0, utils_1.useExternalClass)(() => {
|
|
18
18
|
if (routeMode === 'history') {
|
|
19
|
-
|
|
19
|
+
mounted.current ||= scrollToId(location.hash.slice(1));
|
|
20
20
|
}
|
|
21
21
|
});
|
|
22
22
|
const scrollToId = (id) => {
|
|
@@ -28,7 +28,7 @@ exports.AnchorList = (0, react_1.memo)(({ anchors, renderAnchorItem, indent = 24
|
|
|
28
28
|
scrollerEl.scrollTo({
|
|
29
29
|
top: targetEl.offsetTop - offset,
|
|
30
30
|
// 初始化之前无需平滑滚动
|
|
31
|
-
behavior:
|
|
31
|
+
behavior: mounted.current ? scrollBehavior : 'instant'
|
|
32
32
|
});
|
|
33
33
|
return true;
|
|
34
34
|
};
|
|
@@ -3,13 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Deferred = Deferred;
|
|
4
4
|
const react_1 = require("react");
|
|
5
5
|
function Deferred({ init, value, children }) {
|
|
6
|
-
const [
|
|
7
|
-
const
|
|
6
|
+
const [mounted, setMounted] = (0, react_1.useState)(false);
|
|
7
|
+
const deferredMounted = (0, react_1.useDeferredValue)(mounted);
|
|
8
8
|
(0, react_1.useEffect)(() => {
|
|
9
|
-
|
|
9
|
+
setMounted(true);
|
|
10
10
|
}, []);
|
|
11
11
|
const deferredValue = (0, react_1.useDeferredValue)(value);
|
|
12
|
-
if (!
|
|
12
|
+
if (!deferredMounted) {
|
|
13
13
|
return init;
|
|
14
14
|
}
|
|
15
15
|
return typeof children === 'function'
|
|
@@ -67,7 +67,7 @@ function Dialog({ icon, title, footer, prefix, suffix, width = 420, minWidth, ma
|
|
|
67
67
|
if (scrollBehavior !== 'card') {
|
|
68
68
|
return;
|
|
69
69
|
}
|
|
70
|
-
if (innerOpen.current) {
|
|
70
|
+
if (innerOpen.current && bodyRef.current && bodyWrapRef.current) {
|
|
71
71
|
const resizeObserver = new ResizeObserver(onScroll);
|
|
72
72
|
resizeObserver.observe(bodyRef.current);
|
|
73
73
|
resizeObserver.observe(bodyWrapRef.current);
|
|
@@ -9,16 +9,15 @@ const progress_1 = require("../progress");
|
|
|
9
9
|
const utils_1 = require("../../utils");
|
|
10
10
|
const backdrop_1 = require("../backdrop");
|
|
11
11
|
exports.LoadingMask = (0, react_1.memo)(({ open = false, text = '加载中...', progress, color, indicatorProps, progressProps, ...props }) => {
|
|
12
|
-
const [visible, setVisible] = (0,
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
const [visible, setVisible] = (0, react_1.useState)(open);
|
|
13
|
+
(0, react_1.useMemo)(() => {
|
|
14
|
+
open && setVisible(true);
|
|
15
15
|
}, [open]);
|
|
16
16
|
const onExited = () => {
|
|
17
|
-
// 动画结束后,loading为false才需要改变visible
|
|
18
17
|
setVisible(false);
|
|
19
18
|
};
|
|
20
19
|
const showProgress = typeof progress === 'number';
|
|
21
|
-
return open || visible
|
|
20
|
+
return open || visible
|
|
22
21
|
? (0, jsx_runtime_1.jsxs)(backdrop_1.Backdrop, { variant: "light", ...props, css: loadingMask_style_1.style, open: open, className: (0, utils_1.clsx)(loadingMask_style_1.classes.root, props.className), onExited: onExited, "data-show-progress": showProgress, children: [(0, jsx_runtime_1.jsxs)("div", { className: loadingMask_style_1.classes.indicator, children: [(0, jsx_runtime_1.jsx)(loadingIndicator_1.LoadingIndicator, { size: showProgress ? 14 : 30, borderWidth: showProgress ? 2 : 3, color: color, ...indicatorProps }), (0, jsx_runtime_1.jsx)("div", { className: loadingMask_style_1.classes.text, children: text })] }), showProgress &&
|
|
23
22
|
(0, jsx_runtime_1.jsx)(progress_1.Progress, { className: loadingMask_style_1.classes.progress, value: progress, ...progressProps })] })
|
|
24
23
|
: null;
|
|
@@ -57,12 +57,7 @@ function Popper({ ref, popperRef, anchorElement, container, effectContainer, con
|
|
|
57
57
|
}
|
|
58
58
|
};
|
|
59
59
|
const { onChildrenOpenChange: tellParentOpenChange } = (0, popperContext_1.usePopperContext)();
|
|
60
|
-
|
|
61
|
-
(0, react_1.useEffect)(() => {
|
|
62
|
-
if (!initialized.current) {
|
|
63
|
-
initialized.current = true;
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
60
|
+
(0, utils_1.useUpdateEffect)(() => {
|
|
66
61
|
tellParentOpenChange(innerOpen.current);
|
|
67
62
|
}, [innerOpen.current]);
|
|
68
63
|
const onChildrenOpenChange = (childrenOpen) => {
|
|
@@ -4,6 +4,7 @@ exports.PopperContext = void 0;
|
|
|
4
4
|
exports.usePopperContext = usePopperContext;
|
|
5
5
|
exports.useScrollToTarget = useScrollToTarget;
|
|
6
6
|
const react_1 = require("react");
|
|
7
|
+
const utils_1 = require("../../utils");
|
|
7
8
|
exports.PopperContext = (0, react_1.createContext)({
|
|
8
9
|
autoClose: false,
|
|
9
10
|
open: false,
|
|
@@ -30,11 +31,10 @@ function useScrollToTarget(scrollerRef) {
|
|
|
30
31
|
scrollerEl.scrollTop = targetEl.offsetTop + targetEl.clientHeight / 2 - scrollerEl.clientHeight / 2;
|
|
31
32
|
}
|
|
32
33
|
}, []);
|
|
33
|
-
(0,
|
|
34
|
+
(0, utils_1.useExternalClass)(() => {
|
|
34
35
|
beforeOpenCallbacks.add(beforeOpen);
|
|
35
|
-
},
|
|
36
|
-
(0, react_1.useEffect)(() => () => {
|
|
36
|
+
}, () => {
|
|
37
37
|
beforeOpenCallbacks.delete(beforeOpen);
|
|
38
|
-
}
|
|
38
|
+
});
|
|
39
39
|
return ref;
|
|
40
40
|
}
|
|
@@ -40,9 +40,7 @@ const placementToIndex = {
|
|
|
40
40
|
exports.SnackbarBase = (0, react_2.memo)(({ methods, useTo, max = useTo === 'message' ? 5 : 4, container, effectContainer }) => {
|
|
41
41
|
const [stacks, setStacks] = (0, react_2.useState)([]);
|
|
42
42
|
const timers = (0, react_2.useRef)([]);
|
|
43
|
-
(0,
|
|
44
|
-
timers.current.forEach(timer => clearTimeout(timer));
|
|
45
|
-
}, []);
|
|
43
|
+
const isUnmounted = (0, utils_1.useUnmounted)();
|
|
46
44
|
const defineMethod = (type) => (props) => new Promise(resolve => {
|
|
47
45
|
const propsObject = typeof props === 'object' && !(0, react_2.isValidElement)(props)
|
|
48
46
|
? props
|
|
@@ -51,7 +49,7 @@ exports.SnackbarBase = (0, react_2.memo)(({ methods, useTo, max = useTo === 'mes
|
|
|
51
49
|
const index = placementToIndex[placement];
|
|
52
50
|
let id = (0, utils_1.getEasyID)('snackbar');
|
|
53
51
|
const onCloseButtonClick = () => {
|
|
54
|
-
setStacks(o => {
|
|
52
|
+
!isUnmounted.current && setStacks(o => {
|
|
55
53
|
o[index] = o[index].filter(s => s.id !== id);
|
|
56
54
|
return [...o];
|
|
57
55
|
});
|
|
@@ -79,15 +79,17 @@ exports.Tabs = (0, react_2.memo)(({ tabs, labelKey = 'label', primaryKey = 'valu
|
|
|
79
79
|
const [shadowStart, setShadowStart] = (0, react_2.useState)(false);
|
|
80
80
|
const [shadowEnd, setShadowEnd] = (0, react_2.useState)(false);
|
|
81
81
|
const setShadow = () => {
|
|
82
|
-
if (
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
82
|
+
if (scrollRef.current) {
|
|
83
|
+
if (position === 'top' || position === 'bottom') {
|
|
84
|
+
const { scrollLeft } = scrollRef.current;
|
|
85
|
+
setShadowStart(scrollLeft > 0);
|
|
86
|
+
setShadowEnd(scrollLeft < scrollRef.current.scrollWidth - scrollRef.current.clientWidth);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const { scrollTop } = scrollRef.current;
|
|
90
|
+
setShadowStart(scrollTop > 0);
|
|
91
|
+
setShadowEnd(scrollTop < scrollRef.current.scrollHeight - scrollRef.current.clientHeight);
|
|
92
|
+
}
|
|
91
93
|
}
|
|
92
94
|
};
|
|
93
95
|
(0, react_2.useEffect)(() => {
|
|
@@ -33,11 +33,11 @@ const Sweeping = ({ ref, in: _in = false, appear = true, orientation = 'vertical
|
|
|
33
33
|
setSize(getCollapsedSize());
|
|
34
34
|
});
|
|
35
35
|
};
|
|
36
|
-
const
|
|
37
|
-
(0,
|
|
38
|
-
if (!
|
|
36
|
+
const mounted = (0, react_1.useRef)(false);
|
|
37
|
+
(0, utils_1.useStrictEffect)(() => {
|
|
38
|
+
if (!mounted.current) {
|
|
39
39
|
// 首次渲染
|
|
40
|
-
|
|
40
|
+
mounted.current = true;
|
|
41
41
|
if (!appear) {
|
|
42
42
|
// 若appear为false,则跳过首次动画
|
|
43
43
|
return;
|
|
@@ -32,17 +32,10 @@ const Waterfall = ({ columnCount = { xs: 4 }, gap = 0, columnGap, rowGap, ...pro
|
|
|
32
32
|
elements.current.forEach(el => resizeObserver.current.observe(el));
|
|
33
33
|
});
|
|
34
34
|
});
|
|
35
|
-
|
|
36
|
-
(0,
|
|
37
|
-
if (!isInitialized.current) {
|
|
38
|
-
isInitialized.current = true;
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
computeItemOrder();
|
|
42
|
-
}, [columnCountNum.current]);
|
|
43
|
-
(0, react_1.useEffect)(() => () => {
|
|
35
|
+
(0, utils_1.useUpdateEffect)(computeItemOrder, [columnCountNum.current]);
|
|
36
|
+
(0, utils_1.useExternalClass)(() => void 0, () => {
|
|
44
37
|
resizeObserver.current.disconnect();
|
|
45
|
-
}
|
|
38
|
+
});
|
|
46
39
|
return ((0, jsx_runtime_1.jsx)("div", { ...props, ref: (0, utils_1.cloneRef)(containerRef, props.ref), css: (0, waterfall_style_1.useStyle)({ columnCount, columnGap, rowGap }), className: (0, utils_1.clsx)(waterfall_style_1.classes.root, props.className), children: react_1.Children.map(props.children, child => {
|
|
47
40
|
if (!(0, react_1.isValidElement)(child)) {
|
|
48
41
|
throw Error('Children of <Waterfall> must be element');
|
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import { RefObject, Dispatch, SetStateAction } from 'react';
|
|
1
|
+
import { RefObject, Dispatch, SetStateAction, EffectCallback, DependencyList } from 'react';
|
|
2
2
|
import { DefineElement } from '../types';
|
|
3
|
-
/**
|
|
4
|
-
* 获取渲染前的值
|
|
5
|
-
* @param value
|
|
6
|
-
*/
|
|
7
|
-
export declare function usePrev<T>(value: T): T | null;
|
|
8
3
|
/**
|
|
9
4
|
* 将某个值使用ref同步,主要用于对付组件的闭包问题
|
|
10
5
|
* @param value
|
|
@@ -27,6 +22,7 @@ export declare function useForceUpdate(): () => void;
|
|
|
27
22
|
*/
|
|
28
23
|
export declare function useDerivedState<T>(referredState: (prevState: T | undefined) => T, deps: any[]): [RefObject<T>, Dispatch<SetStateAction<T>>];
|
|
29
24
|
export declare function useDerivedState<T>(referredState: T, deps?: any[]): [RefObject<T>, Dispatch<SetStateAction<T>>];
|
|
25
|
+
export declare function useMounted(): void;
|
|
30
26
|
/**
|
|
31
27
|
* 组件卸载后得到{current: true}
|
|
32
28
|
* @returns
|
|
@@ -60,3 +56,11 @@ export declare function useContainer<T extends HTMLElement | null>(container?: D
|
|
|
60
56
|
* 使用外部类,该方法可避免`StrictMode`下,React渲染行为与外部类实例生命周期不同步的问题
|
|
61
57
|
*/
|
|
62
58
|
export declare function useExternalClass<T>(setup: () => T, cleanup?: (instance: T) => void): T;
|
|
59
|
+
/**
|
|
60
|
+
* 用法同{@link useEffect},但StrictMode下不会执行两次
|
|
61
|
+
*/
|
|
62
|
+
export declare function useStrictEffect(effect: EffectCallback, deps?: DependencyList): void;
|
|
63
|
+
/**
|
|
64
|
+
* 用法同{@link useEffect},但会排除首次渲染
|
|
65
|
+
*/
|
|
66
|
+
export declare function useUpdateEffect(effect: EffectCallback, deps?: DependencyList): void;
|
package/dist/cjs/utils/hooks.js
CHANGED
|
@@ -1,28 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.usePrev = usePrev;
|
|
4
3
|
exports.useSync = useSync;
|
|
5
4
|
exports.useSyncState = useSyncState;
|
|
6
5
|
exports.useForceUpdate = useForceUpdate;
|
|
7
6
|
exports.useDerivedState = useDerivedState;
|
|
7
|
+
exports.useMounted = useMounted;
|
|
8
8
|
exports.useUnmounted = useUnmounted;
|
|
9
9
|
exports.useControlled = useControlled;
|
|
10
10
|
exports.useLoading = useLoading;
|
|
11
11
|
exports.useContainer = useContainer;
|
|
12
12
|
exports.useExternalClass = useExternalClass;
|
|
13
|
+
exports.useStrictEffect = useStrictEffect;
|
|
14
|
+
exports.useUpdateEffect = useUpdateEffect;
|
|
13
15
|
const react_1 = require("react");
|
|
14
16
|
const utils_1 = require("./utils");
|
|
15
|
-
/**
|
|
16
|
-
* 获取渲染前的值
|
|
17
|
-
* @param value
|
|
18
|
-
*/
|
|
19
|
-
function usePrev(value) {
|
|
20
|
-
const prev = (0, react_1.useRef)(null);
|
|
21
|
-
(0, react_1.useEffect)(() => {
|
|
22
|
-
prev.current = value;
|
|
23
|
-
});
|
|
24
|
-
return prev.current;
|
|
25
|
-
}
|
|
26
17
|
/**
|
|
27
18
|
* 将某个值使用ref同步,主要用于对付组件的闭包问题
|
|
28
19
|
* @param value
|
|
@@ -54,6 +45,10 @@ function useForceUpdate() {
|
|
|
54
45
|
}
|
|
55
46
|
function useDerivedState(referredState, deps) {
|
|
56
47
|
const derivedState = (0, react_1.useRef)(void 0);
|
|
48
|
+
(0, react_1.useMemo)(() => {
|
|
49
|
+
// SSR模式下,derivedState会重置2次
|
|
50
|
+
derivedState.current = void 0;
|
|
51
|
+
}, []);
|
|
57
52
|
const updateState = (state) => {
|
|
58
53
|
const newState = typeof state === 'function' ? state(derivedState.current) : state;
|
|
59
54
|
if (derivedState.current !== newState) {
|
|
@@ -74,13 +69,15 @@ function useDerivedState(referredState, deps) {
|
|
|
74
69
|
}, [])
|
|
75
70
|
];
|
|
76
71
|
}
|
|
72
|
+
function useMounted() {
|
|
73
|
+
}
|
|
77
74
|
/**
|
|
78
75
|
* 组件卸载后得到{current: true}
|
|
79
76
|
* @returns
|
|
80
77
|
*/
|
|
81
78
|
function useUnmounted() {
|
|
82
79
|
const isUnmounted = (0, react_1.useRef)(false);
|
|
83
|
-
useExternalClass(() => void 0, () =>
|
|
80
|
+
useExternalClass(() => void 0, () => {
|
|
84
81
|
isUnmounted.current = true;
|
|
85
82
|
});
|
|
86
83
|
return isUnmounted;
|
|
@@ -164,3 +161,29 @@ function useExternalClass(setup, cleanup) {
|
|
|
164
161
|
}, []);
|
|
165
162
|
return instance;
|
|
166
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* 用法同{@link useEffect},但StrictMode下不会执行两次
|
|
166
|
+
*/
|
|
167
|
+
function useStrictEffect(effect, deps) {
|
|
168
|
+
const prevDeps = (0, react_1.useRef)(void 0);
|
|
169
|
+
(0, react_1.useEffect)(() => {
|
|
170
|
+
const isDepsChanged = prevDeps.current ? !(0, utils_1.arrayShallowEqual)(prevDeps.current, deps) : true;
|
|
171
|
+
if (isDepsChanged) {
|
|
172
|
+
prevDeps.current = deps;
|
|
173
|
+
return effect();
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* 用法同{@link useEffect},但会排除首次渲染
|
|
179
|
+
*/
|
|
180
|
+
function useUpdateEffect(effect, deps) {
|
|
181
|
+
const mounted = (0, react_1.useRef)(false);
|
|
182
|
+
useStrictEffect(() => {
|
|
183
|
+
if (!mounted.current) {
|
|
184
|
+
mounted.current = true;
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
return effect();
|
|
188
|
+
}, [deps]);
|
|
189
|
+
}
|
package/dist/cjs/utils/tree.js
CHANGED
|
@@ -86,34 +86,36 @@ function sortTreeNodes(props, sortInfo) {
|
|
|
86
86
|
}
|
|
87
87
|
return null;
|
|
88
88
|
};
|
|
89
|
-
pickUp(nodes);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
for (let i = 0, { length } = nodes; i < length; i++) {
|
|
95
|
-
const node = nodes[i];
|
|
96
|
-
if (node[primaryKey] === destination) {
|
|
97
|
-
switch (placement) {
|
|
98
|
-
case 'before':
|
|
99
|
-
nodes.splice(i, 0, node);
|
|
100
|
-
return true;
|
|
101
|
-
case 'after':
|
|
102
|
-
nodes.splice(i + 1, 0, node);
|
|
103
|
-
return true;
|
|
104
|
-
default:
|
|
105
|
-
node.children ||= [];
|
|
106
|
-
node.children.push(node);
|
|
107
|
-
return true;
|
|
108
|
-
}
|
|
89
|
+
const sourceNode = pickUp(nodes);
|
|
90
|
+
if (sourceNode) {
|
|
91
|
+
const putDown = (nodes) => {
|
|
92
|
+
if (!nodes?.length) {
|
|
93
|
+
return false;
|
|
109
94
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
95
|
+
for (let i = 0, { length } = nodes; i < length; i++) {
|
|
96
|
+
const node = nodes[i];
|
|
97
|
+
if (node[primaryKey] === destination) {
|
|
98
|
+
switch (placement) {
|
|
99
|
+
case 'before':
|
|
100
|
+
nodes.splice(i, 0, sourceNode);
|
|
101
|
+
return true;
|
|
102
|
+
case 'after':
|
|
103
|
+
nodes.splice(i + 1, 0, sourceNode);
|
|
104
|
+
return true;
|
|
105
|
+
default:
|
|
106
|
+
node.children ||= [];
|
|
107
|
+
node.children.push(sourceNode);
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const foundInChildren = putDown(node[childrenKey]);
|
|
112
|
+
if (foundInChildren) {
|
|
113
|
+
return foundInChildren;
|
|
114
|
+
}
|
|
113
115
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
return false;
|
|
117
|
+
};
|
|
118
|
+
putDown(nodes);
|
|
119
|
+
}
|
|
118
120
|
return nodes;
|
|
119
121
|
}
|
|
@@ -47,6 +47,7 @@ export declare function mergeDeep<T extends {}, U, V, W, X>(target: T, source: U
|
|
|
47
47
|
export declare function mergeDeep<T extends {}, U, V, W, X, Y>(target: T, source: U, source2: V, source3: W, source4: X, source5: Y): T & U & V & W & X & Y;
|
|
48
48
|
export declare function mergeDeep<T extends {}, U, V, W, X, Y, Z>(target: T, source: U, source2: V, source3: W, source4: X, source5: Y, source6: Z): T & U & V & W & X & Y & Z;
|
|
49
49
|
export declare function mergeDeep(target: object, ...sources: any[]): any;
|
|
50
|
+
export declare function arrayShallowEqual(a: any[], b: any[]): boolean;
|
|
50
51
|
export type OverflowEdge = 'top' | 'bottom' | 'left' | 'right';
|
|
51
52
|
/**
|
|
52
53
|
* 判断元素是否完全在目标容器内,用于Popper组件
|
package/dist/cjs/utils/utils.js
CHANGED
|
@@ -8,6 +8,7 @@ exports.toArray = toArray;
|
|
|
8
8
|
exports.isSelected = isSelected;
|
|
9
9
|
exports.cloneDeep = cloneDeep;
|
|
10
10
|
exports.mergeDeep = mergeDeep;
|
|
11
|
+
exports.arrayShallowEqual = arrayShallowEqual;
|
|
11
12
|
exports.isElementOverflowed = isElementOverflowed;
|
|
12
13
|
exports.nextTick = nextTick;
|
|
13
14
|
exports.cloneRef = cloneRef;
|
|
@@ -137,6 +138,22 @@ function mergeDeep(target, ...sources) {
|
|
|
137
138
|
}
|
|
138
139
|
return target;
|
|
139
140
|
}
|
|
141
|
+
function arrayShallowEqual(a, b) {
|
|
142
|
+
if (a === b) {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
if (a.length !== b.length) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
let isEqual = true;
|
|
149
|
+
for (let i = 0, { length } = a; i < length; i++) {
|
|
150
|
+
if (a[i] !== b[i]) {
|
|
151
|
+
isEqual = false;
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return isEqual;
|
|
156
|
+
}
|
|
140
157
|
/**
|
|
141
158
|
* 判断元素是否完全在目标容器内,用于Popper组件
|
|
142
159
|
* @param target 目标元素
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
2
2
|
import { classes, style } from './anchorList.style';
|
|
3
|
-
import { clsx, listenAllPredecessorsScroll, useDerivedState, useSyncState } from '../../utils';
|
|
3
|
+
import { clsx, listenAllPredecessorsScroll, useDerivedState, useExternalClass, useSyncState } from '../../utils';
|
|
4
4
|
import { memo, useEffect, useRef } from 'react';
|
|
5
5
|
import { Flex } from '../flex';
|
|
6
6
|
import { ActiveIndicator } from './activeIndicator';
|
|
@@ -10,10 +10,10 @@ export const AnchorList = memo(({ anchors, renderAnchorItem, indent = 24, scroll
|
|
|
10
10
|
* ------------------------------------------------------------------------
|
|
11
11
|
* 初始化高亮与滚动位置
|
|
12
12
|
*/
|
|
13
|
-
const
|
|
14
|
-
|
|
13
|
+
const mounted = useRef(false);
|
|
14
|
+
useExternalClass(() => {
|
|
15
15
|
if (routeMode === 'history') {
|
|
16
|
-
|
|
16
|
+
mounted.current ||= scrollToId(location.hash.slice(1));
|
|
17
17
|
}
|
|
18
18
|
});
|
|
19
19
|
const scrollToId = (id) => {
|
|
@@ -25,7 +25,7 @@ export const AnchorList = memo(({ anchors, renderAnchorItem, indent = 24, scroll
|
|
|
25
25
|
scrollerEl.scrollTo({
|
|
26
26
|
top: targetEl.offsetTop - offset,
|
|
27
27
|
// 初始化之前无需平滑滚动
|
|
28
|
-
behavior:
|
|
28
|
+
behavior: mounted.current ? scrollBehavior : 'instant'
|
|
29
29
|
});
|
|
30
30
|
return true;
|
|
31
31
|
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { useDeferredValue, useEffect, useState } from 'react';
|
|
2
2
|
export function Deferred({ init, value, children }) {
|
|
3
|
-
const [
|
|
4
|
-
const
|
|
3
|
+
const [mounted, setMounted] = useState(false);
|
|
4
|
+
const deferredMounted = useDeferredValue(mounted);
|
|
5
5
|
useEffect(() => {
|
|
6
|
-
|
|
6
|
+
setMounted(true);
|
|
7
7
|
}, []);
|
|
8
8
|
const deferredValue = useDeferredValue(value);
|
|
9
|
-
if (!
|
|
9
|
+
if (!deferredMounted) {
|
|
10
10
|
return init;
|
|
11
11
|
}
|
|
12
12
|
return typeof children === 'function'
|
|
@@ -64,7 +64,7 @@ export function Dialog({ icon, title, footer, prefix, suffix, width = 420, minWi
|
|
|
64
64
|
if (scrollBehavior !== 'card') {
|
|
65
65
|
return;
|
|
66
66
|
}
|
|
67
|
-
if (innerOpen.current) {
|
|
67
|
+
if (innerOpen.current && bodyRef.current && bodyWrapRef.current) {
|
|
68
68
|
const resizeObserver = new ResizeObserver(onScroll);
|
|
69
69
|
resizeObserver.observe(bodyRef.current);
|
|
70
70
|
resizeObserver.observe(bodyWrapRef.current);
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
2
|
-
import { memo } from 'react';
|
|
2
|
+
import { memo, useMemo, useState } from 'react';
|
|
3
3
|
import { classes, style } from './loadingMask.style';
|
|
4
4
|
import { LoadingIndicator } from '../loadingIndicator';
|
|
5
5
|
import { Progress } from '../progress';
|
|
6
|
-
import { clsx
|
|
6
|
+
import { clsx } from '../../utils';
|
|
7
7
|
import { Backdrop } from '../backdrop';
|
|
8
8
|
export const LoadingMask = memo(({ open = false, text = '加载中...', progress, color, indicatorProps, progressProps, ...props }) => {
|
|
9
|
-
const [visible, setVisible] =
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const [visible, setVisible] = useState(open);
|
|
10
|
+
useMemo(() => {
|
|
11
|
+
open && setVisible(true);
|
|
12
12
|
}, [open]);
|
|
13
13
|
const onExited = () => {
|
|
14
|
-
// 动画结束后,loading为false才需要改变visible
|
|
15
14
|
setVisible(false);
|
|
16
15
|
};
|
|
17
16
|
const showProgress = typeof progress === 'number';
|
|
18
|
-
return open || visible
|
|
17
|
+
return open || visible
|
|
19
18
|
? _jsxs(Backdrop, { variant: "light", ...props, css: style, open: open, className: clsx(classes.root, props.className), onExited: onExited, "data-show-progress": showProgress, children: [_jsxs("div", { className: classes.indicator, children: [_jsx(LoadingIndicator, { size: showProgress ? 14 : 30, borderWidth: showProgress ? 2 : 3, color: color, ...indicatorProps }), _jsx("div", { className: classes.text, children: text })] }), showProgress &&
|
|
20
19
|
_jsx(Progress, { className: classes.progress, value: progress, ...progressProps })] })
|
|
21
20
|
: null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
2
2
|
import { cloneElement, isValidElement, useCallback, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
|
-
import { clsx, cloneRef, listenAllPredecessorsScroll, toArray, useControlled, useDerivedState, useForceUpdate, useSync, useSyncState, useUnmounted, useContainer, isElementOverflowed, isChildOf } from '../../utils';
|
|
4
|
+
import { clsx, cloneRef, listenAllPredecessorsScroll, toArray, useControlled, useDerivedState, useForceUpdate, useSync, useSyncState, useUnmounted, useContainer, isElementOverflowed, isChildOf, useUpdateEffect } from '../../utils';
|
|
5
5
|
import { ClickAway } from '../clickAway';
|
|
6
6
|
import { classes, style } from './popper.style';
|
|
7
7
|
import { PopperContext, usePopperContext } from './popperContext';
|
|
@@ -54,12 +54,7 @@ export function Popper({ ref, popperRef, anchorElement, container, effectContain
|
|
|
54
54
|
}
|
|
55
55
|
};
|
|
56
56
|
const { onChildrenOpenChange: tellParentOpenChange } = usePopperContext();
|
|
57
|
-
|
|
58
|
-
useEffect(() => {
|
|
59
|
-
if (!initialized.current) {
|
|
60
|
-
initialized.current = true;
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
57
|
+
useUpdateEffect(() => {
|
|
63
58
|
tellParentOpenChange(innerOpen.current);
|
|
64
59
|
}, [innerOpen.current]);
|
|
65
60
|
const onChildrenOpenChange = (childrenOpen) => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { createContext, useContext, useRef,
|
|
1
|
+
import { createContext, useContext, useRef, useCallback } from 'react';
|
|
2
|
+
import { useExternalClass } from '../../utils';
|
|
2
3
|
export const PopperContext = createContext({
|
|
3
4
|
autoClose: false,
|
|
4
5
|
open: false,
|
|
@@ -25,11 +26,10 @@ export function useScrollToTarget(scrollerRef) {
|
|
|
25
26
|
scrollerEl.scrollTop = targetEl.offsetTop + targetEl.clientHeight / 2 - scrollerEl.clientHeight / 2;
|
|
26
27
|
}
|
|
27
28
|
}, []);
|
|
28
|
-
|
|
29
|
+
useExternalClass(() => {
|
|
29
30
|
beforeOpenCallbacks.add(beforeOpen);
|
|
30
|
-
},
|
|
31
|
-
useEffect(() => () => {
|
|
31
|
+
}, () => {
|
|
32
32
|
beforeOpenCallbacks.delete(beforeOpen);
|
|
33
|
-
}
|
|
33
|
+
});
|
|
34
34
|
return ref;
|
|
35
35
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
2
2
|
import { createElement as _createElement } from "@emotion/react";
|
|
3
|
-
import { isValidElement, memo,
|
|
3
|
+
import { isValidElement, memo, useRef, useState } from 'react';
|
|
4
4
|
import { Collapse, Slide } from '../transitionBase';
|
|
5
|
-
import { clsx, getEasyID, useColor, useContainer } from '../../utils';
|
|
5
|
+
import { clsx, getEasyID, useColor, useContainer, useUnmounted } from '../../utils';
|
|
6
6
|
import { classes, style } from './snackbarBase.style';
|
|
7
7
|
import { TransitionGroup } from 'react-transition-group';
|
|
8
8
|
import { StatusIcon, statusMapToIconDefinition } from '../status';
|
|
@@ -36,9 +36,7 @@ const placementToIndex = {
|
|
|
36
36
|
export const SnackbarBase = memo(({ methods, useTo, max = useTo === 'message' ? 5 : 4, container, effectContainer }) => {
|
|
37
37
|
const [stacks, setStacks] = useState([]);
|
|
38
38
|
const timers = useRef([]);
|
|
39
|
-
|
|
40
|
-
timers.current.forEach(timer => clearTimeout(timer));
|
|
41
|
-
}, []);
|
|
39
|
+
const isUnmounted = useUnmounted();
|
|
42
40
|
const defineMethod = (type) => (props) => new Promise(resolve => {
|
|
43
41
|
const propsObject = typeof props === 'object' && !isValidElement(props)
|
|
44
42
|
? props
|
|
@@ -47,7 +45,7 @@ export const SnackbarBase = memo(({ methods, useTo, max = useTo === 'message' ?
|
|
|
47
45
|
const index = placementToIndex[placement];
|
|
48
46
|
let id = getEasyID('snackbar');
|
|
49
47
|
const onCloseButtonClick = () => {
|
|
50
|
-
setStacks(o => {
|
|
48
|
+
!isUnmounted.current && setStacks(o => {
|
|
51
49
|
o[index] = o[index].filter(s => s.id !== id);
|
|
52
50
|
return [...o];
|
|
53
51
|
});
|
|
@@ -75,15 +75,17 @@ export const Tabs = memo(({ tabs, labelKey = 'label', primaryKey = 'value', vari
|
|
|
75
75
|
const [shadowStart, setShadowStart] = useState(false);
|
|
76
76
|
const [shadowEnd, setShadowEnd] = useState(false);
|
|
77
77
|
const setShadow = () => {
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
78
|
+
if (scrollRef.current) {
|
|
79
|
+
if (position === 'top' || position === 'bottom') {
|
|
80
|
+
const { scrollLeft } = scrollRef.current;
|
|
81
|
+
setShadowStart(scrollLeft > 0);
|
|
82
|
+
setShadowEnd(scrollLeft < scrollRef.current.scrollWidth - scrollRef.current.clientWidth);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
const { scrollTop } = scrollRef.current;
|
|
86
|
+
setShadowStart(scrollTop > 0);
|
|
87
|
+
setShadowEnd(scrollTop < scrollRef.current.scrollHeight - scrollRef.current.clientHeight);
|
|
88
|
+
}
|
|
87
89
|
}
|
|
88
90
|
};
|
|
89
91
|
useEffect(() => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { useRef, useState } from 'react';
|
|
3
3
|
import { TransitionBase } from './transitionBase';
|
|
4
|
-
import { cloneRef } from '../../utils';
|
|
4
|
+
import { cloneRef, useStrictEffect } from '../../utils';
|
|
5
5
|
export const Collapse = ({ transitionType = 'sweeping', ...props }) => {
|
|
6
6
|
const Component = transitionType === 'sweeping' ? Sweeping : TransitionBase;
|
|
7
7
|
return (_jsx(Component, { ...props, _mode: transitionType === 'sweeping' ? '_sweeping' : 'collapse' }));
|
|
@@ -29,11 +29,11 @@ const Sweeping = ({ ref, in: _in = false, appear = true, orientation = 'vertical
|
|
|
29
29
|
setSize(getCollapsedSize());
|
|
30
30
|
});
|
|
31
31
|
};
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
if (!
|
|
32
|
+
const mounted = useRef(false);
|
|
33
|
+
useStrictEffect(() => {
|
|
34
|
+
if (!mounted.current) {
|
|
35
35
|
// 首次渲染
|
|
36
|
-
|
|
36
|
+
mounted.current = true;
|
|
37
37
|
if (!appear) {
|
|
38
38
|
// 若appear为false,则跳过首次动画
|
|
39
39
|
return;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
2
|
-
import { Children, isValidElement,
|
|
2
|
+
import { Children, isValidElement, useLayoutEffect, useRef } from 'react';
|
|
3
3
|
import { classes, useStyle } from './waterfall.style';
|
|
4
4
|
import { WaterfallItem } from './waterfallItem';
|
|
5
|
-
import { cloneRef, clsx, toResponsiveValue, useResponsiveValue } from '../../utils';
|
|
5
|
+
import { cloneRef, clsx, toResponsiveValue, useExternalClass, useResponsiveValue, useUpdateEffect } from '../../utils';
|
|
6
6
|
export const Waterfall = ({ columnCount = { xs: 4 }, gap = 0, columnGap, rowGap, ...props }) => {
|
|
7
7
|
columnCount = toResponsiveValue(columnCount);
|
|
8
8
|
gap = toResponsiveValue(gap);
|
|
@@ -29,17 +29,10 @@ export const Waterfall = ({ columnCount = { xs: 4 }, gap = 0, columnGap, rowGap,
|
|
|
29
29
|
elements.current.forEach(el => resizeObserver.current.observe(el));
|
|
30
30
|
});
|
|
31
31
|
});
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (!isInitialized.current) {
|
|
35
|
-
isInitialized.current = true;
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
computeItemOrder();
|
|
39
|
-
}, [columnCountNum.current]);
|
|
40
|
-
useEffect(() => () => {
|
|
32
|
+
useUpdateEffect(computeItemOrder, [columnCountNum.current]);
|
|
33
|
+
useExternalClass(() => void 0, () => {
|
|
41
34
|
resizeObserver.current.disconnect();
|
|
42
|
-
}
|
|
35
|
+
});
|
|
43
36
|
return (_jsx("div", { ...props, ref: cloneRef(containerRef, props.ref), css: useStyle({ columnCount, columnGap, rowGap }), className: clsx(classes.root, props.className), children: Children.map(props.children, child => {
|
|
44
37
|
if (!isValidElement(child)) {
|
|
45
38
|
throw Error('Children of <Waterfall> must be element');
|
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import { RefObject, Dispatch, SetStateAction } from 'react';
|
|
1
|
+
import { RefObject, Dispatch, SetStateAction, EffectCallback, DependencyList } from 'react';
|
|
2
2
|
import { DefineElement } from '../types';
|
|
3
|
-
/**
|
|
4
|
-
* 获取渲染前的值
|
|
5
|
-
* @param value
|
|
6
|
-
*/
|
|
7
|
-
export declare function usePrev<T>(value: T): T | null;
|
|
8
3
|
/**
|
|
9
4
|
* 将某个值使用ref同步,主要用于对付组件的闭包问题
|
|
10
5
|
* @param value
|
|
@@ -27,6 +22,7 @@ export declare function useForceUpdate(): () => void;
|
|
|
27
22
|
*/
|
|
28
23
|
export declare function useDerivedState<T>(referredState: (prevState: T | undefined) => T, deps: any[]): [RefObject<T>, Dispatch<SetStateAction<T>>];
|
|
29
24
|
export declare function useDerivedState<T>(referredState: T, deps?: any[]): [RefObject<T>, Dispatch<SetStateAction<T>>];
|
|
25
|
+
export declare function useMounted(): void;
|
|
30
26
|
/**
|
|
31
27
|
* 组件卸载后得到{current: true}
|
|
32
28
|
* @returns
|
|
@@ -60,3 +56,11 @@ export declare function useContainer<T extends HTMLElement | null>(container?: D
|
|
|
60
56
|
* 使用外部类,该方法可避免`StrictMode`下,React渲染行为与外部类实例生命周期不同步的问题
|
|
61
57
|
*/
|
|
62
58
|
export declare function useExternalClass<T>(setup: () => T, cleanup?: (instance: T) => void): T;
|
|
59
|
+
/**
|
|
60
|
+
* 用法同{@link useEffect},但StrictMode下不会执行两次
|
|
61
|
+
*/
|
|
62
|
+
export declare function useStrictEffect(effect: EffectCallback, deps?: DependencyList): void;
|
|
63
|
+
/**
|
|
64
|
+
* 用法同{@link useEffect},但会排除首次渲染
|
|
65
|
+
*/
|
|
66
|
+
export declare function useUpdateEffect(effect: EffectCallback, deps?: DependencyList): void;
|
package/dist/esm/utils/hooks.js
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
1
|
import { useRef, useEffect, useState, useCallback, useMemo } from 'react';
|
|
2
|
-
import { isPromise, getPromiseState } from './utils';
|
|
3
|
-
/**
|
|
4
|
-
* 获取渲染前的值
|
|
5
|
-
* @param value
|
|
6
|
-
*/
|
|
7
|
-
export function usePrev(value) {
|
|
8
|
-
const prev = useRef(null);
|
|
9
|
-
useEffect(() => {
|
|
10
|
-
prev.current = value;
|
|
11
|
-
});
|
|
12
|
-
return prev.current;
|
|
13
|
-
}
|
|
2
|
+
import { isPromise, getPromiseState, arrayShallowEqual } from './utils';
|
|
14
3
|
/**
|
|
15
4
|
* 将某个值使用ref同步,主要用于对付组件的闭包问题
|
|
16
5
|
* @param value
|
|
@@ -42,6 +31,10 @@ export function useForceUpdate() {
|
|
|
42
31
|
}
|
|
43
32
|
export function useDerivedState(referredState, deps) {
|
|
44
33
|
const derivedState = useRef(void 0);
|
|
34
|
+
useMemo(() => {
|
|
35
|
+
// SSR模式下,derivedState会重置2次
|
|
36
|
+
derivedState.current = void 0;
|
|
37
|
+
}, []);
|
|
45
38
|
const updateState = (state) => {
|
|
46
39
|
const newState = typeof state === 'function' ? state(derivedState.current) : state;
|
|
47
40
|
if (derivedState.current !== newState) {
|
|
@@ -62,13 +55,15 @@ export function useDerivedState(referredState, deps) {
|
|
|
62
55
|
}, [])
|
|
63
56
|
];
|
|
64
57
|
}
|
|
58
|
+
export function useMounted() {
|
|
59
|
+
}
|
|
65
60
|
/**
|
|
66
61
|
* 组件卸载后得到{current: true}
|
|
67
62
|
* @returns
|
|
68
63
|
*/
|
|
69
64
|
export function useUnmounted() {
|
|
70
65
|
const isUnmounted = useRef(false);
|
|
71
|
-
useExternalClass(() => void 0, () =>
|
|
66
|
+
useExternalClass(() => void 0, () => {
|
|
72
67
|
isUnmounted.current = true;
|
|
73
68
|
});
|
|
74
69
|
return isUnmounted;
|
|
@@ -152,3 +147,29 @@ export function useExternalClass(setup, cleanup) {
|
|
|
152
147
|
}, []);
|
|
153
148
|
return instance;
|
|
154
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* 用法同{@link useEffect},但StrictMode下不会执行两次
|
|
152
|
+
*/
|
|
153
|
+
export function useStrictEffect(effect, deps) {
|
|
154
|
+
const prevDeps = useRef(void 0);
|
|
155
|
+
useEffect(() => {
|
|
156
|
+
const isDepsChanged = prevDeps.current ? !arrayShallowEqual(prevDeps.current, deps) : true;
|
|
157
|
+
if (isDepsChanged) {
|
|
158
|
+
prevDeps.current = deps;
|
|
159
|
+
return effect();
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* 用法同{@link useEffect},但会排除首次渲染
|
|
165
|
+
*/
|
|
166
|
+
export function useUpdateEffect(effect, deps) {
|
|
167
|
+
const mounted = useRef(false);
|
|
168
|
+
useStrictEffect(() => {
|
|
169
|
+
if (!mounted.current) {
|
|
170
|
+
mounted.current = true;
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
return effect();
|
|
174
|
+
}, [deps]);
|
|
175
|
+
}
|
package/dist/esm/utils/tree.js
CHANGED
|
@@ -82,34 +82,36 @@ export function sortTreeNodes(props, sortInfo) {
|
|
|
82
82
|
}
|
|
83
83
|
return null;
|
|
84
84
|
};
|
|
85
|
-
pickUp(nodes);
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
for (let i = 0, { length } = nodes; i < length; i++) {
|
|
91
|
-
const node = nodes[i];
|
|
92
|
-
if (node[primaryKey] === destination) {
|
|
93
|
-
switch (placement) {
|
|
94
|
-
case 'before':
|
|
95
|
-
nodes.splice(i, 0, node);
|
|
96
|
-
return true;
|
|
97
|
-
case 'after':
|
|
98
|
-
nodes.splice(i + 1, 0, node);
|
|
99
|
-
return true;
|
|
100
|
-
default:
|
|
101
|
-
node.children ||= [];
|
|
102
|
-
node.children.push(node);
|
|
103
|
-
return true;
|
|
104
|
-
}
|
|
85
|
+
const sourceNode = pickUp(nodes);
|
|
86
|
+
if (sourceNode) {
|
|
87
|
+
const putDown = (nodes) => {
|
|
88
|
+
if (!nodes?.length) {
|
|
89
|
+
return false;
|
|
105
90
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
91
|
+
for (let i = 0, { length } = nodes; i < length; i++) {
|
|
92
|
+
const node = nodes[i];
|
|
93
|
+
if (node[primaryKey] === destination) {
|
|
94
|
+
switch (placement) {
|
|
95
|
+
case 'before':
|
|
96
|
+
nodes.splice(i, 0, sourceNode);
|
|
97
|
+
return true;
|
|
98
|
+
case 'after':
|
|
99
|
+
nodes.splice(i + 1, 0, sourceNode);
|
|
100
|
+
return true;
|
|
101
|
+
default:
|
|
102
|
+
node.children ||= [];
|
|
103
|
+
node.children.push(sourceNode);
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const foundInChildren = putDown(node[childrenKey]);
|
|
108
|
+
if (foundInChildren) {
|
|
109
|
+
return foundInChildren;
|
|
110
|
+
}
|
|
109
111
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
return false;
|
|
113
|
+
};
|
|
114
|
+
putDown(nodes);
|
|
115
|
+
}
|
|
114
116
|
return nodes;
|
|
115
117
|
}
|
|
@@ -47,6 +47,7 @@ export declare function mergeDeep<T extends {}, U, V, W, X>(target: T, source: U
|
|
|
47
47
|
export declare function mergeDeep<T extends {}, U, V, W, X, Y>(target: T, source: U, source2: V, source3: W, source4: X, source5: Y): T & U & V & W & X & Y;
|
|
48
48
|
export declare function mergeDeep<T extends {}, U, V, W, X, Y, Z>(target: T, source: U, source2: V, source3: W, source4: X, source5: Y, source6: Z): T & U & V & W & X & Y & Z;
|
|
49
49
|
export declare function mergeDeep(target: object, ...sources: any[]): any;
|
|
50
|
+
export declare function arrayShallowEqual(a: any[], b: any[]): boolean;
|
|
50
51
|
export type OverflowEdge = 'top' | 'bottom' | 'left' | 'right';
|
|
51
52
|
/**
|
|
52
53
|
* 判断元素是否完全在目标容器内,用于Popper组件
|
package/dist/esm/utils/utils.js
CHANGED
|
@@ -111,6 +111,22 @@ export function mergeDeep(target, ...sources) {
|
|
|
111
111
|
}
|
|
112
112
|
return target;
|
|
113
113
|
}
|
|
114
|
+
export function arrayShallowEqual(a, b) {
|
|
115
|
+
if (a === b) {
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
if (a.length !== b.length) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
let isEqual = true;
|
|
122
|
+
for (let i = 0, { length } = a; i < length; i++) {
|
|
123
|
+
if (a[i] !== b[i]) {
|
|
124
|
+
isEqual = false;
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return isEqual;
|
|
129
|
+
}
|
|
114
130
|
/**
|
|
115
131
|
* 判断元素是否完全在目标容器内,用于Popper组件
|
|
116
132
|
* @param target 目标元素
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canlooks/can-ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.117",
|
|
4
4
|
"author": "C.CanLiang <canlooks@gmail.com>",
|
|
5
5
|
"description": "My ui framework",
|
|
6
6
|
"license": "MIT",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"build:documentation": "vite build -c documentation/vite.config.mts && tsc -p documentation/tsconfig.bootstrap.json",
|
|
45
45
|
"rebuild": "npm run clean && npm run build:core && npm run build:documentation",
|
|
46
46
|
"dev": "vite -c test/vite.config.mts",
|
|
47
|
+
"dev:ssr": "next dev test",
|
|
47
48
|
"dev:documentation": "vite -c documentation/vite.config.mts --host",
|
|
48
49
|
"test:unit": "npx ts-node test/unit.ts"
|
|
49
50
|
},
|
|
@@ -74,6 +75,7 @@
|
|
|
74
75
|
"@types/react-syntax-highlighter": "^15.5.13",
|
|
75
76
|
"@types/react-transition-group": "^4.4.12",
|
|
76
77
|
"mime": "^4.1.0",
|
|
78
|
+
"next": "^16.0.10",
|
|
77
79
|
"react": "^19.2.3",
|
|
78
80
|
"react-dom": "^19.2.3",
|
|
79
81
|
"react-markdown": "^10.1.0",
|