@canlooks/can-ui 0.0.111 → 0.0.113
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/app/app.js +2 -2
- package/dist/cjs/components/image/image.js +1 -1
- package/dist/cjs/components/overlayBase/overlayBase.d.ts +1 -1
- package/dist/cjs/components/overlayBase/overlayBase.js +1 -1
- package/dist/cjs/components/pinchable/pinchable.js +14 -10
- package/dist/cjs/components/popper/popper.js +1 -1
- package/dist/cjs/components/snackbarBase/snackbarBase.d.ts +1 -1
- package/dist/cjs/components/snackbarBase/snackbarBase.js +1 -1
- package/dist/cjs/components/sortableItem/sortableItem.js +8 -5
- package/dist/cjs/components/sortableItem/sortableItem.style.d.ts +5 -0
- package/dist/cjs/components/sortableItem/sortableItem.style.js +18 -0
- package/dist/cjs/components/tree/treeDnd.js +3 -2
- package/dist/cjs/components/tree/treeDnd.style.d.ts +1 -0
- package/dist/cjs/components/tree/treeDnd.style.js +6 -1
- package/dist/cjs/components/tree/treeNode.js +12 -0
- package/dist/cjs/utils/hooks.d.ts +5 -1
- package/dist/cjs/utils/hooks.js +25 -6
- package/dist/cjs/utils/tree.d.ts +9 -0
- package/dist/cjs/utils/tree.js +56 -0
- package/dist/esm/components/app/app.js +4 -4
- package/dist/esm/components/image/image.js +1 -1
- package/dist/esm/components/overlayBase/overlayBase.d.ts +1 -1
- package/dist/esm/components/overlayBase/overlayBase.js +1 -1
- package/dist/esm/components/pinchable/pinchable.js +14 -10
- package/dist/esm/components/popper/popper.js +1 -1
- package/dist/esm/components/snackbarBase/snackbarBase.d.ts +1 -1
- package/dist/esm/components/snackbarBase/snackbarBase.js +1 -1
- package/dist/esm/components/sortableItem/sortableItem.js +10 -7
- package/dist/esm/components/sortableItem/sortableItem.style.d.ts +5 -0
- package/dist/esm/components/sortableItem/sortableItem.style.js +15 -0
- package/dist/esm/components/tree/treeDnd.js +5 -4
- package/dist/esm/components/tree/treeDnd.style.d.ts +1 -0
- package/dist/esm/components/tree/treeDnd.style.js +5 -0
- package/dist/esm/components/tree/treeNode.js +12 -0
- package/dist/esm/utils/hooks.d.ts +5 -1
- package/dist/esm/utils/hooks.js +24 -6
- package/dist/esm/utils/tree.d.ts +9 -0
- package/dist/esm/utils/tree.js +55 -0
- package/package.json +1 -1
|
@@ -27,12 +27,12 @@ exports.App = (({ theme, ...props }) => {
|
|
|
27
27
|
return ((0, jsx_runtime_1.jsx)(globalEventDelegation_1.GlobalEventDelegation, { children: (0, jsx_runtime_1.jsx)(theme_1.ThemeProvider, { theme: theme, children: (0, jsx_runtime_1.jsx)(InnerApp, { ...props }) }) }));
|
|
28
28
|
});
|
|
29
29
|
function InnerApp({ component: Component = 'div', theme, children, fill = true, ...props }) {
|
|
30
|
-
const appValue = (0,
|
|
30
|
+
const appValue = (0, utils_1.useExternalClass)(() => ({
|
|
31
31
|
dialog: exports.App.dialog = new appDialog_1.AppDialogMethods(),
|
|
32
32
|
message: exports.App.message = new appMessage_1.AppMessageMethods(),
|
|
33
33
|
notification: exports.App.notification = new appNotification_1.AppNotificationMethods(),
|
|
34
34
|
actionSheet: exports.App.actionSheet = new appActionSheet_1.AppActionSheetMethods()
|
|
35
|
-
})
|
|
35
|
+
}));
|
|
36
36
|
return ((0, jsx_runtime_1.jsxs)(AppContext, { value: appValue, children: [Component
|
|
37
37
|
? (0, jsx_runtime_1.jsx)(Component, { ...props, css: [
|
|
38
38
|
app_style_1.style,
|
|
@@ -47,6 +47,6 @@ exports.Image = (0, react_1.memo)(({ src, fallback, onLoad, onError, renderLoadi
|
|
|
47
47
|
}, onLoad: loadHandler, onError: errorHandler }), loading.current &&
|
|
48
48
|
(renderLoading ?? (0, jsx_runtime_1.jsx)(skeleton_1.Skeleton, { className: image_style_1.classes.skeleton })), !!renderedActions && !failed.current &&
|
|
49
49
|
(0, jsx_runtime_1.jsx)("div", { className: image_style_1.classes.mask, children: renderedActions }), previewable && src &&
|
|
50
|
-
(0, jsx_runtime_1.jsx)(gallery_1.Gallery, { src: [src], ...previewProps, open: previewOpen.current, onOpenChange: setPreviewOpen })] }));
|
|
50
|
+
(0, jsx_runtime_1.jsx)(gallery_1.Gallery, { src: [src], ...previewProps, open: previewOpen.current, onOpenChange: setPreviewOpen, onPointerDown: e => e.stopPropagation() })] }));
|
|
51
51
|
});
|
|
52
52
|
exports.Image.Gallery = gallery_1.Gallery;
|
|
@@ -24,4 +24,4 @@ export interface OverlayBaseProps extends DivProps {
|
|
|
24
24
|
removeFocusOnOpen?: boolean;
|
|
25
25
|
}
|
|
26
26
|
export declare const overlayBaseTransitionDuration = 300;
|
|
27
|
-
export declare function OverlayBase({ container, effectContainer, forceRender, open, onMaskClick, singleLayer, onOpened, onClosed, maskProps, removeFocusOnOpen, ...props }: OverlayBaseProps): false | React.ReactPortal;
|
|
27
|
+
export declare function OverlayBase({ container, effectContainer, forceRender, open, onMaskClick, singleLayer, onOpened, onClosed, maskProps, removeFocusOnOpen, ...props }: OverlayBaseProps): false | React.ReactPortal | null;
|
|
@@ -37,7 +37,7 @@ function OverlayBase({ container, effectContainer, forceRender, open, onMaskClic
|
|
|
37
37
|
onClosed?.();
|
|
38
38
|
forceRender === false && setShouldRender(false);
|
|
39
39
|
};
|
|
40
|
-
return shouldRender.current && (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsxs)("div", { ...props, css: overlayBase_style_1.style, className: (0, utils_1.clsx)(overlayBase_style_1.classes.root, props.className), "data-open": open, "data-custom-container": containerEl.current !== document.body, children: [(0, jsx_runtime_1.jsx)(transitionBase_1.Fade, { timeout: exports.overlayBaseTransitionDuration, ...(0, utils_1.mergeComponentProps)(maskProps, {
|
|
40
|
+
return shouldRender.current && containerEl.current && (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsxs)("div", { ...props, css: overlayBase_style_1.style, className: (0, utils_1.clsx)(overlayBase_style_1.classes.root, props.className), "data-open": open, "data-custom-container": containerEl.current !== document.body, children: [(0, jsx_runtime_1.jsx)(transitionBase_1.Fade, { timeout: exports.overlayBaseTransitionDuration, ...(0, utils_1.mergeComponentProps)(maskProps, {
|
|
41
41
|
in: open,
|
|
42
42
|
className: overlayBase_style_1.classes.mask,
|
|
43
43
|
onClick,
|
|
@@ -15,12 +15,12 @@ exports.Pinchable = (({ component: Component = 'div', ref, gestureOptions, defau
|
|
|
15
15
|
zoomFn(innerScale.current * .5);
|
|
16
16
|
};
|
|
17
17
|
wrapperRef.current.zoomTo = zoomFn;
|
|
18
|
-
wrapperRef.current.rotate =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
wrapperRef.current.rotate = rotateFn;
|
|
19
|
+
wrapperRef.current.rotateLeft = () => {
|
|
20
|
+
rotateFn(innerRotate.current - 90);
|
|
21
|
+
};
|
|
22
22
|
wrapperRef.current.rotateRight = () => {
|
|
23
|
-
rotateFn(innerRotate.current
|
|
23
|
+
rotateFn(innerRotate.current - 90);
|
|
24
24
|
};
|
|
25
25
|
wrapperRef.current.reset = resetAll;
|
|
26
26
|
}
|
|
@@ -134,7 +134,7 @@ exports.Pinchable = (({ component: Component = 'div', ref, gestureOptions, defau
|
|
|
134
134
|
resetZoom(false);
|
|
135
135
|
setInnerRotate(0);
|
|
136
136
|
};
|
|
137
|
-
const
|
|
137
|
+
const onDoubleClick = (e) => {
|
|
138
138
|
childrenProps.onDoubleClick?.(e);
|
|
139
139
|
if (innerScale.current < 1.5) {
|
|
140
140
|
zoomFn(3, e.clientX, e.clientY);
|
|
@@ -143,12 +143,16 @@ exports.Pinchable = (({ component: Component = 'div', ref, gestureOptions, defau
|
|
|
143
143
|
resetZoom();
|
|
144
144
|
}
|
|
145
145
|
};
|
|
146
|
-
const
|
|
146
|
+
const onWheel = (e) => {
|
|
147
147
|
childrenProps.onMouseWheel?.(e);
|
|
148
148
|
e.deltaY > 0
|
|
149
149
|
? zoomFn(innerScale.current * .8, e.clientX, e.clientY)
|
|
150
150
|
: zoomFn(innerScale.current * 1.2, e.clientX, e.clientY);
|
|
151
151
|
};
|
|
152
|
+
const onTransitionEnd = (e) => {
|
|
153
|
+
e.currentTarget.dataset.transition = 'false';
|
|
154
|
+
setInnerRotate(innerRotate.current % 360);
|
|
155
|
+
};
|
|
152
156
|
return ((0, jsx_runtime_1.jsx)(Component, { ...props, ref: wrapperRef, css: pinchable_style_1.style, className: (0, utils_1.clsx)(pinchable_style_1.classes.root, props.className), ...pinchableHandles, children: (0, react_1.cloneElement)(children, {
|
|
153
157
|
ref: (0, utils_1.cloneRef)(contentRef, childrenProps.ref),
|
|
154
158
|
className: (0, utils_1.clsx)(pinchable_style_1.classes.content, childrenProps.className),
|
|
@@ -160,8 +164,8 @@ exports.Pinchable = (({ component: Component = 'div', ref, gestureOptions, defau
|
|
|
160
164
|
transformOrigin: 'center'
|
|
161
165
|
},
|
|
162
166
|
...draggableHandles,
|
|
163
|
-
onDoubleClick
|
|
164
|
-
onWheel
|
|
165
|
-
onTransitionEnd
|
|
167
|
+
onDoubleClick,
|
|
168
|
+
onWheel,
|
|
169
|
+
onTransitionEnd
|
|
166
170
|
}) }));
|
|
167
171
|
});
|
|
@@ -537,7 +537,7 @@ function Popper({ ref, popperRef, anchorElement, container = document.body, effe
|
|
|
537
537
|
? (0, react_1.cloneElement)(children, {
|
|
538
538
|
ref: childRef
|
|
539
539
|
})
|
|
540
|
-
: children, renderedOnce.current && (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsx)(clickAway_1.ClickAway, { disabled: !clickable && !enterable && !contextMenuable,
|
|
540
|
+
: children, renderedOnce.current && containerEl.current && (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsx)(clickAway_1.ClickAway, { disabled: !clickable && !enterable && !contextMenuable,
|
|
541
541
|
// 右键菜单点击anchor需要关闭弹框
|
|
542
542
|
targets: () => contextMenuEvent.current ? void 0 : getAnchorElement(), onClickAway: onClickAway, children: (0, jsx_runtime_1.jsx)("div", { ...props, ref: innerPopperRef, css: popper_style_1.style, className: (0, utils_1.clsx)(popper_style_1.classes.root, props.className), style: {
|
|
543
543
|
...popperBounding,
|
|
@@ -30,7 +30,7 @@ export declare const SnackbarBase: React.MemoExoticComponent<({ methods, useTo,
|
|
|
30
30
|
max?: number;
|
|
31
31
|
container?: DefineElement<HTMLElement>;
|
|
32
32
|
effectContainer?: DefineElement<HTMLElement>;
|
|
33
|
-
}) => React.ReactPortal>;
|
|
33
|
+
}) => React.ReactPortal | null>;
|
|
34
34
|
interface SnackbarBaseItemProps extends Omit<SnackbarBaseProps, 'duration' | 'onAutoClose'> {
|
|
35
35
|
id: string;
|
|
36
36
|
type: keyof SnackbarBaseMethods;
|
|
@@ -86,7 +86,7 @@ exports.SnackbarBase = (0, react_2.memo)(({ methods, useTo, max = useTo === 'mes
|
|
|
86
86
|
methods.error = defineMethod('error');
|
|
87
87
|
const css = (0, snackbarBase_style_1.style)();
|
|
88
88
|
const containerEl = (0, utils_1.useContainer)(container, effectContainer);
|
|
89
|
-
return (0, react_dom_1.createPortal)(stacks.flatMap((stack, i) => stack
|
|
89
|
+
return containerEl.current && (0, react_dom_1.createPortal)(stacks.flatMap((stack, i) => stack
|
|
90
90
|
? (0, jsx_runtime_1.jsx)(react_transition_group_1.TransitionGroup, { css: css, className: snackbarBase_style_1.classes.root, "data-place": i, "data-use-to": useTo, children: stack.map(p => (0, react_1.createElement)(exports.SnackbarBaseItem, { ...p, key: p.id })) }, i)
|
|
91
91
|
: []), containerEl.current);
|
|
92
92
|
});
|
|
@@ -6,6 +6,9 @@ const react_1 = require("react");
|
|
|
6
6
|
const sortable_1 = require("@dnd-kit/sortable");
|
|
7
7
|
const utilities_1 = require("@dnd-kit/utilities");
|
|
8
8
|
const utils_1 = require("../../utils");
|
|
9
|
+
const react_2 = require("@emotion/react");
|
|
10
|
+
const treeDnd_style_1 = require("../tree/treeDnd.style");
|
|
11
|
+
const sortableItem_style_1 = require("./sortableItem.style");
|
|
9
12
|
exports.SortableItem = (({ component: Component = 'div', id, disabled, sortableArguments, ...props }) => {
|
|
10
13
|
const { attributes, isDragging, listeners, setNodeRef, transform, transition } = (0, sortable_1.useSortable)({
|
|
11
14
|
...sortableArguments,
|
|
@@ -30,9 +33,9 @@ exports.SortableItem = (({ component: Component = 'div', id, disabled, sortableA
|
|
|
30
33
|
addEventListener('pointerup', onPointerUp);
|
|
31
34
|
}, []);
|
|
32
35
|
(0, react_1.useEffect)(() => removeListener, []);
|
|
33
|
-
return ((0, jsx_runtime_1.jsx)(Component, { ...attributes, ...listeners, ...props, ref: (0, utils_1.cloneRef)(setNodeRef, props.ref), style: {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Component, { ...attributes, ...listeners, ...props, ref: (0, utils_1.cloneRef)(setNodeRef, props.ref), css: sortableItem_style_1.style, className: (0, utils_1.clsx)(sortableItem_style_1.classes.root, props.className), style: {
|
|
37
|
+
transform: utilities_1.CSS.Transform.toString(transform),
|
|
38
|
+
transition,
|
|
39
|
+
...props.style
|
|
40
|
+
}, onTouchStart: disabled ? void 0 : onTouchStart, "data-dragging": isDragging }), isDragging && (0, jsx_runtime_1.jsx)(react_2.Global, { styles: treeDnd_style_1.globalGrabbingStyle })] }));
|
|
38
41
|
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.globalGrabbingStyle = exports.style = exports.classes = void 0;
|
|
4
|
+
const react_1 = require("@emotion/react");
|
|
5
|
+
const utils_1 = require("../../utils");
|
|
6
|
+
exports.classes = (0, utils_1.defineInnerClasses)('sortable-item');
|
|
7
|
+
exports.style = (0, react_1.css) `
|
|
8
|
+
cursor: grab;
|
|
9
|
+
|
|
10
|
+
&:active {
|
|
11
|
+
cursor: grabbing;
|
|
12
|
+
}
|
|
13
|
+
`;
|
|
14
|
+
exports.globalGrabbingStyle = (0, react_1.css) `
|
|
15
|
+
* {
|
|
16
|
+
cursor: grabbing;
|
|
17
|
+
}
|
|
18
|
+
`;
|
|
@@ -5,6 +5,7 @@ exports.useTreeDndContext = useTreeDndContext;
|
|
|
5
5
|
const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
|
|
6
6
|
const react_1 = require("react");
|
|
7
7
|
const treeDnd_style_1 = require("./treeDnd.style");
|
|
8
|
+
const react_2 = require("@emotion/react");
|
|
8
9
|
exports.TreeDndContext = (0, react_1.createContext)({});
|
|
9
10
|
function useTreeDndContext() {
|
|
10
11
|
return (0, react_1.useContext)(exports.TreeDndContext);
|
|
@@ -13,8 +14,8 @@ exports.TreeDnd = (0, react_1.memo)(({ sortable, showDragHandle, onSort, childre
|
|
|
13
14
|
const dragging = (0, react_1.useState)(void 0);
|
|
14
15
|
const overing = (0, react_1.useRef)(void 0);
|
|
15
16
|
const placement = (0, react_1.useRef)(void 0);
|
|
16
|
-
return ((0, jsx_runtime_1.
|
|
17
|
+
return ((0, jsx_runtime_1.jsxs)(exports.TreeDndContext, { value: {
|
|
17
18
|
sortable, showDragHandle, onSort,
|
|
18
19
|
dragging, overing, placement
|
|
19
|
-
}, children: (0, jsx_runtime_1.jsx)("div", { className: treeDnd_style_1.treeDndClasses.levelBlock, children: children }) }));
|
|
20
|
+
}, children: [(0, jsx_runtime_1.jsx)("div", { className: treeDnd_style_1.treeDndClasses.levelBlock, children: children }), !!dragging[0] && (0, jsx_runtime_1.jsx)(react_2.Global, { styles: treeDnd_style_1.globalGrabbingStyle })] }));
|
|
20
21
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.treeDndClasses = void 0;
|
|
3
|
+
exports.globalGrabbingStyle = exports.treeDndClasses = void 0;
|
|
4
4
|
exports.useStyle = useStyle;
|
|
5
5
|
const tslib_1 = require("tslib");
|
|
6
6
|
const utils_1 = require("../../utils");
|
|
@@ -191,3 +191,8 @@ function useStyle({ indent }) {
|
|
|
191
191
|
}
|
|
192
192
|
`, [indent]);
|
|
193
193
|
}
|
|
194
|
+
exports.globalGrabbingStyle = (0, react_1.css) `
|
|
195
|
+
* {
|
|
196
|
+
cursor: grabbing;
|
|
197
|
+
}
|
|
198
|
+
`;
|
|
@@ -64,6 +64,7 @@ exports.TreeNode = (0, react_1.memo)(({ id, label, prefix, suffix, disabled, _le
|
|
|
64
64
|
const pointerLeavePredecessor = (e) => {
|
|
65
65
|
inactiveBlock(e.currentTarget);
|
|
66
66
|
};
|
|
67
|
+
const overingTimeout = (0, react_1.useRef)(void 0);
|
|
67
68
|
const activeBlock = (el, _placement, upLevel = 0) => {
|
|
68
69
|
if (_placement === 'parent') {
|
|
69
70
|
let i = upLevel;
|
|
@@ -93,6 +94,13 @@ exports.TreeNode = (0, react_1.memo)(({ id, label, prefix, suffix, disabled, _le
|
|
|
93
94
|
return true;
|
|
94
95
|
}
|
|
95
96
|
});
|
|
97
|
+
// 如果有children且为折叠状态,over在该节点上一定时间后,需要展开该节点
|
|
98
|
+
if (hasChildren && !currentExpanded) {
|
|
99
|
+
overingTimeout.current ||= setTimeout(() => {
|
|
100
|
+
overingTimeout.current = void 0;
|
|
101
|
+
toggleExpanded(id);
|
|
102
|
+
}, 600);
|
|
103
|
+
}
|
|
96
104
|
};
|
|
97
105
|
const inactiveBlock = (el) => {
|
|
98
106
|
if (el) {
|
|
@@ -105,6 +113,10 @@ exports.TreeNode = (0, react_1.memo)(({ id, label, prefix, suffix, disabled, _le
|
|
|
105
113
|
el.dataset.active = 'false';
|
|
106
114
|
});
|
|
107
115
|
overing.current = void 0;
|
|
116
|
+
if (overingTimeout.current) {
|
|
117
|
+
clearTimeout(overingTimeout.current);
|
|
118
|
+
overingTimeout.current = void 0;
|
|
119
|
+
}
|
|
108
120
|
};
|
|
109
121
|
/**
|
|
110
122
|
* ---------------------------------------------------------------------
|
|
@@ -55,4 +55,8 @@ export declare function useLoading<A extends any[], R>(fn: (...args: A) => R | P
|
|
|
55
55
|
* @param effectContainer
|
|
56
56
|
* @param defaultContainer 默认为`document.body`
|
|
57
57
|
*/
|
|
58
|
-
export declare function useContainer<T extends HTMLElement | null>(container?: DefineElement<T>, effectContainer?: DefineElement<T>, defaultContainer?: T): RefObject<T>;
|
|
58
|
+
export declare function useContainer<T extends HTMLElement | null>(container?: DefineElement<T>, effectContainer?: DefineElement<T>, defaultContainer?: DefineElement<T>): RefObject<T | null>;
|
|
59
|
+
/**
|
|
60
|
+
* 使用外部类,该方法可避免`StrictMode`下,React渲染行为与外部类实例生命周期不同步的问题
|
|
61
|
+
*/
|
|
62
|
+
export declare function useExternalClass<T>(setup: () => T, cleanup?: (instance: T) => void): T;
|
package/dist/cjs/utils/hooks.js
CHANGED
|
@@ -9,6 +9,7 @@ exports.useUnmounted = useUnmounted;
|
|
|
9
9
|
exports.useControlled = useControlled;
|
|
10
10
|
exports.useLoading = useLoading;
|
|
11
11
|
exports.useContainer = useContainer;
|
|
12
|
+
exports.useExternalClass = useExternalClass;
|
|
12
13
|
const react_1 = require("react");
|
|
13
14
|
const utils_1 = require("./utils");
|
|
14
15
|
/**
|
|
@@ -130,18 +131,36 @@ function useLoading(fn, referredLoading = false) {
|
|
|
130
131
|
* @param effectContainer
|
|
131
132
|
* @param defaultContainer 默认为`document.body`
|
|
132
133
|
*/
|
|
133
|
-
function useContainer(container, effectContainer, defaultContainer
|
|
134
|
+
function useContainer(container, effectContainer, defaultContainer) {
|
|
134
135
|
const [containerEl, setContainerEl] = useDerivedState(prev => {
|
|
135
136
|
if (container) {
|
|
136
137
|
return typeof container === 'function' ? container() : container;
|
|
137
138
|
}
|
|
138
|
-
return prev ||
|
|
139
|
-
}, [container
|
|
139
|
+
return prev || null;
|
|
140
|
+
}, [container]);
|
|
140
141
|
(0, react_1.useEffect)(() => {
|
|
141
|
-
|
|
142
|
-
|
|
142
|
+
const _container = effectContainer || defaultContainer || document.body;
|
|
143
|
+
if (_container) {
|
|
144
|
+
const el = typeof _container === 'function' ? _container() : _container;
|
|
143
145
|
setContainerEl(el);
|
|
144
146
|
}
|
|
145
|
-
}, []);
|
|
147
|
+
}, [effectContainer, defaultContainer]);
|
|
146
148
|
return containerEl;
|
|
147
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* 使用外部类,该方法可避免`StrictMode`下,React渲染行为与外部类实例生命周期不同步的问题
|
|
152
|
+
*/
|
|
153
|
+
function useExternalClass(setup, cleanup) {
|
|
154
|
+
const mountTimes = (0, react_1.useRef)(0);
|
|
155
|
+
const prevInstance = (0, react_1.useRef)(void 0);
|
|
156
|
+
const [instance] = (0, react_1.useState)(() => {
|
|
157
|
+
if (!mountTimes.current++) {
|
|
158
|
+
prevInstance.current = setup();
|
|
159
|
+
}
|
|
160
|
+
return prevInstance.current;
|
|
161
|
+
});
|
|
162
|
+
(0, react_1.useEffect)(() => () => {
|
|
163
|
+
!--mountTimes.current && cleanup?.(instance);
|
|
164
|
+
}, []);
|
|
165
|
+
return instance;
|
|
166
|
+
}
|
package/dist/cjs/utils/tree.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Id, Obj } from '../types';
|
|
2
|
+
import { NodeType, SortInfo } from '../components/tree';
|
|
2
3
|
/**
|
|
3
4
|
* ------------------------------------------------------------------------
|
|
4
5
|
* 统一处理树形搜索
|
|
@@ -25,3 +26,11 @@ export declare function useTreeSearch<N extends Obj, V extends Id = Id>({ nodes,
|
|
|
25
26
|
setInnerSearchValue: import("react").Dispatch<import("react").SetStateAction<string>>;
|
|
26
27
|
filteredTreeData: N[] | undefined;
|
|
27
28
|
};
|
|
29
|
+
/**
|
|
30
|
+
* 得到排序后的树结构
|
|
31
|
+
*/
|
|
32
|
+
export declare function sortTreeNodes<N extends NodeType<V>, V extends Id = Id>(props: {
|
|
33
|
+
nodes: N[];
|
|
34
|
+
primaryKey?: keyof N;
|
|
35
|
+
childrenKey?: keyof N;
|
|
36
|
+
}, sortInfo: SortInfo<V>): N[];
|
package/dist/cjs/utils/tree.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useTreeSearch = useTreeSearch;
|
|
4
|
+
exports.sortTreeNodes = sortTreeNodes;
|
|
4
5
|
const react_1 = require("react");
|
|
5
6
|
const hooks_1 = require("./hooks");
|
|
6
7
|
function useTreeSearch({ nodes, primaryKey = 'id', labelKey = 'label', childrenKey = 'children', searchTokenKey = 'searchToken', defaultExpanded = [], expanded, onExpandedChange, defaultSearchValue = '', searchValue, onSearchChange }) {
|
|
@@ -61,3 +62,58 @@ function useTreeSearch({ nodes, primaryKey = 'id', labelKey = 'label', childrenK
|
|
|
61
62
|
filteredTreeData
|
|
62
63
|
};
|
|
63
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* 得到排序后的树结构
|
|
67
|
+
*/
|
|
68
|
+
function sortTreeNodes(props, sortInfo) {
|
|
69
|
+
let { nodes, primaryKey = 'id', childrenKey = 'children' } = props;
|
|
70
|
+
const { source, destination, placement } = sortInfo;
|
|
71
|
+
nodes = structuredClone(nodes);
|
|
72
|
+
const pickUp = (nodes) => {
|
|
73
|
+
if (!nodes?.length) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
for (let i = 0, { length } = nodes; i < length; i++) {
|
|
77
|
+
const node = nodes[i];
|
|
78
|
+
if (node[primaryKey] === source) {
|
|
79
|
+
nodes.splice(i, 1);
|
|
80
|
+
return node;
|
|
81
|
+
}
|
|
82
|
+
const foundInChildren = pickUp(node[childrenKey]);
|
|
83
|
+
if (foundInChildren) {
|
|
84
|
+
return foundInChildren;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
};
|
|
89
|
+
pickUp(nodes);
|
|
90
|
+
const putDown = (nodes) => {
|
|
91
|
+
if (!nodes?.length) {
|
|
92
|
+
return false;
|
|
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
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const foundInChildren = pickUp(node[childrenKey]);
|
|
111
|
+
if (foundInChildren) {
|
|
112
|
+
return foundInChildren;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return false;
|
|
116
|
+
};
|
|
117
|
+
putDown(nodes);
|
|
118
|
+
return nodes;
|
|
119
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
2
|
-
import { createContext, useContext
|
|
3
|
-
import { clsx, defineCss } from '../../utils';
|
|
2
|
+
import { createContext, useContext } from 'react';
|
|
3
|
+
import { clsx, defineCss, useExternalClass } from '../../utils';
|
|
4
4
|
import { classes, style } from './app.style';
|
|
5
5
|
import { ThemeProvider } from '../theme';
|
|
6
6
|
import { AppDialog, AppDialogMethods } from './appDialog';
|
|
@@ -22,12 +22,12 @@ export const App = (({ theme, ...props }) => {
|
|
|
22
22
|
return (_jsx(GlobalEventDelegation, { children: _jsx(ThemeProvider, { theme: theme, children: _jsx(InnerApp, { ...props }) }) }));
|
|
23
23
|
});
|
|
24
24
|
export function InnerApp({ component: Component = 'div', theme, children, fill = true, ...props }) {
|
|
25
|
-
const appValue =
|
|
25
|
+
const appValue = useExternalClass(() => ({
|
|
26
26
|
dialog: App.dialog = new AppDialogMethods(),
|
|
27
27
|
message: App.message = new AppMessageMethods(),
|
|
28
28
|
notification: App.notification = new AppNotificationMethods(),
|
|
29
29
|
actionSheet: App.actionSheet = new AppActionSheetMethods()
|
|
30
|
-
})
|
|
30
|
+
}));
|
|
31
31
|
return (_jsxs(AppContext, { value: appValue, children: [Component
|
|
32
32
|
? _jsx(Component, { ...props, css: [
|
|
33
33
|
style,
|
|
@@ -44,6 +44,6 @@ export const Image = memo(({ src, fallback, onLoad, onError, renderLoading, alt
|
|
|
44
44
|
}, onLoad: loadHandler, onError: errorHandler }), loading.current &&
|
|
45
45
|
(renderLoading ?? _jsx(Skeleton, { className: classes.skeleton })), !!renderedActions && !failed.current &&
|
|
46
46
|
_jsx("div", { className: classes.mask, children: renderedActions }), previewable && src &&
|
|
47
|
-
_jsx(Gallery, { src: [src], ...previewProps, open: previewOpen.current, onOpenChange: setPreviewOpen })] }));
|
|
47
|
+
_jsx(Gallery, { src: [src], ...previewProps, open: previewOpen.current, onOpenChange: setPreviewOpen, onPointerDown: e => e.stopPropagation() })] }));
|
|
48
48
|
});
|
|
49
49
|
Image.Gallery = Gallery;
|
|
@@ -24,4 +24,4 @@ export interface OverlayBaseProps extends DivProps {
|
|
|
24
24
|
removeFocusOnOpen?: boolean;
|
|
25
25
|
}
|
|
26
26
|
export declare const overlayBaseTransitionDuration = 300;
|
|
27
|
-
export declare function OverlayBase({ container, effectContainer, forceRender, open, onMaskClick, singleLayer, onOpened, onClosed, maskProps, removeFocusOnOpen, ...props }: OverlayBaseProps): false | React.ReactPortal;
|
|
27
|
+
export declare function OverlayBase({ container, effectContainer, forceRender, open, onMaskClick, singleLayer, onOpened, onClosed, maskProps, removeFocusOnOpen, ...props }: OverlayBaseProps): false | React.ReactPortal | null;
|
|
@@ -33,7 +33,7 @@ export function OverlayBase({ container, effectContainer, forceRender, open, onM
|
|
|
33
33
|
onClosed?.();
|
|
34
34
|
forceRender === false && setShouldRender(false);
|
|
35
35
|
};
|
|
36
|
-
return shouldRender.current && createPortal(_jsxs("div", { ...props, css: style, className: clsx(classes.root, props.className), "data-open": open, "data-custom-container": containerEl.current !== document.body, children: [_jsx(Fade, { timeout: overlayBaseTransitionDuration, ...mergeComponentProps(maskProps, {
|
|
36
|
+
return shouldRender.current && containerEl.current && createPortal(_jsxs("div", { ...props, css: style, className: clsx(classes.root, props.className), "data-open": open, "data-custom-container": containerEl.current !== document.body, children: [_jsx(Fade, { timeout: overlayBaseTransitionDuration, ...mergeComponentProps(maskProps, {
|
|
37
37
|
in: open,
|
|
38
38
|
className: classes.mask,
|
|
39
39
|
onClick,
|
|
@@ -12,12 +12,12 @@ export const Pinchable = (({ component: Component = 'div', ref, gestureOptions,
|
|
|
12
12
|
zoomFn(innerScale.current * .5);
|
|
13
13
|
};
|
|
14
14
|
wrapperRef.current.zoomTo = zoomFn;
|
|
15
|
-
wrapperRef.current.rotate =
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
wrapperRef.current.rotate = rotateFn;
|
|
16
|
+
wrapperRef.current.rotateLeft = () => {
|
|
17
|
+
rotateFn(innerRotate.current - 90);
|
|
18
|
+
};
|
|
19
19
|
wrapperRef.current.rotateRight = () => {
|
|
20
|
-
rotateFn(innerRotate.current
|
|
20
|
+
rotateFn(innerRotate.current - 90);
|
|
21
21
|
};
|
|
22
22
|
wrapperRef.current.reset = resetAll;
|
|
23
23
|
}
|
|
@@ -131,7 +131,7 @@ export const Pinchable = (({ component: Component = 'div', ref, gestureOptions,
|
|
|
131
131
|
resetZoom(false);
|
|
132
132
|
setInnerRotate(0);
|
|
133
133
|
};
|
|
134
|
-
const
|
|
134
|
+
const onDoubleClick = (e) => {
|
|
135
135
|
childrenProps.onDoubleClick?.(e);
|
|
136
136
|
if (innerScale.current < 1.5) {
|
|
137
137
|
zoomFn(3, e.clientX, e.clientY);
|
|
@@ -140,12 +140,16 @@ export const Pinchable = (({ component: Component = 'div', ref, gestureOptions,
|
|
|
140
140
|
resetZoom();
|
|
141
141
|
}
|
|
142
142
|
};
|
|
143
|
-
const
|
|
143
|
+
const onWheel = (e) => {
|
|
144
144
|
childrenProps.onMouseWheel?.(e);
|
|
145
145
|
e.deltaY > 0
|
|
146
146
|
? zoomFn(innerScale.current * .8, e.clientX, e.clientY)
|
|
147
147
|
: zoomFn(innerScale.current * 1.2, e.clientX, e.clientY);
|
|
148
148
|
};
|
|
149
|
+
const onTransitionEnd = (e) => {
|
|
150
|
+
e.currentTarget.dataset.transition = 'false';
|
|
151
|
+
setInnerRotate(innerRotate.current % 360);
|
|
152
|
+
};
|
|
149
153
|
return (_jsx(Component, { ...props, ref: wrapperRef, css: style, className: clsx(classes.root, props.className), ...pinchableHandles, children: cloneElement(children, {
|
|
150
154
|
ref: cloneRef(contentRef, childrenProps.ref),
|
|
151
155
|
className: clsx(classes.content, childrenProps.className),
|
|
@@ -157,8 +161,8 @@ export const Pinchable = (({ component: Component = 'div', ref, gestureOptions,
|
|
|
157
161
|
transformOrigin: 'center'
|
|
158
162
|
},
|
|
159
163
|
...draggableHandles,
|
|
160
|
-
onDoubleClick
|
|
161
|
-
onWheel
|
|
162
|
-
onTransitionEnd
|
|
164
|
+
onDoubleClick,
|
|
165
|
+
onWheel,
|
|
166
|
+
onTransitionEnd
|
|
163
167
|
}) }));
|
|
164
168
|
});
|
|
@@ -534,7 +534,7 @@ export function Popper({ ref, popperRef, anchorElement, container = document.bod
|
|
|
534
534
|
? cloneElement(children, {
|
|
535
535
|
ref: childRef
|
|
536
536
|
})
|
|
537
|
-
: children, renderedOnce.current && createPortal(_jsx(ClickAway, { disabled: !clickable && !enterable && !contextMenuable,
|
|
537
|
+
: children, renderedOnce.current && containerEl.current && createPortal(_jsx(ClickAway, { disabled: !clickable && !enterable && !contextMenuable,
|
|
538
538
|
// 右键菜单点击anchor需要关闭弹框
|
|
539
539
|
targets: () => contextMenuEvent.current ? void 0 : getAnchorElement(), onClickAway: onClickAway, children: _jsx("div", { ...props, ref: innerPopperRef, css: style, className: clsx(classes.root, props.className), style: {
|
|
540
540
|
...popperBounding,
|
|
@@ -30,7 +30,7 @@ export declare const SnackbarBase: React.MemoExoticComponent<({ methods, useTo,
|
|
|
30
30
|
max?: number;
|
|
31
31
|
container?: DefineElement<HTMLElement>;
|
|
32
32
|
effectContainer?: DefineElement<HTMLElement>;
|
|
33
|
-
}) => React.ReactPortal>;
|
|
33
|
+
}) => React.ReactPortal | null>;
|
|
34
34
|
interface SnackbarBaseItemProps extends Omit<SnackbarBaseProps, 'duration' | 'onAutoClose'> {
|
|
35
35
|
id: string;
|
|
36
36
|
type: keyof SnackbarBaseMethods;
|
|
@@ -82,7 +82,7 @@ export const SnackbarBase = memo(({ methods, useTo, max = useTo === 'message' ?
|
|
|
82
82
|
methods.error = defineMethod('error');
|
|
83
83
|
const css = style();
|
|
84
84
|
const containerEl = useContainer(container, effectContainer);
|
|
85
|
-
return createPortal(stacks.flatMap((stack, i) => stack
|
|
85
|
+
return containerEl.current && createPortal(stacks.flatMap((stack, i) => stack
|
|
86
86
|
? _jsx(TransitionGroup, { css: css, className: classes.root, "data-place": i, "data-use-to": useTo, children: stack.map(p => _createElement(SnackbarBaseItem, { ...p, key: p.id })) }, i)
|
|
87
87
|
: []), containerEl.current);
|
|
88
88
|
});
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useRef } from 'react';
|
|
3
3
|
import { useSortable } from '@dnd-kit/sortable';
|
|
4
4
|
import { CSS } from '@dnd-kit/utilities';
|
|
5
|
-
import { cloneRef, useSync } from '../../utils';
|
|
5
|
+
import { cloneRef, clsx, useSync } from '../../utils';
|
|
6
|
+
import { Global } from '@emotion/react';
|
|
7
|
+
import { globalGrabbingStyle } from '../tree/treeDnd.style';
|
|
8
|
+
import { classes, style } from './sortableItem.style';
|
|
6
9
|
export const SortableItem = (({ component: Component = 'div', id, disabled, sortableArguments, ...props }) => {
|
|
7
10
|
const { attributes, isDragging, listeners, setNodeRef, transform, transition } = useSortable({
|
|
8
11
|
...sortableArguments,
|
|
@@ -27,9 +30,9 @@ export const SortableItem = (({ component: Component = 'div', id, disabled, sort
|
|
|
27
30
|
addEventListener('pointerup', onPointerUp);
|
|
28
31
|
}, []);
|
|
29
32
|
useEffect(() => removeListener, []);
|
|
30
|
-
return (_jsx(Component, { ...attributes, ...listeners, ...props, ref: cloneRef(setNodeRef, props.ref), style: {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
return (_jsxs(_Fragment, { children: [_jsx(Component, { ...attributes, ...listeners, ...props, ref: cloneRef(setNodeRef, props.ref), css: style, className: clsx(classes.root, props.className), style: {
|
|
34
|
+
transform: CSS.Transform.toString(transform),
|
|
35
|
+
transition,
|
|
36
|
+
...props.style
|
|
37
|
+
}, onTouchStart: disabled ? void 0 : onTouchStart, "data-dragging": isDragging }), isDragging && _jsx(Global, { styles: globalGrabbingStyle })] }));
|
|
35
38
|
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { css } from '@emotion/react';
|
|
2
|
+
import { defineInnerClasses } from '../../utils';
|
|
3
|
+
export const classes = defineInnerClasses('sortable-item');
|
|
4
|
+
export const style = css `
|
|
5
|
+
cursor: grab;
|
|
6
|
+
|
|
7
|
+
&:active {
|
|
8
|
+
cursor: grabbing;
|
|
9
|
+
}
|
|
10
|
+
`;
|
|
11
|
+
export const globalGrabbingStyle = css `
|
|
12
|
+
* {
|
|
13
|
+
cursor: grabbing;
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
2
2
|
import { createContext, memo, useContext, useRef, useState } from 'react';
|
|
3
|
-
import { treeDndClasses } from './treeDnd.style';
|
|
3
|
+
import { globalGrabbingStyle, treeDndClasses } from './treeDnd.style';
|
|
4
|
+
import { Global } from '@emotion/react';
|
|
4
5
|
export const TreeDndContext = createContext({});
|
|
5
6
|
export function useTreeDndContext() {
|
|
6
7
|
return useContext(TreeDndContext);
|
|
@@ -9,8 +10,8 @@ export const TreeDnd = memo(({ sortable, showDragHandle, onSort, children }) =>
|
|
|
9
10
|
const dragging = useState(void 0);
|
|
10
11
|
const overing = useRef(void 0);
|
|
11
12
|
const placement = useRef(void 0);
|
|
12
|
-
return (
|
|
13
|
+
return (_jsxs(TreeDndContext, { value: {
|
|
13
14
|
sortable, showDragHandle, onSort,
|
|
14
15
|
dragging, overing, placement
|
|
15
|
-
}, children: _jsx("div", { className: treeDndClasses.levelBlock, children: children }) }));
|
|
16
|
+
}, children: [_jsx("div", { className: treeDndClasses.levelBlock, children: children }), !!dragging[0] && _jsx(Global, { styles: globalGrabbingStyle })] }));
|
|
16
17
|
});
|
|
@@ -61,6 +61,7 @@ export const TreeNode = memo(({ id, label, prefix, suffix, disabled, _level = 0,
|
|
|
61
61
|
const pointerLeavePredecessor = (e) => {
|
|
62
62
|
inactiveBlock(e.currentTarget);
|
|
63
63
|
};
|
|
64
|
+
const overingTimeout = useRef(void 0);
|
|
64
65
|
const activeBlock = (el, _placement, upLevel = 0) => {
|
|
65
66
|
if (_placement === 'parent') {
|
|
66
67
|
let i = upLevel;
|
|
@@ -90,6 +91,13 @@ export const TreeNode = memo(({ id, label, prefix, suffix, disabled, _level = 0,
|
|
|
90
91
|
return true;
|
|
91
92
|
}
|
|
92
93
|
});
|
|
94
|
+
// 如果有children且为折叠状态,over在该节点上一定时间后,需要展开该节点
|
|
95
|
+
if (hasChildren && !currentExpanded) {
|
|
96
|
+
overingTimeout.current ||= setTimeout(() => {
|
|
97
|
+
overingTimeout.current = void 0;
|
|
98
|
+
toggleExpanded(id);
|
|
99
|
+
}, 600);
|
|
100
|
+
}
|
|
93
101
|
};
|
|
94
102
|
const inactiveBlock = (el) => {
|
|
95
103
|
if (el) {
|
|
@@ -102,6 +110,10 @@ export const TreeNode = memo(({ id, label, prefix, suffix, disabled, _level = 0,
|
|
|
102
110
|
el.dataset.active = 'false';
|
|
103
111
|
});
|
|
104
112
|
overing.current = void 0;
|
|
113
|
+
if (overingTimeout.current) {
|
|
114
|
+
clearTimeout(overingTimeout.current);
|
|
115
|
+
overingTimeout.current = void 0;
|
|
116
|
+
}
|
|
105
117
|
};
|
|
106
118
|
/**
|
|
107
119
|
* ---------------------------------------------------------------------
|
|
@@ -55,4 +55,8 @@ export declare function useLoading<A extends any[], R>(fn: (...args: A) => R | P
|
|
|
55
55
|
* @param effectContainer
|
|
56
56
|
* @param defaultContainer 默认为`document.body`
|
|
57
57
|
*/
|
|
58
|
-
export declare function useContainer<T extends HTMLElement | null>(container?: DefineElement<T>, effectContainer?: DefineElement<T>, defaultContainer?: T): RefObject<T>;
|
|
58
|
+
export declare function useContainer<T extends HTMLElement | null>(container?: DefineElement<T>, effectContainer?: DefineElement<T>, defaultContainer?: DefineElement<T>): RefObject<T | null>;
|
|
59
|
+
/**
|
|
60
|
+
* 使用外部类,该方法可避免`StrictMode`下,React渲染行为与外部类实例生命周期不同步的问题
|
|
61
|
+
*/
|
|
62
|
+
export declare function useExternalClass<T>(setup: () => T, cleanup?: (instance: T) => void): T;
|
package/dist/esm/utils/hooks.js
CHANGED
|
@@ -119,18 +119,36 @@ export function useLoading(fn, referredLoading = false) {
|
|
|
119
119
|
* @param effectContainer
|
|
120
120
|
* @param defaultContainer 默认为`document.body`
|
|
121
121
|
*/
|
|
122
|
-
export function useContainer(container, effectContainer, defaultContainer
|
|
122
|
+
export function useContainer(container, effectContainer, defaultContainer) {
|
|
123
123
|
const [containerEl, setContainerEl] = useDerivedState(prev => {
|
|
124
124
|
if (container) {
|
|
125
125
|
return typeof container === 'function' ? container() : container;
|
|
126
126
|
}
|
|
127
|
-
return prev ||
|
|
128
|
-
}, [container
|
|
127
|
+
return prev || null;
|
|
128
|
+
}, [container]);
|
|
129
129
|
useEffect(() => {
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
const _container = effectContainer || defaultContainer || document.body;
|
|
131
|
+
if (_container) {
|
|
132
|
+
const el = typeof _container === 'function' ? _container() : _container;
|
|
132
133
|
setContainerEl(el);
|
|
133
134
|
}
|
|
134
|
-
}, []);
|
|
135
|
+
}, [effectContainer, defaultContainer]);
|
|
135
136
|
return containerEl;
|
|
136
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* 使用外部类,该方法可避免`StrictMode`下,React渲染行为与外部类实例生命周期不同步的问题
|
|
140
|
+
*/
|
|
141
|
+
export function useExternalClass(setup, cleanup) {
|
|
142
|
+
const mountTimes = useRef(0);
|
|
143
|
+
const prevInstance = useRef(void 0);
|
|
144
|
+
const [instance] = useState(() => {
|
|
145
|
+
if (!mountTimes.current++) {
|
|
146
|
+
prevInstance.current = setup();
|
|
147
|
+
}
|
|
148
|
+
return prevInstance.current;
|
|
149
|
+
});
|
|
150
|
+
useEffect(() => () => {
|
|
151
|
+
!--mountTimes.current && cleanup?.(instance);
|
|
152
|
+
}, []);
|
|
153
|
+
return instance;
|
|
154
|
+
}
|
package/dist/esm/utils/tree.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Id, Obj } from '../types';
|
|
2
|
+
import { NodeType, SortInfo } from '../components/tree';
|
|
2
3
|
/**
|
|
3
4
|
* ------------------------------------------------------------------------
|
|
4
5
|
* 统一处理树形搜索
|
|
@@ -25,3 +26,11 @@ export declare function useTreeSearch<N extends Obj, V extends Id = Id>({ nodes,
|
|
|
25
26
|
setInnerSearchValue: import("react").Dispatch<import("react").SetStateAction<string>>;
|
|
26
27
|
filteredTreeData: N[] | undefined;
|
|
27
28
|
};
|
|
29
|
+
/**
|
|
30
|
+
* 得到排序后的树结构
|
|
31
|
+
*/
|
|
32
|
+
export declare function sortTreeNodes<N extends NodeType<V>, V extends Id = Id>(props: {
|
|
33
|
+
nodes: N[];
|
|
34
|
+
primaryKey?: keyof N;
|
|
35
|
+
childrenKey?: keyof N;
|
|
36
|
+
}, sortInfo: SortInfo<V>): N[];
|
package/dist/esm/utils/tree.js
CHANGED
|
@@ -58,3 +58,58 @@ export function useTreeSearch({ nodes, primaryKey = 'id', labelKey = 'label', ch
|
|
|
58
58
|
filteredTreeData
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* 得到排序后的树结构
|
|
63
|
+
*/
|
|
64
|
+
export function sortTreeNodes(props, sortInfo) {
|
|
65
|
+
let { nodes, primaryKey = 'id', childrenKey = 'children' } = props;
|
|
66
|
+
const { source, destination, placement } = sortInfo;
|
|
67
|
+
nodes = structuredClone(nodes);
|
|
68
|
+
const pickUp = (nodes) => {
|
|
69
|
+
if (!nodes?.length) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
for (let i = 0, { length } = nodes; i < length; i++) {
|
|
73
|
+
const node = nodes[i];
|
|
74
|
+
if (node[primaryKey] === source) {
|
|
75
|
+
nodes.splice(i, 1);
|
|
76
|
+
return node;
|
|
77
|
+
}
|
|
78
|
+
const foundInChildren = pickUp(node[childrenKey]);
|
|
79
|
+
if (foundInChildren) {
|
|
80
|
+
return foundInChildren;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
};
|
|
85
|
+
pickUp(nodes);
|
|
86
|
+
const putDown = (nodes) => {
|
|
87
|
+
if (!nodes?.length) {
|
|
88
|
+
return false;
|
|
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
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const foundInChildren = pickUp(node[childrenKey]);
|
|
107
|
+
if (foundInChildren) {
|
|
108
|
+
return foundInChildren;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return false;
|
|
112
|
+
};
|
|
113
|
+
putDown(nodes);
|
|
114
|
+
return nodes;
|
|
115
|
+
}
|