@canlooks/can-ui 0.0.66 → 0.0.68
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 +26 -20
- package/dist/cjs/components/button/button.js +1 -1
- package/dist/cjs/components/cascade/cascade.js +2 -2
- package/dist/cjs/components/curd/curdColumnConfig.js +2 -1
- package/dist/cjs/components/dataGrid/dataGrid.js +3 -2
- package/dist/cjs/components/gallery/gallery.js +2 -2
- package/dist/cjs/components/menu/menu.js +2 -2
- package/dist/cjs/components/overlayBase/overlayBase.d.ts +3 -1
- package/dist/cjs/components/overlayBase/overlayBase.js +5 -5
- package/dist/cjs/components/popper/popper.d.ts +3 -1
- package/dist/cjs/components/popper/popper.js +6 -7
- package/dist/cjs/components/progress/progress.js +4 -2
- package/dist/cjs/components/snackbarBase/snackbarBase.d.ts +3 -2
- package/dist/cjs/components/snackbarBase/snackbarBase.js +3 -3
- package/dist/cjs/components/theme/themeVariables.d.ts +1 -0
- package/dist/cjs/components/theme/themeVariables.js +1 -0
- package/dist/cjs/components/touchRipple/index.d.ts +1 -0
- package/dist/cjs/components/touchRipple/index.js +1 -0
- package/dist/cjs/components/touchRipple/touchRipple.d.ts +6 -14
- package/dist/cjs/components/touchRipple/touchRipple.js +54 -39
- package/dist/cjs/components/touchRipple/touchRipple.style.js +25 -27
- package/dist/cjs/components/transfer/transfer.js +2 -2
- package/dist/cjs/components/transfer/transferPanel.js +2 -1
- package/dist/cjs/components/upload/upload.js +2 -2
- package/dist/cjs/components/waterfall/waterfallItem.js +1 -1
- package/dist/cjs/utils/hooks.d.ts +8 -0
- package/dist/cjs/utils/hooks.js +22 -0
- package/dist/esm/components/anchorList/anchorList.js +26 -20
- package/dist/esm/components/button/button.js +1 -1
- package/dist/esm/components/cascade/cascade.js +2 -2
- package/dist/esm/components/curd/curdColumnConfig.js +2 -1
- package/dist/esm/components/dataGrid/dataGrid.js +3 -2
- package/dist/esm/components/gallery/gallery.js +2 -2
- package/dist/esm/components/menu/menu.js +2 -2
- package/dist/esm/components/overlayBase/overlayBase.d.ts +3 -1
- package/dist/esm/components/overlayBase/overlayBase.js +6 -6
- package/dist/esm/components/popper/popper.d.ts +3 -1
- package/dist/esm/components/popper/popper.js +7 -8
- package/dist/esm/components/progress/progress.js +4 -2
- package/dist/esm/components/snackbarBase/snackbarBase.d.ts +3 -2
- package/dist/esm/components/snackbarBase/snackbarBase.js +4 -4
- package/dist/esm/components/theme/themeVariables.d.ts +1 -0
- package/dist/esm/components/theme/themeVariables.js +1 -0
- package/dist/esm/components/touchRipple/index.d.ts +1 -0
- package/dist/esm/components/touchRipple/index.js +1 -0
- package/dist/esm/components/touchRipple/touchRipple.d.ts +6 -14
- package/dist/esm/components/touchRipple/touchRipple.js +54 -39
- package/dist/esm/components/touchRipple/touchRipple.style.js +25 -27
- package/dist/esm/components/transfer/transfer.js +2 -2
- package/dist/esm/components/transfer/transferPanel.js +2 -1
- package/dist/esm/components/upload/upload.js +2 -2
- package/dist/esm/components/waterfall/waterfallItem.js +2 -2
- package/dist/esm/utils/hooks.d.ts +8 -0
- package/dist/esm/utils/hooks.js +21 -0
- package/package.json +1 -1
|
@@ -24,7 +24,7 @@ const markFileId = (files) => {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
|
-
exports.Upload = (0, react_1.memo)(({ inputProps, type = 'file', accept = type === 'image' ? 'image/*' : void 0, max = Infinity, showButton = true, buttonProps, buttonText = '选择文件', variant = 'square', sortable, droppable, defaultValue
|
|
27
|
+
exports.Upload = (0, react_1.memo)(({ inputProps, type = 'file', accept = type === 'image' ? 'image/*' : void 0, max = Infinity, showButton = true, buttonProps, buttonText = '选择文件', variant = 'square', sortable, droppable, defaultValue, value, onChange, onUpload, ...props }) => {
|
|
28
28
|
const wrapperRef = (0, react_1.useRef)(null);
|
|
29
29
|
const itemRefs = (0, react_1.useRef)(new Map());
|
|
30
30
|
(0, react_1.useImperativeHandle)(props.ref, () => {
|
|
@@ -54,7 +54,7 @@ exports.Upload = (0, react_1.memo)(({ inputProps, type = 'file', accept = type =
|
|
|
54
54
|
};
|
|
55
55
|
return wrapperRef.current;
|
|
56
56
|
});
|
|
57
|
-
const [innerValue, setInnerValue] = (0, utils_1.useControlled)(defaultValue, value, value => {
|
|
57
|
+
const [innerValue, setInnerValue] = (0, utils_1.useControlled)(defaultValue || [], value, value => {
|
|
58
58
|
markFileId(value);
|
|
59
59
|
onChange?.(value);
|
|
60
60
|
});
|
|
@@ -6,7 +6,7 @@ const waterfall_style_1 = require("./waterfall.style");
|
|
|
6
6
|
const utils_1 = require("../../utils");
|
|
7
7
|
const WaterfallItem = ({ ref, onLoad, child }) => {
|
|
8
8
|
const innerRef = (0, react_1.useRef)(null);
|
|
9
|
-
(0, react_1.
|
|
9
|
+
(0, react_1.useEffect)(() => {
|
|
10
10
|
const el = innerRef.current;
|
|
11
11
|
if (!el) {
|
|
12
12
|
throw Error(`Children of <Waterfall> must expose 'ref' prop`);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RefObject, Dispatch, SetStateAction } from 'react';
|
|
2
|
+
import { DefineElement } from '../types';
|
|
2
3
|
/**
|
|
3
4
|
* 获取渲染前的值
|
|
4
5
|
* @param value
|
|
@@ -48,3 +49,10 @@ export declare function useLoading<A extends any[], R>(fn: (...args: A) => R | P
|
|
|
48
49
|
(...args: A) => Promise<R>,
|
|
49
50
|
Dispatch<SetStateAction<boolean>>
|
|
50
51
|
];
|
|
52
|
+
/**
|
|
53
|
+
* 获取容器元素,通常用于`container`或`effectContainer`属性
|
|
54
|
+
* @param container
|
|
55
|
+
* @param effectContainer
|
|
56
|
+
* @param defaultContainer 默认为`document.body`
|
|
57
|
+
*/
|
|
58
|
+
export declare function useContainer<T extends HTMLElement | null>(container?: DefineElement<T>, effectContainer?: DefineElement<T>, defaultContainer?: T): RefObject<T>;
|
package/dist/cjs/utils/hooks.js
CHANGED
|
@@ -8,6 +8,7 @@ exports.useDerivedState = useDerivedState;
|
|
|
8
8
|
exports.useUnmounted = useUnmounted;
|
|
9
9
|
exports.useControlled = useControlled;
|
|
10
10
|
exports.useLoading = useLoading;
|
|
11
|
+
exports.useContainer = useContainer;
|
|
11
12
|
const react_1 = require("react");
|
|
12
13
|
const utils_1 = require("./utils");
|
|
13
14
|
/**
|
|
@@ -123,3 +124,24 @@ function useLoading(fn, referredLoading = false) {
|
|
|
123
124
|
setLoading
|
|
124
125
|
];
|
|
125
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* 获取容器元素,通常用于`container`或`effectContainer`属性
|
|
129
|
+
* @param container
|
|
130
|
+
* @param effectContainer
|
|
131
|
+
* @param defaultContainer 默认为`document.body`
|
|
132
|
+
*/
|
|
133
|
+
function useContainer(container, effectContainer, defaultContainer = document.body) {
|
|
134
|
+
const [containerEl, setContainerEl] = useDerivedState(prev => {
|
|
135
|
+
if (container) {
|
|
136
|
+
return typeof container === 'function' ? container() : container;
|
|
137
|
+
}
|
|
138
|
+
return prev || defaultContainer;
|
|
139
|
+
}, [container, defaultContainer]);
|
|
140
|
+
(0, react_1.useEffect)(() => {
|
|
141
|
+
if (effectContainer) {
|
|
142
|
+
const el = typeof effectContainer === 'function' ? effectContainer() : effectContainer;
|
|
143
|
+
setContainerEl(el);
|
|
144
|
+
}
|
|
145
|
+
}, []);
|
|
146
|
+
return containerEl;
|
|
147
|
+
}
|
|
@@ -18,10 +18,11 @@ export const AnchorList = memo(({ anchors, renderAnchorItem, indent = 24, scroll
|
|
|
18
18
|
});
|
|
19
19
|
const scrollToId = (id) => {
|
|
20
20
|
const targetEl = document.getElementById(id);
|
|
21
|
-
|
|
21
|
+
const scrollerEl = getScroller();
|
|
22
|
+
if (!targetEl || !scrollerEl) {
|
|
22
23
|
return false;
|
|
23
24
|
}
|
|
24
|
-
|
|
25
|
+
scrollerEl.scrollTo({
|
|
25
26
|
top: targetEl.offsetTop - offset,
|
|
26
27
|
// 初始化之前无需平滑滚动
|
|
27
28
|
behavior: initialized.current ? scrollBehavior : 'instant'
|
|
@@ -50,29 +51,34 @@ export const AnchorList = memo(({ anchors, renderAnchorItem, indent = 24, scroll
|
|
|
50
51
|
* 监听滚动设置高亮
|
|
51
52
|
*/
|
|
52
53
|
const getScroller = () => {
|
|
53
|
-
|
|
54
|
+
if (scroller) {
|
|
55
|
+
return typeof scroller === 'function' ? scroller() : scroller;
|
|
56
|
+
}
|
|
57
|
+
return document.documentElement;
|
|
54
58
|
};
|
|
55
59
|
const [activeId, setActiveId] = useSyncState();
|
|
56
60
|
useEffect(() => {
|
|
57
61
|
const scrollerEl = getScroller();
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
minDistance
|
|
68
|
-
|
|
62
|
+
if (scrollerEl) {
|
|
63
|
+
const scroll = () => {
|
|
64
|
+
let nearest;
|
|
65
|
+
let minDistance = Infinity;
|
|
66
|
+
const targets = anchors?.map(item => document.getElementById(item.id));
|
|
67
|
+
targets?.forEach(target => {
|
|
68
|
+
const top = target?.getBoundingClientRect().top;
|
|
69
|
+
if (typeof top === 'number') {
|
|
70
|
+
const distance = Math.abs(top - offset);
|
|
71
|
+
if (distance < minDistance) {
|
|
72
|
+
minDistance = distance;
|
|
73
|
+
nearest = target;
|
|
74
|
+
}
|
|
69
75
|
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
});
|
|
77
|
+
nearest && setActiveId(nearest.id);
|
|
78
|
+
};
|
|
79
|
+
!activeId.current && scroll();
|
|
80
|
+
return listenAllPredecessorsScroll(scrollerEl === document.documentElement ? document : scrollerEl, scroll);
|
|
81
|
+
}
|
|
76
82
|
}, [anchors, scroller, offset]);
|
|
77
83
|
const [animating, setAnimating] = useDerivedState(prev => typeof prev !== 'undefined', [activeId.current]);
|
|
78
84
|
return (_jsxs(Flex, { direction: "column", alignItems: "flex-start", ...props, css: style, className: clsx(classes.root, props.className), "data-animating": animating.current, children: [anchors?.map(item => {
|
|
@@ -28,7 +28,7 @@ export const Button = ({ component: Component = 'button', color = 'primary', sha
|
|
|
28
28
|
? actualPrefix
|
|
29
29
|
? _jsx(LoadingIndicator, { color: reverseTextColor })
|
|
30
30
|
: _jsx(Collapse, { orientation: "horizontal", in: true, children: _jsx(LoadingIndicator, { color: reverseTextColor }) })
|
|
31
|
-
:
|
|
31
|
+
: actualPrefix, !!actualChildren &&
|
|
32
32
|
_jsx("div", { className: classes.content, children: actualChildren }), !!suffix &&
|
|
33
33
|
_jsx("div", { className: classes.suffix, children: suffix })] }));
|
|
34
34
|
};
|
|
@@ -16,7 +16,7 @@ const CascadeContext = createContext({});
|
|
|
16
16
|
export function useCascadeContext() {
|
|
17
17
|
return useContext(CascadeContext);
|
|
18
18
|
}
|
|
19
|
-
export const Cascade = memo(({ inputProps, defaultOpen = false, open, onOpenChange, children, loadOptions, multiple = false, showCheckbox = !!multiple, defaultValue
|
|
19
|
+
export const Cascade = memo(({ inputProps, defaultOpen = false, open, onOpenChange, children, loadOptions, multiple = false, showCheckbox = !!multiple, defaultValue, value, onChange, renderBackfill, searchable, defaultSearchValue = '', searchValue, onSearchChange, searchInputProps, popperProps, popperRef, clearable = !!multiple, integration = 'deepest',
|
|
20
20
|
// 共享属性,从OptionsBaseSharedProps继承
|
|
21
21
|
loading, options, labelKey = 'label', primaryKey = 'value', childrenKey = 'children', searchTokenKey = 'searchToken', ...props }) => {
|
|
22
22
|
/**
|
|
@@ -75,7 +75,7 @@ loading, options, labelKey = 'label', primaryKey = 'value', childrenKey = 'child
|
|
|
75
75
|
* --------------------------------------------------------------------
|
|
76
76
|
* 控制选中状态
|
|
77
77
|
*/
|
|
78
|
-
const [pathifiedValue, setPathifiedValue] = useControlled(defaultValue, value, onChange);
|
|
78
|
+
const [pathifiedValue, setPathifiedValue] = useControlled(defaultValue || [], value, onChange);
|
|
79
79
|
// 路径转单一键
|
|
80
80
|
const toStandardValue = (path) => {
|
|
81
81
|
if (!path) {
|
|
@@ -11,7 +11,8 @@ import { SortableContext } from '@dnd-kit/sortable';
|
|
|
11
11
|
import { isUnset, onDndDragEnd, useDndSensors } from '../../utils';
|
|
12
12
|
import { Icon } from '../..';
|
|
13
13
|
import { faGear } from '@fortawesome/free-solid-svg-icons/faGear';
|
|
14
|
-
export const CurdColumnConfig = memo(({ columns
|
|
14
|
+
export const CurdColumnConfig = memo(({ columns, innerVisible, setInnerVisible, setInnerOrder, }) => {
|
|
15
|
+
columns ||= [];
|
|
15
16
|
const dragEndHandler = (e) => {
|
|
16
17
|
const newColumns = onDndDragEnd(e, columns, '_key');
|
|
17
18
|
newColumns && setInnerOrder(newColumns.flatMap(col => col._key ?? []));
|
|
@@ -14,7 +14,7 @@ const DataGridContext = createContext({});
|
|
|
14
14
|
export function useDataGridContext() {
|
|
15
15
|
return useContext(DataGridContext);
|
|
16
16
|
}
|
|
17
|
-
export const DataGrid = memo(({ columns, rows, rowProps, primaryKey = 'id', childrenKey = null, defaultOrderColumn, orderColumn, defaultOrderType = 'descend', orderType, onOrderChange, selectable, relation = 'dependent', integration = 'shallowest', allowSelectAll = true, clickRowToSelect = true, selectorProps, indent = 24, renderExpandIcon, defaultExpanded
|
|
17
|
+
export const DataGrid = memo(({ columns, rows, rowProps, primaryKey = 'id', childrenKey = null, defaultOrderColumn, orderColumn, defaultOrderType = 'descend', orderType, onOrderChange, selectable, relation = 'dependent', integration = 'shallowest', allowSelectAll = true, clickRowToSelect = true, selectorProps, indent = 24, renderExpandIcon, defaultExpanded, expanded, onExpandedChange, paginatable = true, paginationProps, renderPagination, loading, emptyPlaceholder, columnResizable = false, size, bordered, striped, tableProps, multiple, defaultValue, value, onChange, ...props }) => {
|
|
18
18
|
/**
|
|
19
19
|
* ---------------------------------------------------------------
|
|
20
20
|
* 选择行
|
|
@@ -61,7 +61,7 @@ export const DataGrid = memo(({ columns, rows, rowProps, primaryKey = 'id', chil
|
|
|
61
61
|
* ---------------------------------------------------------------
|
|
62
62
|
* 展开行
|
|
63
63
|
*/
|
|
64
|
-
const [innerExpanded, setInnerExpanded] = useControlled(defaultExpanded, expanded);
|
|
64
|
+
const [innerExpanded, setInnerExpanded] = useControlled(defaultExpanded || [], expanded);
|
|
65
65
|
const expandedSet = useMemo(() => {
|
|
66
66
|
return new Set(innerExpanded.current);
|
|
67
67
|
}, [innerExpanded.current]);
|
|
@@ -79,6 +79,7 @@ export const DataGrid = memo(({ columns, rows, rowProps, primaryKey = 'id', chil
|
|
|
79
79
|
* ---------------------------------------------------------------
|
|
80
80
|
* 分页
|
|
81
81
|
*/
|
|
82
|
+
paginationProps ||= {};
|
|
82
83
|
const [innerPage, setInnerPage] = useControlled(paginationProps.defaultPage ?? 1, paginationProps.page, paginationProps.onPageChange);
|
|
83
84
|
const [innerPageSize, setInnerPageSize] = useControlled(paginationProps.defaultPageSize ?? 10, paginationProps.pageSize, paginationProps.onPageSizeChange);
|
|
84
85
|
const pageChangeHandler = (page, pageSize) => {
|
|
@@ -22,8 +22,8 @@ const commonControlProps = {
|
|
|
22
22
|
color: 'text'
|
|
23
23
|
};
|
|
24
24
|
const bounceBezier = cubicBezier(0, 0, 0, 1);
|
|
25
|
-
export const Gallery = memo(({ src
|
|
26
|
-
const srcArr = useSync(toArray(src));
|
|
25
|
+
export const Gallery = memo(({ src, defaultIndex = 0, index, onIndexChange, defaultOpen = false, open, onOpenChange, showRotation = true, showZoom = true, showClose = true, renderControl, bounceElementTranslate = 24, bounceDragDistance = 240, effectiveSpeed = 450, ...props }) => {
|
|
26
|
+
const srcArr = useSync(toArray(src || []));
|
|
27
27
|
const [innerOpen, setInnerOpen] = useControlled(defaultOpen, open, onOpenChange);
|
|
28
28
|
const close = () => {
|
|
29
29
|
setInnerOpen(false);
|
|
@@ -12,10 +12,10 @@ export function useMenuContext() {
|
|
|
12
12
|
const { size = theme.size, ellipsis = true, indent = theme.spacing[8], ...context } = useContext(MenuContext);
|
|
13
13
|
return { size, ellipsis, indent, ...context };
|
|
14
14
|
}
|
|
15
|
-
export const Menu = memo(({ items, primaryKey = 'value', labelKey = 'label', childrenKey = 'children', defaultExpanded
|
|
15
|
+
export const Menu = memo(({ items, primaryKey = 'value', labelKey = 'label', childrenKey = 'children', defaultExpanded, expanded, onExpandedChange, multiple, defaultValue, value, onChange,
|
|
16
16
|
// 以下属性传递给<MenuItem/>
|
|
17
17
|
size = 'large', showCheckbox, ellipsis, indent, ...props }) => {
|
|
18
|
-
const [innerExpanded, setInnerExpanded] = useControlled(defaultExpanded, expanded);
|
|
18
|
+
const [innerExpanded, setInnerExpanded] = useControlled(defaultExpanded || [], expanded);
|
|
19
19
|
const expandedSet = useMemo(() => {
|
|
20
20
|
return new Set(innerExpanded.current);
|
|
21
21
|
}, [innerExpanded.current]);
|
|
@@ -4,6 +4,8 @@ import { TransitionBaseProps } from '../transitionBase';
|
|
|
4
4
|
export interface OverlayBaseProps extends DivProps {
|
|
5
5
|
/** 模态的容器元素,默认为document.body */
|
|
6
6
|
container?: DefineElement<HTMLElement>;
|
|
7
|
+
/** 同{@link container},但会在useEffect后取值,且只会执行一次 */
|
|
8
|
+
effectContainer?: DefineElement<HTMLElement>;
|
|
7
9
|
/**
|
|
8
10
|
* @enum {true} 跟随父组件强制渲染
|
|
9
11
|
* @enum {false} 打开时渲染,关闭后销毁
|
|
@@ -22,4 +24,4 @@ export interface OverlayBaseProps extends DivProps {
|
|
|
22
24
|
removeFocusOnOpen?: boolean;
|
|
23
25
|
}
|
|
24
26
|
export declare const overlayBaseTransitionDuration = 300;
|
|
25
|
-
export declare function OverlayBase({ container, 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;
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
2
2
|
import { useEffect } from 'react';
|
|
3
3
|
import { classes, style } from './overlayBase.style';
|
|
4
|
-
import { clsx, useDerivedState } from '../../utils';
|
|
4
|
+
import { clsx, useContainer, useDerivedState } from '../../utils';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
6
6
|
import { Fade } from '../transitionBase';
|
|
7
7
|
export const overlayBaseTransitionDuration = 300;
|
|
8
|
-
export function OverlayBase({ container, forceRender, open, onMaskClick, singleLayer, onOpened, onClosed, maskProps, removeFocusOnOpen = true, ...props }) {
|
|
8
|
+
export function OverlayBase({ container, effectContainer, forceRender, open, onMaskClick, singleLayer, onOpened, onClosed, maskProps, removeFocusOnOpen = true, ...props }) {
|
|
9
9
|
const [shouldRender, setShouldRender] = useDerivedState((prev = false) => {
|
|
10
10
|
if (open) {
|
|
11
11
|
return true;
|
|
12
12
|
}
|
|
13
13
|
return forceRender === true || prev;
|
|
14
14
|
}, [open, forceRender]);
|
|
15
|
-
const containerEl = (
|
|
15
|
+
const containerEl = useContainer(container, effectContainer);
|
|
16
16
|
useEffect(() => {
|
|
17
17
|
if (!open) {
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
20
|
removeFocusOnOpen && document.activeElement?.blur?.();
|
|
21
|
-
containerEl.style.overflow = 'hidden';
|
|
21
|
+
containerEl.current.style.overflow = 'hidden';
|
|
22
22
|
return () => {
|
|
23
|
-
containerEl.style.overflow = '';
|
|
23
|
+
containerEl.current.style.overflow = '';
|
|
24
24
|
};
|
|
25
25
|
}, [open]);
|
|
26
26
|
const clickHandler = (e) => {
|
|
@@ -36,5 +36,5 @@ export function OverlayBase({ container, forceRender, open, onMaskClick, singleL
|
|
|
36
36
|
onClosed?.();
|
|
37
37
|
forceRender === false && setShouldRender(false);
|
|
38
38
|
};
|
|
39
|
-
return shouldRender.current && createPortal(_jsxs("div", { ...props, css: style, className: clsx(classes.root, props.className), "data-open": open, "data-custom-container": containerEl !== document.body, children: [_jsx(Fade, { timeout: overlayBaseTransitionDuration, ...maskProps, in: open, className: clsx(classes.mask, maskProps?.className), onClick: clickHandler, onEntered: onEntered, onExited: onExited }), props.children] }), containerEl);
|
|
39
|
+
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, ...maskProps, in: open, className: clsx(classes.mask, maskProps?.className), onClick: clickHandler, onEntered: onEntered, onExited: onExited }), props.children] }), containerEl.current);
|
|
40
40
|
}
|
|
@@ -7,6 +7,8 @@ export interface PopperProps extends Omit<DivProps, 'content' | 'children'> {
|
|
|
7
7
|
anchorElement?: DefineElement<HTMLElement>;
|
|
8
8
|
/** 弹框渲染的容器元素,默认为{@link document.body} */
|
|
9
9
|
container?: DefineElement<HTMLElement>;
|
|
10
|
+
/** 同{@link container},但会在useEffect后取值,且只会执行一次 */
|
|
11
|
+
effectContainer?: DefineElement<HTMLElement>;
|
|
10
12
|
/** 汽泡里的内容 */
|
|
11
13
|
content?: ReactNode;
|
|
12
14
|
/** 弹框偏离元素的距离 */
|
|
@@ -46,4 +48,4 @@ export interface PopperRef extends HTMLDivElement {
|
|
|
46
48
|
openAnimation?: boolean;
|
|
47
49
|
}, beforeOpen?: () => void): void;
|
|
48
50
|
}
|
|
49
|
-
export declare function Popper({ ref, popperRef, anchorElement, container, content, offset, trigger, placement, variant, sizeAdaptable, mouseEnterDelay, mouseLeaveDelay, defaultOpen, open, onOpenChange, onOpenChangeEnd, disabled, autoClose, forceRender, children, ...props }: PopperProps): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
51
|
+
export declare function Popper({ ref, popperRef, anchorElement, container, effectContainer, content, offset, trigger, placement, variant, sizeAdaptable, mouseEnterDelay, mouseLeaveDelay, defaultOpen, open, onOpenChange, onOpenChangeEnd, disabled, autoClose, forceRender, children, ...props }: PopperProps): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
@@ -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, isElementVisibleCompletely, listenAllPredecessorsScroll, toArray, useControlled, useDerivedState, useForceUpdate, useSync, useSyncState, useUnmounted } from '../../utils';
|
|
4
|
+
import { clsx, cloneRef, isElementVisibleCompletely, listenAllPredecessorsScroll, toArray, useControlled, useDerivedState, useForceUpdate, useSync, useSyncState, useUnmounted, useContainer } from '../../utils';
|
|
5
5
|
import { ClickAway } from '../clickAway';
|
|
6
6
|
import { classes, style } from './popper.style';
|
|
7
7
|
import { PopperContext, usePopperContext } from './popperContext';
|
|
@@ -19,7 +19,7 @@ const getAttemptOrder = (placement) => {
|
|
|
19
19
|
}
|
|
20
20
|
return order;
|
|
21
21
|
};
|
|
22
|
-
export function Popper({ ref, popperRef, anchorElement, container = document.body, content, offset, trigger = 'hover', placement = 'top', variant = 'zoom', sizeAdaptable = variant === 'collapse', mouseEnterDelay = 100, mouseLeaveDelay = 150, defaultOpen = false, open, onOpenChange, onOpenChangeEnd, disabled, autoClose = false, forceRender, children, ...props }) {
|
|
22
|
+
export function Popper({ ref, popperRef, anchorElement, container = document.body, effectContainer, content, offset, trigger = 'hover', placement = 'top', variant = 'zoom', sizeAdaptable = variant === 'collapse', mouseEnterDelay = 100, mouseLeaveDelay = 150, defaultOpen = false, open, onOpenChange, onOpenChangeEnd, disabled, autoClose = false, forceRender, children, ...props }) {
|
|
23
23
|
const { spacing } = useTheme();
|
|
24
24
|
offset ??= spacing[2];
|
|
25
25
|
useImperativeHandle(popperRef, () => {
|
|
@@ -35,7 +35,6 @@ export function Popper({ ref, popperRef, anchorElement, container = document.bod
|
|
|
35
35
|
const unmounted = useUnmounted();
|
|
36
36
|
const openHolding = useRef(0);
|
|
37
37
|
const hold = (open) => {
|
|
38
|
-
console.log('hold', open);
|
|
39
38
|
return open ? ++openHolding.current
|
|
40
39
|
: openHolding.current > 0 ? --openHolding.current
|
|
41
40
|
: openHolding.current;
|
|
@@ -102,14 +101,14 @@ export function Popper({ ref, popperRef, anchorElement, container = document.bod
|
|
|
102
101
|
const getAnchorElement = () => {
|
|
103
102
|
return anchorRef.current || (typeof syncAnchorElement.current === 'function' ? syncAnchorElement.current() : syncAnchorElement.current);
|
|
104
103
|
};
|
|
105
|
-
const
|
|
104
|
+
const containerEl = useContainer(container, effectContainer);
|
|
106
105
|
const innerPopperRef = useRef(null);
|
|
107
106
|
const [popperBounding, setPopperBounding] = useState();
|
|
108
107
|
const [openNextFrame, setOpenNextFrame] = useDerivedState(!innerOpen.current, [innerOpen.current, contextMenuEvent.current]);
|
|
109
108
|
const placeA = useRef(void 0);
|
|
110
109
|
const placeB = useRef(void 0);
|
|
111
110
|
const fitPosition = (options, beforeOpen) => {
|
|
112
|
-
const containerRect =
|
|
111
|
+
const containerRect = containerEl.current.getBoundingClientRect();
|
|
113
112
|
const popperEl = innerPopperRef.current;
|
|
114
113
|
let { offsetWidth: popperWidth, offsetHeight: popperHeight } = popperEl;
|
|
115
114
|
let pA, pB;
|
|
@@ -185,7 +184,7 @@ export function Popper({ ref, popperRef, anchorElement, container = document.bod
|
|
|
185
184
|
}
|
|
186
185
|
popperEl.style.left = left + 'px';
|
|
187
186
|
popperEl.style.top = top + 'px';
|
|
188
|
-
return isElementVisibleCompletely(popperEl,
|
|
187
|
+
return isElementVisibleCompletely(popperEl, containerEl.current === document.body ? void 0 : containerEl.current);
|
|
189
188
|
};
|
|
190
189
|
}
|
|
191
190
|
else {
|
|
@@ -256,7 +255,7 @@ export function Popper({ ref, popperRef, anchorElement, container = document.bod
|
|
|
256
255
|
}
|
|
257
256
|
popperEl.style.left = left + 'px';
|
|
258
257
|
popperEl.style.top = top + 'px';
|
|
259
|
-
return isElementVisibleCompletely(popperEl,
|
|
258
|
+
return isElementVisibleCompletely(popperEl, containerEl.current === document.body ? void 0 : containerEl.current);
|
|
260
259
|
};
|
|
261
260
|
}
|
|
262
261
|
if (options?.forcePlacement) {
|
|
@@ -500,5 +499,5 @@ export function Popper({ ref, popperRef, anchorElement, container = document.bod
|
|
|
500
499
|
transform: 'scale(1)'
|
|
501
500
|
},
|
|
502
501
|
...props.style
|
|
503
|
-
}, "data-open": innerOpen.current, "data-variant": variant, "data-place-a": placeA.current, "data-place-b": placeB.current, onTransitionEnd: onTransitionEnd, children: _jsx(PopperContext, { value: contextValue, children: content }) }) }),
|
|
502
|
+
}, "data-open": innerOpen.current, "data-variant": variant, "data-place-a": placeA.current, "data-place-b": placeB.current, onTransitionEnd: onTransitionEnd, children: _jsx(PopperContext, { value: contextValue, children: content }) }) }), containerEl.current)] }));
|
|
504
503
|
}
|
|
@@ -7,7 +7,9 @@ import { css, keyframes } from '@emotion/react';
|
|
|
7
7
|
import { Icon } from '../..';
|
|
8
8
|
import { faCircleCheck } from '@fortawesome/free-solid-svg-icons/faCircleCheck';
|
|
9
9
|
import { faCircleXmark } from '@fortawesome/free-solid-svg-icons/faCircleXmark';
|
|
10
|
-
export const Progress = memo(({ showInfo = true, renderInfo, color
|
|
10
|
+
export const Progress = memo(({ showInfo = true, renderInfo, color, status = 'default', variant = 'linear', gapDegree = 90, size = 60, indeterminate = false, barWidth = 4, strokeLinecap = variant === 'gauge' ? 'butt' : 'round', value = 0, ...props }) => {
|
|
11
|
+
const isColorSpecified = !!color;
|
|
12
|
+
color ??= 'primary';
|
|
11
13
|
const { colors: { success, error } } = useTheme();
|
|
12
14
|
const isSucceed = status === 'success' || (status !== 'error' && value === 100 && variant !== 'gauge');
|
|
13
15
|
const renderInfoFn = () => {
|
|
@@ -52,7 +54,7 @@ export const Progress = memo(({ showInfo = true, renderInfo, color = 'primary',
|
|
|
52
54
|
}
|
|
53
55
|
return;
|
|
54
56
|
}, [indeterminate, variant, strokeLinecap, size, barWidth]);
|
|
55
|
-
return (_jsx("div", { ...props, css: useStyle({ color: color || 'primary', variant }), className: clsx(classes.root, props.className), "data-variant": variant, "data-indeterminate": indeterminate, "data-processing": value < 100 && status === 'processing', "data-success": isSucceed, "data-error": status === 'error', children: variant === 'linear'
|
|
57
|
+
return (_jsx("div", { ...props, css: useStyle({ color: color || 'primary', variant }), className: clsx(classes.root, props.className), "data-variant": variant, "data-indeterminate": indeterminate, "data-processing": value < 100 && status === 'processing', "data-success": isColorSpecified ? void 0 : isSucceed, "data-error": isColorSpecified ? void 0 : status === 'error', children: variant === 'linear'
|
|
56
58
|
? _jsxs(_Fragment, { children: [_jsx("div", { className: classes.track, style: {
|
|
57
59
|
height: barWidth,
|
|
58
60
|
...props.style
|
|
@@ -24,11 +24,12 @@ export declare class SnackbarBaseMethods<P extends SnackbarBaseProps = SnackbarB
|
|
|
24
24
|
error(content: ReactNode): Promise<void>;
|
|
25
25
|
error(props: P): Promise<void>;
|
|
26
26
|
}
|
|
27
|
-
export declare const SnackbarBase: React.MemoExoticComponent<({ methods, useTo, max, container }: {
|
|
27
|
+
export declare const SnackbarBase: React.MemoExoticComponent<({ methods, useTo, max, container, effectContainer }: {
|
|
28
28
|
methods: SnackbarBaseMethods;
|
|
29
29
|
useTo: "message" | "notification";
|
|
30
30
|
max?: number;
|
|
31
|
-
container?: DefineElement
|
|
31
|
+
container?: DefineElement<HTMLElement>;
|
|
32
|
+
effectContainer?: DefineElement<HTMLElement>;
|
|
32
33
|
}) => React.ReactPortal>;
|
|
33
34
|
interface SnackbarBaseItemProps extends Omit<SnackbarBaseProps, 'duration' | 'onAutoClose'> {
|
|
34
35
|
id: string;
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
|
2
2
|
import { createElement as _createElement } from "@emotion/react";
|
|
3
3
|
import { isValidElement, memo, useEffect, useRef, useState } from 'react';
|
|
4
4
|
import { Collapse, Slide } from '../transitionBase';
|
|
5
|
-
import { clsx, getEasyID, useColor } from '../../utils';
|
|
5
|
+
import { clsx, getEasyID, useColor, useContainer } 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';
|
|
@@ -33,7 +33,7 @@ const placementToIndex = {
|
|
|
33
33
|
bottomRight: 5,
|
|
34
34
|
rightBottom: 5
|
|
35
35
|
};
|
|
36
|
-
export const SnackbarBase = memo(({ methods, useTo, max = useTo === 'message' ? 5 : 4, container }) => {
|
|
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
39
|
useEffect(() => () => {
|
|
@@ -81,10 +81,10 @@ export const SnackbarBase = memo(({ methods, useTo, max = useTo === 'message' ?
|
|
|
81
81
|
methods.warning = defineMethod('warning');
|
|
82
82
|
methods.error = defineMethod('error');
|
|
83
83
|
const css = style();
|
|
84
|
-
const containerEl = (
|
|
84
|
+
const containerEl = useContainer(container, effectContainer);
|
|
85
85
|
return 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
|
-
: []), containerEl);
|
|
87
|
+
: []), containerEl.current);
|
|
88
88
|
});
|
|
89
89
|
/**
|
|
90
90
|
* ----------------------------------------------------------------------
|
|
@@ -1,16 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export interface TouchRippleProps extends Omit<DivProps, 'children'> {
|
|
1
|
+
import { ColorPropsValue, DefineElement, DivProps } from '../../types';
|
|
2
|
+
export interface TouchRippleOverlayProps extends DivProps {
|
|
4
3
|
color?: ColorPropsValue;
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
/** 容器元素,默认为该组件元素的父元素 */
|
|
5
|
+
container?: DefineElement<HTMLElement>;
|
|
6
|
+
effectContainer?: DefineElement<HTMLElement>;
|
|
7
7
|
}
|
|
8
|
-
export declare const TouchRipple: {
|
|
9
|
-
(props: TouchRippleProps): ReactElement;
|
|
10
|
-
Ripple: typeof Ripple;
|
|
11
|
-
};
|
|
12
|
-
interface RippleProps extends DivProps {
|
|
13
|
-
color?: ColorPropsValue;
|
|
14
|
-
}
|
|
15
|
-
export declare const Ripple: import("react").MemoExoticComponent<({ ref, color, ...props }: RippleProps) => import("@emotion/react/jsx-runtime").JSX.Element>;
|
|
16
|
-
export {};
|
|
8
|
+
export declare const TouchRipple: import("react").MemoExoticComponent<({ color, container, effectContainer, ...props }: TouchRippleOverlayProps) => import("@emotion/react/jsx-runtime").JSX.Element>;
|
|
@@ -1,54 +1,69 @@
|
|
|
1
1
|
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { memo, useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { createPortal } from 'react-dom';
|
|
4
|
+
import { cloneRef, clsx, useContainer } from '../../utils';
|
|
3
5
|
import { classes, useStyle } from './touchRipple.style';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
{
|
|
24
|
-
key: getEasyID('touch-ripple'),
|
|
25
|
-
r: Math.sqrt(wrapper.clientWidth ** 2 + wrapper.clientHeight ** 2),
|
|
26
|
-
left: e.offsetX,
|
|
27
|
-
top: e.offsetY,
|
|
6
|
+
export const TouchRipple = memo(({ color = 'primary', container, effectContainer, ...props }) => {
|
|
7
|
+
const ref = useRef(null);
|
|
8
|
+
const [ripples, setRipples] = useState(new Map());
|
|
9
|
+
const incrementKey = useRef(0);
|
|
10
|
+
const containerEl = useContainer(container, effectContainer, null);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
const parentElement = containerEl.current ?? ref.current.parentElement;
|
|
13
|
+
if (parentElement) {
|
|
14
|
+
const pointerDown = ({ offsetX, offsetY }) => {
|
|
15
|
+
const maxWidth = Math.max(parentElement.clientWidth - offsetX, offsetX);
|
|
16
|
+
const maxHeight = Math.max(parentElement.clientHeight - offsetY, offsetY);
|
|
17
|
+
setRipples(o => {
|
|
18
|
+
const r = new Map(o);
|
|
19
|
+
const key = ++incrementKey.current;
|
|
20
|
+
r.set(key, {
|
|
21
|
+
key,
|
|
22
|
+
diameter: Math.sqrt(maxWidth ** 2 + maxHeight ** 2) * 2,
|
|
23
|
+
left: offsetX,
|
|
24
|
+
top: offsetY,
|
|
28
25
|
leaving: false
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
});
|
|
27
|
+
return r;
|
|
28
|
+
});
|
|
29
|
+
parentElement.addEventListener('pointerup', leave);
|
|
30
|
+
parentElement.addEventListener('pointerleave', leave);
|
|
33
31
|
};
|
|
34
32
|
const leave = () => {
|
|
35
|
-
setRipples(o =>
|
|
33
|
+
setRipples(o => {
|
|
34
|
+
const r = new Map(o);
|
|
35
|
+
r.forEach(v => v.leaving = true);
|
|
36
|
+
return r;
|
|
37
|
+
});
|
|
36
38
|
removeLeaveListener();
|
|
37
39
|
};
|
|
38
|
-
wrapper.addEventListener('pointerdown', pointerDown);
|
|
39
40
|
const removeLeaveListener = () => {
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
parentElement.removeEventListener('pointerup', leave);
|
|
42
|
+
parentElement.removeEventListener('pointerleave', leave);
|
|
42
43
|
};
|
|
44
|
+
parentElement.addEventListener('pointerdown', pointerDown);
|
|
43
45
|
return () => {
|
|
44
|
-
|
|
46
|
+
parentElement.removeEventListener('pointerdown', pointerDown);
|
|
45
47
|
removeLeaveListener();
|
|
46
48
|
};
|
|
47
49
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
}, [containerEl.current]);
|
|
51
|
+
const leftHandler = (key) => {
|
|
52
|
+
setRipples(o => {
|
|
53
|
+
const r = new Map(o);
|
|
54
|
+
r.delete(key);
|
|
55
|
+
if (!r.size) {
|
|
56
|
+
incrementKey.current = 0;
|
|
57
|
+
}
|
|
58
|
+
return r;
|
|
59
|
+
});
|
|
52
60
|
};
|
|
53
|
-
|
|
61
|
+
const children = (_jsx("div", { ...props, ref: cloneRef(ref, props.ref), css: useStyle({ color }), className: clsx(classes.root, props.className), children: ripples.values().toArray().map(({ key, diameter, left, top, leaving }) => _jsx("div", { className: classes.ripple, style: {
|
|
62
|
+
width: diameter,
|
|
63
|
+
height: diameter,
|
|
64
|
+
left, top
|
|
65
|
+
}, "data-leaving": leaving, onTransitionEnd: () => leftHandler(key) }, key)) }));
|
|
66
|
+
return containerEl.current
|
|
67
|
+
? createPortal(children, containerEl.current)
|
|
68
|
+
: children;
|
|
54
69
|
});
|