@canlooks/can-ui 0.0.145 → 0.0.147
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/autocomplete/autocomplete.js +10 -5
- package/dist/cjs/components/cascade/searchResult.js +2 -2
- package/dist/cjs/components/clickAway/clickAway.d.ts +11 -11
- package/dist/cjs/components/dataGrid/dataGridHead.js +2 -1
- package/dist/cjs/components/dataGrid/filterBubbleContent.js +1 -1
- package/dist/cjs/components/inputBase/inputBase.style.js +1 -1
- package/dist/cjs/components/optionsBase/filterOptions.d.ts +4 -0
- package/dist/cjs/components/optionsBase/filterOptions.js +36 -0
- package/dist/cjs/components/optionsBase/optionsBase.d.ts +5 -0
- package/dist/cjs/components/optionsBase/optionsBase.js +3 -28
- package/dist/cjs/components/popper/popper.d.ts +4 -2
- package/dist/cjs/components/popper/popper.js +7 -2
- package/dist/cjs/components/popper/popper.style.js +4 -1
- package/dist/cjs/utils/utils.js +5 -4
- package/dist/esm/components/autocomplete/autocomplete.js +11 -6
- package/dist/esm/components/cascade/searchResult.js +2 -2
- package/dist/esm/components/clickAway/clickAway.d.ts +11 -11
- package/dist/esm/components/dataGrid/dataGridHead.js +2 -1
- package/dist/esm/components/dataGrid/filterBubbleContent.js +1 -1
- package/dist/esm/components/inputBase/inputBase.style.js +1 -1
- package/dist/esm/components/optionsBase/filterOptions.d.ts +4 -0
- package/dist/esm/components/optionsBase/filterOptions.js +33 -0
- package/dist/esm/components/optionsBase/optionsBase.d.ts +5 -0
- package/dist/esm/components/optionsBase/optionsBase.js +4 -29
- package/dist/esm/components/popper/popper.d.ts +4 -2
- package/dist/esm/components/popper/popper.js +7 -2
- package/dist/esm/components/popper/popper.style.js +4 -1
- package/dist/esm/utils/utils.js +5 -4
- package/package.json +15 -18
- package/documentation/bootstrap.mjs +0 -8
- package/documentation/dist/assets/index-DyrGMYuH.js +0 -8115
- package/documentation/dist/atom-one-dark.min.css +0 -1
- package/documentation/dist/components/accordion.md +0 -38
- package/documentation/dist/components/actionSheet.md +0 -49
- package/documentation/dist/components/alert.md +0 -38
- package/documentation/dist/components/anchorList.md +0 -36
- package/documentation/dist/components/autocomplete.md +0 -68
- package/documentation/dist/components/avatar.md +0 -79
- package/documentation/dist/components/badge.md +0 -33
- package/documentation/dist/components/bottomNavigation.md +0 -39
- package/documentation/dist/components/breadcrumb.md +0 -28
- package/documentation/dist/components/bubbleConfirm.md +0 -34
- package/documentation/dist/components/button.md +0 -62
- package/documentation/dist/components/card.md +0 -30
- package/documentation/dist/components/cascade.md +0 -48
- package/documentation/dist/components/checkbox.md +0 -36
- package/documentation/dist/components/colorPicker.md +0 -27
- package/documentation/dist/components/contextMenu.md +0 -27
- package/documentation/dist/components/counter.md +0 -29
- package/documentation/dist/components/dataGrid.md +0 -112
- package/documentation/dist/components/dateTimePicker.md +0 -35
- package/documentation/dist/components/dateTimeRangePicker.md +0 -36
- package/documentation/dist/components/descriptions.md +0 -35
- package/documentation/dist/components/dialog.md +0 -56
- package/documentation/dist/components/divider.md +0 -26
- package/documentation/dist/components/drawer.md +0 -40
- package/documentation/dist/components/flex.md +0 -20
- package/documentation/dist/components/form.md +0 -131
- package/documentation/dist/components/formDialog.md +0 -36
- package/documentation/dist/components/grid.md +0 -34
- package/documentation/dist/components/highlight.md +0 -26
- package/documentation/dist/components/image.md +0 -90
- package/documentation/dist/components/input.md +0 -39
- package/documentation/dist/components/loading.md +0 -46
- package/documentation/dist/components/menu.md +0 -85
- package/documentation/dist/components/pagination.md +0 -38
- package/documentation/dist/components/pickerDialog.md +0 -56
- package/documentation/dist/components/placeholder.md +0 -30
- package/documentation/dist/components/progress.md +0 -43
- package/documentation/dist/components/radio.md +0 -37
- package/documentation/dist/components/rating.md +0 -35
- package/documentation/dist/components/resizable.md +0 -41
- package/documentation/dist/components/scrollbar.md +0 -31
- package/documentation/dist/components/segmented.md +0 -57
- package/documentation/dist/components/select.md +0 -30
- package/documentation/dist/components/skeleton.md +0 -26
- package/documentation/dist/components/slidableActions.md +0 -53
- package/documentation/dist/guide/appComponent.md +0 -30
- package/documentation/dist/guide/globalMethods.md +0 -238
- package/documentation/dist/guide/icon.md +0 -57
- package/documentation/dist/guide/introduction.md +0 -2
- package/documentation/dist/guide/overrideProps.md +0 -0
- package/documentation/dist/guide/startup.md +0 -23
- package/documentation/dist/guide/theme.md +0 -249
- package/documentation/dist/index.html +0 -13
- package/documentation/dist/logo.png +0 -0
- package/documentation/vite.config.mjs +0 -22
|
@@ -9,6 +9,7 @@ const input_1 = require("../input");
|
|
|
9
9
|
const utils_1 = require("../../utils");
|
|
10
10
|
const autocomplete_style_1 = require("./autocomplete.style");
|
|
11
11
|
const popper_style_1 = require("../popper/popper.style");
|
|
12
|
+
const filterOptions_1 = require("../optionsBase/filterOptions");
|
|
12
13
|
exports.Autocomplete = (0, react_1.memo)(({ children, loading, options, loadOptions, primaryKey = 'value', labelKey = 'label', onSelect, renderInput, popperProps, popperRef, defaultValue = '', value, onChange, ...props }) => {
|
|
13
14
|
const [focused, _setFocused] = (0, react_1.useState)(false);
|
|
14
15
|
const setFocused = (focused) => {
|
|
@@ -36,7 +37,12 @@ exports.Autocomplete = (0, react_1.memo)(({ children, loading, options, loadOpti
|
|
|
36
37
|
* ------------------------------------------------------------------
|
|
37
38
|
* 合并最终选项
|
|
38
39
|
*/
|
|
39
|
-
const actualOptions =
|
|
40
|
+
const actualOptions = (0, filterOptions_1.useFilterOptions)({
|
|
41
|
+
searchValue: innerValue.current,
|
|
42
|
+
options: innerOptions || options,
|
|
43
|
+
children,
|
|
44
|
+
labelKey
|
|
45
|
+
}).map(opt => (0, react_1.isValidElement)(opt) ? opt.props : opt);
|
|
40
46
|
const optionsMap = (0, react_1.useMemo)(() => {
|
|
41
47
|
const map = new Map();
|
|
42
48
|
actualOptions?.forEach(opt => {
|
|
@@ -49,7 +55,7 @@ exports.Autocomplete = (0, react_1.memo)(({ children, loading, options, loadOpti
|
|
|
49
55
|
}, [actualOptions, primaryKey]);
|
|
50
56
|
const [open, _setOpen] = (0, utils_1.useDerivedState)(() => {
|
|
51
57
|
return focused && !!optionsMap.size;
|
|
52
|
-
}, [focused, optionsMap
|
|
58
|
+
}, [focused, optionsMap]);
|
|
53
59
|
const setOpen = (open) => {
|
|
54
60
|
if (!props.disabled && !props.readOnly && (!open || optionsMap.size)) {
|
|
55
61
|
// 必须有选项才能打开下拉框
|
|
@@ -75,8 +81,6 @@ exports.Autocomplete = (0, react_1.memo)(({ children, loading, options, loadOpti
|
|
|
75
81
|
loading: innerLoading.current,
|
|
76
82
|
value: innerValue.current,
|
|
77
83
|
onChange: changeHandler,
|
|
78
|
-
onInput: () => setOpen(true),
|
|
79
|
-
onClick: () => setOpen(true),
|
|
80
84
|
onFocus: () => setFocused(true),
|
|
81
85
|
onBlur: () => setFocused(false)
|
|
82
86
|
});
|
|
@@ -84,7 +88,8 @@ exports.Autocomplete = (0, react_1.memo)(({ children, loading, options, loadOpti
|
|
|
84
88
|
placement: 'bottom',
|
|
85
89
|
variant: 'collapse',
|
|
86
90
|
trigger: false,
|
|
87
|
-
|
|
91
|
+
animation: false,
|
|
92
|
+
content: ((0, jsx_runtime_1.jsx)(optionsBase_1.OptionsBase, { onToggleSelected: optionSelectHandler, loading: innerLoading.current, options: actualOptions, labelKey: labelKey, primaryKey: primaryKey, searchValue: innerValue.current, _optionsAlreadyFilter: true, children: children }))
|
|
88
93
|
}, popperProps, {
|
|
89
94
|
css: popper_style_1.popperStyle,
|
|
90
95
|
open: open.current,
|
|
@@ -42,9 +42,9 @@ exports.SearchResult = (0, react_1.memo)(({ primaryKey, labelKey, childrenKey, s
|
|
|
42
42
|
if (!searchValue) {
|
|
43
43
|
return flattedOptions;
|
|
44
44
|
}
|
|
45
|
-
const
|
|
45
|
+
const split = searchValue.split(' ');
|
|
46
46
|
return flattedOptions.filter(({ searchToken }) => {
|
|
47
|
-
return
|
|
47
|
+
return split.some(k => {
|
|
48
48
|
return k && searchToken.toLowerCase().includes(k.toLowerCase());
|
|
49
49
|
});
|
|
50
50
|
});
|
|
@@ -140,18 +140,18 @@ export declare function ClickAway({ ref, container, eventType, onClickAway, disa
|
|
|
140
140
|
onFocusCapture: import("react").FocusEventHandler<HTMLDivElement>;
|
|
141
141
|
onBlur: import("react").FocusEventHandler<HTMLDivElement>;
|
|
142
142
|
onBlurCapture: import("react").FocusEventHandler<HTMLDivElement>;
|
|
143
|
-
onChange: import("react").
|
|
144
|
-
onChangeCapture: import("react").
|
|
143
|
+
onChange: import("react").ChangeEventHandler<HTMLDivElement, Element>;
|
|
144
|
+
onChangeCapture: import("react").ChangeEventHandler<HTMLDivElement, Element>;
|
|
145
145
|
onBeforeInput: import("react").InputEventHandler<HTMLDivElement>;
|
|
146
|
-
onBeforeInputCapture: import("react").
|
|
147
|
-
onInput: import("react").
|
|
148
|
-
onInputCapture: import("react").
|
|
149
|
-
onReset: import("react").
|
|
150
|
-
onResetCapture: import("react").
|
|
151
|
-
onSubmit: import("react").
|
|
152
|
-
onSubmitCapture: import("react").
|
|
153
|
-
onInvalid: import("react").
|
|
154
|
-
onInvalidCapture: import("react").
|
|
146
|
+
onBeforeInputCapture: import("react").InputEventHandler<HTMLDivElement>;
|
|
147
|
+
onInput: import("react").InputEventHandler<HTMLDivElement>;
|
|
148
|
+
onInputCapture: import("react").InputEventHandler<HTMLDivElement>;
|
|
149
|
+
onReset: import("react").ReactEventHandler<HTMLDivElement>;
|
|
150
|
+
onResetCapture: import("react").ReactEventHandler<HTMLDivElement>;
|
|
151
|
+
onSubmit: import("react").SubmitEventHandler<HTMLDivElement>;
|
|
152
|
+
onSubmitCapture: import("react").SubmitEventHandler<HTMLDivElement>;
|
|
153
|
+
onInvalid: import("react").ReactEventHandler<HTMLDivElement>;
|
|
154
|
+
onInvalidCapture: import("react").ReactEventHandler<HTMLDivElement>;
|
|
155
155
|
onLoad: import("react").ReactEventHandler<HTMLDivElement>;
|
|
156
156
|
onLoadCapture: import("react").ReactEventHandler<HTMLDivElement>;
|
|
157
157
|
onError: import("react").ReactEventHandler<HTMLDivElement>;
|
|
@@ -86,7 +86,8 @@ exports.DataGridHead = (0, react_2.memo)(({ allowSelectAll, columnResizable, fla
|
|
|
86
86
|
const sortable = sorter && !children?.length;
|
|
87
87
|
const isOrderingColumn = orderColumn === _key;
|
|
88
88
|
const currentOrderType = isOrderingColumn ? orderType : 'descend';
|
|
89
|
-
const
|
|
89
|
+
const filteredValue = formValue?.[_key];
|
|
90
|
+
const isFilteredColumn = !(0, utils_1.isUnset)(filteredValue) && !(Array.isArray(filteredValue) && !filteredValue.length);
|
|
90
91
|
const filterButton = ((0, jsx_runtime_1.jsx)(button_1.Button, { className: dataGrid_style_1.classes.filterButton, variant: "plain", color: isFilteredColumn ? 'primary' : 'text.placeholder', onClick: e => {
|
|
91
92
|
e.stopPropagation();
|
|
92
93
|
onFilterClick?.(_key, e);
|
|
@@ -25,7 +25,7 @@ exports.FilterBubbleContent = (0, react_1.memo)(({ columnKey, columnFilterProps
|
|
|
25
25
|
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(form_1.FormItem, { field: columnKey, children: 'control' in columnFilterProps
|
|
26
26
|
? columnFilterProps.control
|
|
27
27
|
: (0, jsx_runtime_1.jsx)(FilterOptions, { ...columnFilterProps, onChange: () => {
|
|
28
|
-
|
|
28
|
+
columnFilterProps.multiple === false && setOpen(false);
|
|
29
29
|
} }) }), columnFilterProps.showResetButton !== false &&
|
|
30
30
|
(0, jsx_runtime_1.jsx)(flex_1.Flex, { gap: 6, justifyContent: "center", marginTop: 6, children: (0, jsx_runtime_1.jsx)(button_1.Button, { variant: "text", onClick: () => {
|
|
31
31
|
formRef.current.resetField(columnKey);
|
|
@@ -78,7 +78,7 @@ function useStyle({ color }) {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
&:not(:has([data-read-only=true]))[data-focused=true],
|
|
81
|
-
&:not(:has([data-read-only=true])):
|
|
81
|
+
&:not(:has([data-read-only=true])):focus-within {
|
|
82
82
|
&::before, &::after {
|
|
83
83
|
display: block;
|
|
84
84
|
animation: ${borderAnim} .4s ${easing.easeOut} forwards;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { Id } from '../../types';
|
|
3
|
+
import { MenuOptionType, OptionsBaseProps } from './optionsBase';
|
|
4
|
+
export declare function useFilterOptions<O extends MenuOptionType<V>, V extends Id = Id>({ searchValue, options, children, filterPredicate, labelKey, searchTokenKey, _optionsAlreadyFilter }: Pick<OptionsBaseProps<O, V>, 'searchValue' | 'children' | 'options' | 'filterPredicate' | 'labelKey' | 'searchTokenKey' | '_optionsAlreadyFilter'>): (O | ReactNode)[];
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useFilterOptions = useFilterOptions;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
function useFilterOptions({ searchValue, options, children, filterPredicate, labelKey = 'label', searchTokenKey = 'searchToken', _optionsAlreadyFilter }) {
|
|
6
|
+
return (0, react_1.useMemo)(() => {
|
|
7
|
+
if (_optionsAlreadyFilter) {
|
|
8
|
+
return options || react_1.Children.toArray(children);
|
|
9
|
+
}
|
|
10
|
+
const trimmedSearchValue = searchValue?.trim();
|
|
11
|
+
if (!trimmedSearchValue) {
|
|
12
|
+
return options || react_1.Children.toArray(children);
|
|
13
|
+
}
|
|
14
|
+
const splitValue = trimmedSearchValue.split(' ');
|
|
15
|
+
const filterFn = (opt, index) => {
|
|
16
|
+
let ret = false;
|
|
17
|
+
if (filterPredicate) {
|
|
18
|
+
ret = filterPredicate(trimmedSearchValue, opt, index);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
const searchToken = typeof opt[labelKey] === 'string' ? opt[labelKey] : opt[searchTokenKey];
|
|
22
|
+
if (typeof searchToken === 'string') {
|
|
23
|
+
ret = splitValue.some(k => {
|
|
24
|
+
return k && searchToken.toLowerCase().includes(k.toLowerCase());
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return ret;
|
|
29
|
+
};
|
|
30
|
+
return options
|
|
31
|
+
? options.filter(filterFn)
|
|
32
|
+
: react_1.Children.toArray(children).filter((c, index) => {
|
|
33
|
+
return (0, react_1.isValidElement)(c) && filterFn(c.props, index);
|
|
34
|
+
});
|
|
35
|
+
}, [searchValue, filterPredicate, options, children, labelKey, searchTokenKey, _optionsAlreadyFilter]);
|
|
36
|
+
}
|
|
@@ -27,5 +27,10 @@ export interface OptionsBaseProps<O extends MenuOptionType<V>, V extends Id = Id
|
|
|
27
27
|
searchValue?: string;
|
|
28
28
|
selectedValue?: V | V[];
|
|
29
29
|
onToggleSelected?(value: V, e: KeyboardEvent | React.MouseEvent<HTMLDivElement>): void;
|
|
30
|
+
/**
|
|
31
|
+
* @private
|
|
32
|
+
* 内部使用,传入的选项是否已经经过筛选
|
|
33
|
+
*/
|
|
34
|
+
_optionsAlreadyFilter?: boolean;
|
|
30
35
|
}
|
|
31
36
|
export declare const OptionsBase: <O extends MenuOptionType<V>, V extends Id = Id>(props: OptionsBaseProps<O, V>) => ReactElement;
|
|
@@ -10,39 +10,14 @@ const utils_1 = require("../../utils");
|
|
|
10
10
|
const optionsBase_style_1 = require("./optionsBase.style");
|
|
11
11
|
const loading_1 = require("../loading");
|
|
12
12
|
const popper_1 = require("../popper");
|
|
13
|
+
const filterOptions_1 = require("./filterOptions");
|
|
13
14
|
exports.OptionsBase = (0, react_1.memo)(({
|
|
14
15
|
// 共享属性
|
|
15
16
|
showCheckbox, loading, options, children, labelKey = 'label', primaryKey = 'value', searchTokenKey = 'searchToken', filterPredicate,
|
|
16
17
|
// 以下为非共享属性
|
|
17
|
-
searchValue, selectedValue, onToggleSelected, ...props }) => {
|
|
18
|
+
searchValue, selectedValue, onToggleSelected, _optionsAlreadyFilter, ...props }) => {
|
|
18
19
|
const { open, setOpen } = (0, popper_1.usePopperContext)();
|
|
19
|
-
const filteredOptions = (0,
|
|
20
|
-
const trimmedSearchValue = searchValue?.trim();
|
|
21
|
-
if (!trimmedSearchValue) {
|
|
22
|
-
return options || react_1.Children.toArray(children);
|
|
23
|
-
}
|
|
24
|
-
const splitedValue = trimmedSearchValue.split(' ');
|
|
25
|
-
const filterFn = (opt, index) => {
|
|
26
|
-
let ret = false;
|
|
27
|
-
if (filterPredicate) {
|
|
28
|
-
ret = filterPredicate(trimmedSearchValue, opt, index);
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
const searchToken = typeof opt[labelKey] === 'string' ? opt[labelKey] : opt[searchTokenKey];
|
|
32
|
-
if (typeof searchToken === 'string') {
|
|
33
|
-
ret = splitedValue.some(k => {
|
|
34
|
-
return k && searchToken.toLowerCase().includes(k.toLowerCase());
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return ret;
|
|
39
|
-
};
|
|
40
|
-
return options
|
|
41
|
-
? options.filter(filterFn)
|
|
42
|
-
: react_1.Children.toArray(children).filter((c, index) => {
|
|
43
|
-
return (0, react_1.isValidElement)(c) && filterFn(c.props, index);
|
|
44
|
-
});
|
|
45
|
-
}, [searchValue, filterPredicate, options, children, labelKey, searchTokenKey]);
|
|
20
|
+
const filteredOptions = (0, filterOptions_1.useFilterOptions)({ searchValue, filterPredicate, options, children, labelKey, searchTokenKey, _optionsAlreadyFilter });
|
|
46
21
|
/**
|
|
47
22
|
* ------------------------------------------------------------------
|
|
48
23
|
* 键盘控制
|
|
@@ -28,7 +28,7 @@ export interface PopperProps extends Omit<DivProps, 'content' | 'children'> {
|
|
|
28
28
|
sizeAdaptable?: boolean;
|
|
29
29
|
/** trigger{@link trigger}包含"hover"时,鼠标移入移的延迟时间,默认为`150(ms)` */
|
|
30
30
|
mouseEnterDelay?: number;
|
|
31
|
-
|
|
31
|
+
/** 默认为`150(ms)` */
|
|
32
32
|
mouseLeaveDelay?: number;
|
|
33
33
|
defaultOpen?: boolean;
|
|
34
34
|
open?: boolean;
|
|
@@ -43,6 +43,8 @@ export interface PopperProps extends Omit<DivProps, 'content' | 'children'> {
|
|
|
43
43
|
* @enum {undefined} 第一次打开时渲染,跟随父组件销毁。
|
|
44
44
|
*/
|
|
45
45
|
forceRender?: boolean;
|
|
46
|
+
/** 打开与关闭是否渲染过度动画,默认为`true` */
|
|
47
|
+
animation?: boolean;
|
|
46
48
|
children?: ReactElement<any>;
|
|
47
49
|
}
|
|
48
50
|
export interface PopperRef extends HTMLDivElement {
|
|
@@ -51,4 +53,4 @@ export interface PopperRef extends HTMLDivElement {
|
|
|
51
53
|
openAnimation?: boolean;
|
|
52
54
|
}, beforeOpen?: () => void): void;
|
|
53
55
|
}
|
|
54
|
-
export declare function Popper({ ref, popperRef, anchorElement, container, effectContainer, content, offset, trigger, clickToClose, placement, variant, sizeAdaptable, mouseEnterDelay, mouseLeaveDelay, defaultOpen, open, onOpenChange, onOpenChangeEnd, disabled, autoClose, forceRender, children, ...props }: PopperProps): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
56
|
+
export declare function Popper({ ref, popperRef, anchorElement, container, effectContainer, content, offset, trigger, clickToClose, placement, variant, sizeAdaptable, mouseEnterDelay, mouseLeaveDelay, defaultOpen, open, onOpenChange, onOpenChangeEnd, disabled, autoClose, forceRender, animation, children, ...props }: PopperProps): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
@@ -22,7 +22,7 @@ const getAttemptOrder = (placement) => {
|
|
|
22
22
|
}
|
|
23
23
|
return order;
|
|
24
24
|
};
|
|
25
|
-
function Popper({ ref, popperRef, anchorElement, container, effectContainer, content, offset, trigger = 'hover', clickToClose, placement = 'top', variant = 'zoom', sizeAdaptable = variant === 'collapse', mouseEnterDelay = 150, mouseLeaveDelay = 150, defaultOpen = false, open, onOpenChange, onOpenChangeEnd, disabled, autoClose = false, forceRender, children, ...props }) {
|
|
25
|
+
function Popper({ ref, popperRef, anchorElement, container, effectContainer, content, offset, trigger = 'hover', clickToClose, placement = 'top', variant = 'zoom', sizeAdaptable = variant === 'collapse', mouseEnterDelay = 150, mouseLeaveDelay = 150, defaultOpen = false, open, onOpenChange, onOpenChangeEnd, disabled, autoClose = false, forceRender, animation = true, children, ...props }) {
|
|
26
26
|
const { spacing } = (0, theme_1.useTheme)();
|
|
27
27
|
offset ??= spacing[2];
|
|
28
28
|
(0, react_1.useImperativeHandle)(popperRef, () => {
|
|
@@ -55,6 +55,8 @@ function Popper({ ref, popperRef, anchorElement, container, effectContainer, con
|
|
|
55
55
|
if (newOpen || openHolding.current === 0) {
|
|
56
56
|
_setInnerOpen(newOpen);
|
|
57
57
|
}
|
|
58
|
+
// 不渲染动画时,需要手动触发onTransitionEnd
|
|
59
|
+
!animation && transitionEndHandler();
|
|
58
60
|
};
|
|
59
61
|
const { onChildrenOpenChange: tellParentOpenChange } = (0, popperContext_1.usePopperContext)();
|
|
60
62
|
(0, utils_1.useUpdateEffect)(() => {
|
|
@@ -85,6 +87,9 @@ function Popper({ ref, popperRef, anchorElement, container, effectContainer, con
|
|
|
85
87
|
const animating = (0, react_1.useRef)(false);
|
|
86
88
|
const onTransitionEnd = (e) => {
|
|
87
89
|
props.onTransitionEnd?.(e);
|
|
90
|
+
transitionEndHandler();
|
|
91
|
+
};
|
|
92
|
+
const transitionEndHandler = () => {
|
|
88
93
|
onOpenChangeEnd?.(innerOpen.current);
|
|
89
94
|
if (forceRender === false && !innerOpen.current) {
|
|
90
95
|
renderedOnce.current = false;
|
|
@@ -541,5 +546,5 @@ function Popper({ ref, popperRef, anchorElement, container, effectContainer, con
|
|
|
541
546
|
transform: 'scale(1)'
|
|
542
547
|
},
|
|
543
548
|
...props.style
|
|
544
|
-
}, "data-open": innerOpen.current, "data-variant": variant, "data-place-a": placeA.current, "data-place-b": placeB.current, onTransitionEnd: onTransitionEnd, children: (0, jsx_runtime_1.jsx)(popperContext_1.PopperContext, { value: contextValue, children: content }) }) }), containerEl.current)] }));
|
|
549
|
+
}, "data-open": innerOpen.current, "data-variant": variant, "data-place-a": placeA.current, "data-place-b": placeB.current, "data-animation": animation, onTransitionEnd: onTransitionEnd, children: (0, jsx_runtime_1.jsx)(popperContext_1.PopperContext, { value: contextValue, children: content }) }) }), containerEl.current)] }));
|
|
545
550
|
}
|
|
@@ -19,7 +19,10 @@ exports.style = (0, utils_1.defineCss)(theme => {
|
|
|
19
19
|
left: 0;
|
|
20
20
|
z-index: ${theme_1.zIndex.popper};
|
|
21
21
|
transition-property: transform, opacity;
|
|
22
|
-
|
|
22
|
+
|
|
23
|
+
&[data-animation=true] {
|
|
24
|
+
transition-duration: .25s;
|
|
25
|
+
}
|
|
23
26
|
|
|
24
27
|
&[data-open=true] {
|
|
25
28
|
transition-timing-function: ${easing.bounce}, ${easing.easeOut};
|
package/dist/cjs/utils/utils.js
CHANGED
|
@@ -399,11 +399,12 @@ function mergeComponentProps(...props) {
|
|
|
399
399
|
target.style = { ...source.style, ...target.style };
|
|
400
400
|
continue;
|
|
401
401
|
default:
|
|
402
|
-
const
|
|
403
|
-
if (typeof
|
|
402
|
+
const sourceFn = source[p];
|
|
403
|
+
if (typeof sourceFn === 'function') {
|
|
404
|
+
const targetFn = target[p];
|
|
404
405
|
target[p] = (...args) => {
|
|
405
|
-
|
|
406
|
-
|
|
406
|
+
targetFn(...args);
|
|
407
|
+
sourceFn(...args);
|
|
407
408
|
};
|
|
408
409
|
continue;
|
|
409
410
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { isValidElement, memo, useCallback, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { Popper } from '../popper';
|
|
4
4
|
import { OptionsBase } from '../optionsBase';
|
|
5
5
|
import { Input } from '../input';
|
|
6
6
|
import { isUnset, useControlled, useDerivedState, useLoading, useSync, mergeComponentProps, useStrictEffect } from '../../utils';
|
|
7
7
|
import { classes } from './autocomplete.style';
|
|
8
8
|
import { popperStyle } from '../popper/popper.style';
|
|
9
|
+
import { useFilterOptions } from '../optionsBase/filterOptions';
|
|
9
10
|
export const Autocomplete = memo(({ children, loading, options, loadOptions, primaryKey = 'value', labelKey = 'label', onSelect, renderInput, popperProps, popperRef, defaultValue = '', value, onChange, ...props }) => {
|
|
10
11
|
const [focused, _setFocused] = useState(false);
|
|
11
12
|
const setFocused = (focused) => {
|
|
@@ -33,7 +34,12 @@ export const Autocomplete = memo(({ children, loading, options, loadOptions, pri
|
|
|
33
34
|
* ------------------------------------------------------------------
|
|
34
35
|
* 合并最终选项
|
|
35
36
|
*/
|
|
36
|
-
const actualOptions =
|
|
37
|
+
const actualOptions = useFilterOptions({
|
|
38
|
+
searchValue: innerValue.current,
|
|
39
|
+
options: innerOptions || options,
|
|
40
|
+
children,
|
|
41
|
+
labelKey
|
|
42
|
+
}).map(opt => isValidElement(opt) ? opt.props : opt);
|
|
37
43
|
const optionsMap = useMemo(() => {
|
|
38
44
|
const map = new Map();
|
|
39
45
|
actualOptions?.forEach(opt => {
|
|
@@ -46,7 +52,7 @@ export const Autocomplete = memo(({ children, loading, options, loadOptions, pri
|
|
|
46
52
|
}, [actualOptions, primaryKey]);
|
|
47
53
|
const [open, _setOpen] = useDerivedState(() => {
|
|
48
54
|
return focused && !!optionsMap.size;
|
|
49
|
-
}, [focused, optionsMap
|
|
55
|
+
}, [focused, optionsMap]);
|
|
50
56
|
const setOpen = (open) => {
|
|
51
57
|
if (!props.disabled && !props.readOnly && (!open || optionsMap.size)) {
|
|
52
58
|
// 必须有选项才能打开下拉框
|
|
@@ -72,8 +78,6 @@ export const Autocomplete = memo(({ children, loading, options, loadOptions, pri
|
|
|
72
78
|
loading: innerLoading.current,
|
|
73
79
|
value: innerValue.current,
|
|
74
80
|
onChange: changeHandler,
|
|
75
|
-
onInput: () => setOpen(true),
|
|
76
|
-
onClick: () => setOpen(true),
|
|
77
81
|
onFocus: () => setFocused(true),
|
|
78
82
|
onBlur: () => setFocused(false)
|
|
79
83
|
});
|
|
@@ -81,7 +85,8 @@ export const Autocomplete = memo(({ children, loading, options, loadOptions, pri
|
|
|
81
85
|
placement: 'bottom',
|
|
82
86
|
variant: 'collapse',
|
|
83
87
|
trigger: false,
|
|
84
|
-
|
|
88
|
+
animation: false,
|
|
89
|
+
content: (_jsx(OptionsBase, { onToggleSelected: optionSelectHandler, loading: innerLoading.current, options: actualOptions, labelKey: labelKey, primaryKey: primaryKey, searchValue: innerValue.current, _optionsAlreadyFilter: true, children: children }))
|
|
85
90
|
}, popperProps, {
|
|
86
91
|
css: popperStyle,
|
|
87
92
|
open: open.current,
|
|
@@ -39,9 +39,9 @@ export const SearchResult = memo(({ primaryKey, labelKey, childrenKey, searchTok
|
|
|
39
39
|
if (!searchValue) {
|
|
40
40
|
return flattedOptions;
|
|
41
41
|
}
|
|
42
|
-
const
|
|
42
|
+
const split = searchValue.split(' ');
|
|
43
43
|
return flattedOptions.filter(({ searchToken }) => {
|
|
44
|
-
return
|
|
44
|
+
return split.some(k => {
|
|
45
45
|
return k && searchToken.toLowerCase().includes(k.toLowerCase());
|
|
46
46
|
});
|
|
47
47
|
});
|
|
@@ -140,18 +140,18 @@ export declare function ClickAway({ ref, container, eventType, onClickAway, disa
|
|
|
140
140
|
onFocusCapture: import("react").FocusEventHandler<HTMLDivElement>;
|
|
141
141
|
onBlur: import("react").FocusEventHandler<HTMLDivElement>;
|
|
142
142
|
onBlurCapture: import("react").FocusEventHandler<HTMLDivElement>;
|
|
143
|
-
onChange: import("react").
|
|
144
|
-
onChangeCapture: import("react").
|
|
143
|
+
onChange: import("react").ChangeEventHandler<HTMLDivElement, Element>;
|
|
144
|
+
onChangeCapture: import("react").ChangeEventHandler<HTMLDivElement, Element>;
|
|
145
145
|
onBeforeInput: import("react").InputEventHandler<HTMLDivElement>;
|
|
146
|
-
onBeforeInputCapture: import("react").
|
|
147
|
-
onInput: import("react").
|
|
148
|
-
onInputCapture: import("react").
|
|
149
|
-
onReset: import("react").
|
|
150
|
-
onResetCapture: import("react").
|
|
151
|
-
onSubmit: import("react").
|
|
152
|
-
onSubmitCapture: import("react").
|
|
153
|
-
onInvalid: import("react").
|
|
154
|
-
onInvalidCapture: import("react").
|
|
146
|
+
onBeforeInputCapture: import("react").InputEventHandler<HTMLDivElement>;
|
|
147
|
+
onInput: import("react").InputEventHandler<HTMLDivElement>;
|
|
148
|
+
onInputCapture: import("react").InputEventHandler<HTMLDivElement>;
|
|
149
|
+
onReset: import("react").ReactEventHandler<HTMLDivElement>;
|
|
150
|
+
onResetCapture: import("react").ReactEventHandler<HTMLDivElement>;
|
|
151
|
+
onSubmit: import("react").SubmitEventHandler<HTMLDivElement>;
|
|
152
|
+
onSubmitCapture: import("react").SubmitEventHandler<HTMLDivElement>;
|
|
153
|
+
onInvalid: import("react").ReactEventHandler<HTMLDivElement>;
|
|
154
|
+
onInvalidCapture: import("react").ReactEventHandler<HTMLDivElement>;
|
|
155
155
|
onLoad: import("react").ReactEventHandler<HTMLDivElement>;
|
|
156
156
|
onLoadCapture: import("react").ReactEventHandler<HTMLDivElement>;
|
|
157
157
|
onError: import("react").ReactEventHandler<HTMLDivElement>;
|
|
@@ -83,7 +83,8 @@ export const DataGridHead = memo(({ allowSelectAll, columnResizable, flattedColu
|
|
|
83
83
|
const sortable = sorter && !children?.length;
|
|
84
84
|
const isOrderingColumn = orderColumn === _key;
|
|
85
85
|
const currentOrderType = isOrderingColumn ? orderType : 'descend';
|
|
86
|
-
const
|
|
86
|
+
const filteredValue = formValue?.[_key];
|
|
87
|
+
const isFilteredColumn = !isUnset(filteredValue) && !(Array.isArray(filteredValue) && !filteredValue.length);
|
|
87
88
|
const filterButton = (_jsx(Button, { className: classes.filterButton, variant: "plain", color: isFilteredColumn ? 'primary' : 'text.placeholder', onClick: e => {
|
|
88
89
|
e.stopPropagation();
|
|
89
90
|
onFilterClick?.(_key, e);
|
|
@@ -22,7 +22,7 @@ export const FilterBubbleContent = memo(({ columnKey, columnFilterProps }) => {
|
|
|
22
22
|
return (_jsxs(_Fragment, { children: [_jsx(FormItem, { field: columnKey, children: 'control' in columnFilterProps
|
|
23
23
|
? columnFilterProps.control
|
|
24
24
|
: _jsx(FilterOptions, { ...columnFilterProps, onChange: () => {
|
|
25
|
-
|
|
25
|
+
columnFilterProps.multiple === false && setOpen(false);
|
|
26
26
|
} }) }), columnFilterProps.showResetButton !== false &&
|
|
27
27
|
_jsx(Flex, { gap: 6, justifyContent: "center", marginTop: 6, children: _jsx(Button, { variant: "text", onClick: () => {
|
|
28
28
|
formRef.current.resetField(columnKey);
|
|
@@ -74,7 +74,7 @@ export function useStyle({ color }) {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
&:not(:has([data-read-only=true]))[data-focused=true],
|
|
77
|
-
&:not(:has([data-read-only=true])):
|
|
77
|
+
&:not(:has([data-read-only=true])):focus-within {
|
|
78
78
|
&::before, &::after {
|
|
79
79
|
display: block;
|
|
80
80
|
animation: ${borderAnim} .4s ${easing.easeOut} forwards;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { Id } from '../../types';
|
|
3
|
+
import { MenuOptionType, OptionsBaseProps } from './optionsBase';
|
|
4
|
+
export declare function useFilterOptions<O extends MenuOptionType<V>, V extends Id = Id>({ searchValue, options, children, filterPredicate, labelKey, searchTokenKey, _optionsAlreadyFilter }: Pick<OptionsBaseProps<O, V>, 'searchValue' | 'children' | 'options' | 'filterPredicate' | 'labelKey' | 'searchTokenKey' | '_optionsAlreadyFilter'>): (O | ReactNode)[];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Children, isValidElement, useMemo } from 'react';
|
|
2
|
+
export function useFilterOptions({ searchValue, options, children, filterPredicate, labelKey = 'label', searchTokenKey = 'searchToken', _optionsAlreadyFilter }) {
|
|
3
|
+
return useMemo(() => {
|
|
4
|
+
if (_optionsAlreadyFilter) {
|
|
5
|
+
return options || Children.toArray(children);
|
|
6
|
+
}
|
|
7
|
+
const trimmedSearchValue = searchValue?.trim();
|
|
8
|
+
if (!trimmedSearchValue) {
|
|
9
|
+
return options || Children.toArray(children);
|
|
10
|
+
}
|
|
11
|
+
const splitValue = trimmedSearchValue.split(' ');
|
|
12
|
+
const filterFn = (opt, index) => {
|
|
13
|
+
let ret = false;
|
|
14
|
+
if (filterPredicate) {
|
|
15
|
+
ret = filterPredicate(trimmedSearchValue, opt, index);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
const searchToken = typeof opt[labelKey] === 'string' ? opt[labelKey] : opt[searchTokenKey];
|
|
19
|
+
if (typeof searchToken === 'string') {
|
|
20
|
+
ret = splitValue.some(k => {
|
|
21
|
+
return k && searchToken.toLowerCase().includes(k.toLowerCase());
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return ret;
|
|
26
|
+
};
|
|
27
|
+
return options
|
|
28
|
+
? options.filter(filterFn)
|
|
29
|
+
: Children.toArray(children).filter((c, index) => {
|
|
30
|
+
return isValidElement(c) && filterFn(c.props, index);
|
|
31
|
+
});
|
|
32
|
+
}, [searchValue, filterPredicate, options, children, labelKey, searchTokenKey, _optionsAlreadyFilter]);
|
|
33
|
+
}
|
|
@@ -27,5 +27,10 @@ export interface OptionsBaseProps<O extends MenuOptionType<V>, V extends Id = Id
|
|
|
27
27
|
searchValue?: string;
|
|
28
28
|
selectedValue?: V | V[];
|
|
29
29
|
onToggleSelected?(value: V, e: KeyboardEvent | React.MouseEvent<HTMLDivElement>): void;
|
|
30
|
+
/**
|
|
31
|
+
* @private
|
|
32
|
+
* 内部使用,传入的选项是否已经经过筛选
|
|
33
|
+
*/
|
|
34
|
+
_optionsAlreadyFilter?: boolean;
|
|
30
35
|
}
|
|
31
36
|
export declare const OptionsBase: <O extends MenuOptionType<V>, V extends Id = Id>(props: OptionsBaseProps<O, V>) => ReactElement;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
2
|
-
import { useMemo, memo,
|
|
2
|
+
import { useMemo, memo, isValidElement, cloneElement, useRef } from 'react';
|
|
3
3
|
import { Highlight } from '../highlight';
|
|
4
4
|
import { MenuItem } from '../menuItem';
|
|
5
5
|
import { Placeholder } from '../placeholder';
|
|
@@ -7,39 +7,14 @@ import { clsx, isSelected, mergeComponentProps, useKeyboard, useSync } from '../
|
|
|
7
7
|
import { classes, style } from './optionsBase.style';
|
|
8
8
|
import { Loading } from '../loading';
|
|
9
9
|
import { usePopperContext, useScrollToTarget } from '../popper';
|
|
10
|
+
import { useFilterOptions } from './filterOptions';
|
|
10
11
|
export const OptionsBase = memo(({
|
|
11
12
|
// 共享属性
|
|
12
13
|
showCheckbox, loading, options, children, labelKey = 'label', primaryKey = 'value', searchTokenKey = 'searchToken', filterPredicate,
|
|
13
14
|
// 以下为非共享属性
|
|
14
|
-
searchValue, selectedValue, onToggleSelected, ...props }) => {
|
|
15
|
+
searchValue, selectedValue, onToggleSelected, _optionsAlreadyFilter, ...props }) => {
|
|
15
16
|
const { open, setOpen } = usePopperContext();
|
|
16
|
-
const filteredOptions =
|
|
17
|
-
const trimmedSearchValue = searchValue?.trim();
|
|
18
|
-
if (!trimmedSearchValue) {
|
|
19
|
-
return options || Children.toArray(children);
|
|
20
|
-
}
|
|
21
|
-
const splitedValue = trimmedSearchValue.split(' ');
|
|
22
|
-
const filterFn = (opt, index) => {
|
|
23
|
-
let ret = false;
|
|
24
|
-
if (filterPredicate) {
|
|
25
|
-
ret = filterPredicate(trimmedSearchValue, opt, index);
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
const searchToken = typeof opt[labelKey] === 'string' ? opt[labelKey] : opt[searchTokenKey];
|
|
29
|
-
if (typeof searchToken === 'string') {
|
|
30
|
-
ret = splitedValue.some(k => {
|
|
31
|
-
return k && searchToken.toLowerCase().includes(k.toLowerCase());
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return ret;
|
|
36
|
-
};
|
|
37
|
-
return options
|
|
38
|
-
? options.filter(filterFn)
|
|
39
|
-
: Children.toArray(children).filter((c, index) => {
|
|
40
|
-
return isValidElement(c) && filterFn(c.props, index);
|
|
41
|
-
});
|
|
42
|
-
}, [searchValue, filterPredicate, options, children, labelKey, searchTokenKey]);
|
|
17
|
+
const filteredOptions = useFilterOptions({ searchValue, filterPredicate, options, children, labelKey, searchTokenKey, _optionsAlreadyFilter });
|
|
43
18
|
/**
|
|
44
19
|
* ------------------------------------------------------------------
|
|
45
20
|
* 键盘控制
|
|
@@ -28,7 +28,7 @@ export interface PopperProps extends Omit<DivProps, 'content' | 'children'> {
|
|
|
28
28
|
sizeAdaptable?: boolean;
|
|
29
29
|
/** trigger{@link trigger}包含"hover"时,鼠标移入移的延迟时间,默认为`150(ms)` */
|
|
30
30
|
mouseEnterDelay?: number;
|
|
31
|
-
|
|
31
|
+
/** 默认为`150(ms)` */
|
|
32
32
|
mouseLeaveDelay?: number;
|
|
33
33
|
defaultOpen?: boolean;
|
|
34
34
|
open?: boolean;
|
|
@@ -43,6 +43,8 @@ export interface PopperProps extends Omit<DivProps, 'content' | 'children'> {
|
|
|
43
43
|
* @enum {undefined} 第一次打开时渲染,跟随父组件销毁。
|
|
44
44
|
*/
|
|
45
45
|
forceRender?: boolean;
|
|
46
|
+
/** 打开与关闭是否渲染过度动画,默认为`true` */
|
|
47
|
+
animation?: boolean;
|
|
46
48
|
children?: ReactElement<any>;
|
|
47
49
|
}
|
|
48
50
|
export interface PopperRef extends HTMLDivElement {
|
|
@@ -51,4 +53,4 @@ export interface PopperRef extends HTMLDivElement {
|
|
|
51
53
|
openAnimation?: boolean;
|
|
52
54
|
}, beforeOpen?: () => void): void;
|
|
53
55
|
}
|
|
54
|
-
export declare function Popper({ ref, popperRef, anchorElement, container, effectContainer, content, offset, trigger, clickToClose, placement, variant, sizeAdaptable, mouseEnterDelay, mouseLeaveDelay, defaultOpen, open, onOpenChange, onOpenChangeEnd, disabled, autoClose, forceRender, children, ...props }: PopperProps): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
56
|
+
export declare function Popper({ ref, popperRef, anchorElement, container, effectContainer, content, offset, trigger, clickToClose, placement, variant, sizeAdaptable, mouseEnterDelay, mouseLeaveDelay, defaultOpen, open, onOpenChange, onOpenChangeEnd, disabled, autoClose, forceRender, animation, children, ...props }: PopperProps): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
@@ -19,7 +19,7 @@ const getAttemptOrder = (placement) => {
|
|
|
19
19
|
}
|
|
20
20
|
return order;
|
|
21
21
|
};
|
|
22
|
-
export function Popper({ ref, popperRef, anchorElement, container, effectContainer, content, offset, trigger = 'hover', clickToClose, placement = 'top', variant = 'zoom', sizeAdaptable = variant === 'collapse', mouseEnterDelay = 150, mouseLeaveDelay = 150, defaultOpen = false, open, onOpenChange, onOpenChangeEnd, disabled, autoClose = false, forceRender, children, ...props }) {
|
|
22
|
+
export function Popper({ ref, popperRef, anchorElement, container, effectContainer, content, offset, trigger = 'hover', clickToClose, placement = 'top', variant = 'zoom', sizeAdaptable = variant === 'collapse', mouseEnterDelay = 150, mouseLeaveDelay = 150, defaultOpen = false, open, onOpenChange, onOpenChangeEnd, disabled, autoClose = false, forceRender, animation = true, children, ...props }) {
|
|
23
23
|
const { spacing } = useTheme();
|
|
24
24
|
offset ??= spacing[2];
|
|
25
25
|
useImperativeHandle(popperRef, () => {
|
|
@@ -52,6 +52,8 @@ export function Popper({ ref, popperRef, anchorElement, container, effectContain
|
|
|
52
52
|
if (newOpen || openHolding.current === 0) {
|
|
53
53
|
_setInnerOpen(newOpen);
|
|
54
54
|
}
|
|
55
|
+
// 不渲染动画时,需要手动触发onTransitionEnd
|
|
56
|
+
!animation && transitionEndHandler();
|
|
55
57
|
};
|
|
56
58
|
const { onChildrenOpenChange: tellParentOpenChange } = usePopperContext();
|
|
57
59
|
useUpdateEffect(() => {
|
|
@@ -82,6 +84,9 @@ export function Popper({ ref, popperRef, anchorElement, container, effectContain
|
|
|
82
84
|
const animating = useRef(false);
|
|
83
85
|
const onTransitionEnd = (e) => {
|
|
84
86
|
props.onTransitionEnd?.(e);
|
|
87
|
+
transitionEndHandler();
|
|
88
|
+
};
|
|
89
|
+
const transitionEndHandler = () => {
|
|
85
90
|
onOpenChangeEnd?.(innerOpen.current);
|
|
86
91
|
if (forceRender === false && !innerOpen.current) {
|
|
87
92
|
renderedOnce.current = false;
|
|
@@ -538,5 +543,5 @@ export function Popper({ ref, popperRef, anchorElement, container, effectContain
|
|
|
538
543
|
transform: 'scale(1)'
|
|
539
544
|
},
|
|
540
545
|
...props.style
|
|
541
|
-
}, "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)] }));
|
|
546
|
+
}, "data-open": innerOpen.current, "data-variant": variant, "data-place-a": placeA.current, "data-place-b": placeB.current, "data-animation": animation, onTransitionEnd: onTransitionEnd, children: _jsx(PopperContext, { value: contextValue, children: content }) }) }), containerEl.current)] }));
|
|
542
547
|
}
|
|
@@ -16,7 +16,10 @@ export const style = defineCss(theme => {
|
|
|
16
16
|
left: 0;
|
|
17
17
|
z-index: ${zIndex.popper};
|
|
18
18
|
transition-property: transform, opacity;
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
&[data-animation=true] {
|
|
21
|
+
transition-duration: .25s;
|
|
22
|
+
}
|
|
20
23
|
|
|
21
24
|
&[data-open=true] {
|
|
22
25
|
transition-timing-function: ${easing.bounce}, ${easing.easeOut};
|