@canlooks/can-ui 0.0.144 → 0.0.146
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/appActionSheet.js +42 -41
- package/dist/cjs/components/app/appDialog.js +31 -32
- 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/form/formItem.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/components/snackbarBase/snackbarBase.js +1 -1
- package/dist/cjs/components/upload/upload.js +1 -1
- package/dist/cjs/utils/utils.d.ts +2 -8
- package/dist/cjs/utils/utils.js +9 -23
- package/dist/esm/components/app/appActionSheet.js +38 -37
- package/dist/esm/components/app/appDialog.js +27 -28
- 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/form/formItem.js +2 -2
- 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/components/snackbarBase/snackbarBase.js +2 -2
- package/dist/esm/components/upload/upload.js +2 -2
- package/dist/esm/utils/utils.d.ts +2 -8
- package/dist/esm/utils/utils.js +8 -21
- package/package.json +1 -4
- 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
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
2
|
+
import { createElement as _createElement } from "@emotion/react";
|
|
2
3
|
import { isValidElement, memo, useState } from 'react';
|
|
3
4
|
import { ActionSheet } from '../actionSheet';
|
|
5
|
+
import { getRandomId } from '../../utils';
|
|
4
6
|
export class AppActionSheetMethods {
|
|
5
7
|
async confirm() {
|
|
6
8
|
}
|
|
@@ -9,45 +11,44 @@ export class AppActionSheetMethods {
|
|
|
9
11
|
}
|
|
10
12
|
export const AppActionSheet = memo(({ methods }) => {
|
|
11
13
|
const [stacks, setStacks] = useState([]);
|
|
12
|
-
const defineMethods = (type) =>
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
14
|
+
const defineMethods = (type) => {
|
|
15
|
+
return (params, ...args) => {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
const props = typeof params !== 'object' || isValidElement(params)
|
|
18
|
+
? { title: params }
|
|
19
|
+
: params;
|
|
20
|
+
const key = getRandomId();
|
|
21
|
+
setStacks(o => [
|
|
22
|
+
...o,
|
|
23
|
+
{
|
|
24
|
+
...props,
|
|
25
|
+
key,
|
|
26
|
+
type,
|
|
27
|
+
onAction(action) {
|
|
28
|
+
props?.onAction?.(action, ...args);
|
|
29
|
+
resolve(action);
|
|
30
|
+
},
|
|
31
|
+
onConfirm() {
|
|
32
|
+
props?.onConfirm?.(...args);
|
|
33
|
+
resolve(void 0);
|
|
34
|
+
},
|
|
35
|
+
onCancel(e) {
|
|
36
|
+
props?.onCancel?.(e);
|
|
37
|
+
reject();
|
|
38
|
+
},
|
|
39
|
+
onClosed() {
|
|
40
|
+
props?.onClosed?.();
|
|
41
|
+
setStacks(stacks => stacks.filter(stack => stack.key !== key));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
]);
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
};
|
|
43
48
|
methods.confirm = defineMethods('confirm');
|
|
44
49
|
methods.open = defineMethods('open');
|
|
45
|
-
return stacks.map(
|
|
50
|
+
return stacks.map(p => _createElement(AppActionSheetStack, { ...p, key: p.key }));
|
|
46
51
|
});
|
|
47
52
|
const AppActionSheetStack = memo(({ type, ...props }) => {
|
|
48
|
-
|
|
49
|
-
return (_jsx(ActionSheet, { showConfirm: type === 'confirm', ...props, open: open, onClose: reason => {
|
|
50
|
-
props.onClose?.(reason);
|
|
51
|
-
setOpen(false);
|
|
52
|
-
} }));
|
|
53
|
+
return (_jsx(ActionSheet, { showConfirm: type === 'confirm', defaultOpen: true, ...props }));
|
|
53
54
|
});
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
2
|
+
import { createElement as _createElement } from "@emotion/react";
|
|
2
3
|
import { memo, useState } from 'react';
|
|
3
4
|
import { Dialog } from '../dialog';
|
|
4
5
|
import { StatusIcon } from '../status';
|
|
6
|
+
import { getRandomId } from '../../utils';
|
|
5
7
|
export class AppDialogMethods {
|
|
6
8
|
async info(props, ...args) {
|
|
7
9
|
}
|
|
@@ -19,28 +21,29 @@ export const AppDialog = memo(({ methods }) => {
|
|
|
19
21
|
const defineMethod = (type) => {
|
|
20
22
|
return (props, ...args) => {
|
|
21
23
|
return new Promise((resolve, reject) => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
...
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
24
|
+
const key = getRandomId();
|
|
25
|
+
setStacks(o => {
|
|
26
|
+
return [
|
|
27
|
+
...o,
|
|
28
|
+
{
|
|
29
|
+
...props,
|
|
30
|
+
key,
|
|
31
|
+
type,
|
|
32
|
+
onConfirm: async () => {
|
|
33
|
+
await props.onConfirm?.(...args);
|
|
34
|
+
resolve();
|
|
35
|
+
},
|
|
36
|
+
onCancel: () => {
|
|
37
|
+
props.onCancel?.(...args);
|
|
38
|
+
reject();
|
|
39
|
+
},
|
|
40
|
+
onClosed: () => {
|
|
41
|
+
props.onClosed?.();
|
|
42
|
+
setStacks(stacks => stacks.filter(stack => stack.key !== key));
|
|
43
|
+
}
|
|
41
44
|
}
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
];
|
|
46
|
+
});
|
|
44
47
|
});
|
|
45
48
|
};
|
|
46
49
|
};
|
|
@@ -49,14 +52,10 @@ export const AppDialog = memo(({ methods }) => {
|
|
|
49
52
|
methods.warning = defineMethod('warning');
|
|
50
53
|
methods.error = defineMethod('error');
|
|
51
54
|
methods.confirm = defineMethod('confirm');
|
|
52
|
-
return stacks.map(
|
|
53
|
-
return
|
|
55
|
+
return stacks.map(p => {
|
|
56
|
+
return _createElement(AppDialogStack, { ...p, key: p.key });
|
|
54
57
|
});
|
|
55
58
|
});
|
|
56
59
|
const AppDialogStack = memo(({ type, content, ...props }) => {
|
|
57
|
-
|
|
58
|
-
return (_jsx(Dialog, { width: 360, maskClosable: false, icon: _jsx(StatusIcon, { status: type }), showCancel: type === 'confirm', showClose: false, confirmText: type === 'confirm' ? void 0 : '知道了', ...props, open: open, onClose: reason => {
|
|
59
|
-
props.onClose?.(reason);
|
|
60
|
-
setOpen(false);
|
|
61
|
-
}, children: content }));
|
|
60
|
+
return (_jsx(Dialog, { width: 360, maskClosable: false, icon: _jsx(StatusIcon, { status: type }), showCancel: type === 'confirm', showClose: false, confirmText: type === 'confirm' ? void 0 : '知道了', defaultOpen: true, ...props, children: content }));
|
|
62
61
|
});
|
|
@@ -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>;
|
|
@@ -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, useEffect, useImperativeHandle, useMemo, useRef } from 'react';
|
|
3
3
|
import { useFormContext, useFormStyleContext, useFormValueContext } from './form';
|
|
4
|
-
import { clsx, getValueOnChange, queryDeep, stringifyField, useDerivedState, toArray,
|
|
4
|
+
import { clsx, getValueOnChange, queryDeep, stringifyField, useDerivedState, toArray, getRandomId, isUnset, useStrictMemo } from '../../utils';
|
|
5
5
|
import { DescriptionItem } from '../descriptions';
|
|
6
6
|
import { classes } from './form.style';
|
|
7
7
|
import { Collapse } from '../transitionBase';
|
|
@@ -134,7 +134,7 @@ export const FormItem = ({ ref, wrapperRef, field, initialValue, label = '', rul
|
|
|
134
134
|
}, [rules, required]);
|
|
135
135
|
const [randomKey] = useDerivedState(prev => {
|
|
136
136
|
// fieldValue变为undefined时,需要更新key以强制重渲染组件
|
|
137
|
-
return !prev || typeof fieldValue === 'undefined' ?
|
|
137
|
+
return !prev || typeof fieldValue === 'undefined' ? getRandomId() : prev;
|
|
138
138
|
}, [fieldValue]);
|
|
139
139
|
const renderedChildren = useMemo(() => {
|
|
140
140
|
if (typeof children === 'function') {
|
|
@@ -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};
|
|
@@ -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, useRef, useState } from 'react';
|
|
4
4
|
import { Collapse, Slide } from '../transitionBase';
|
|
5
|
-
import { clsx,
|
|
5
|
+
import { clsx, getRandomId, useColor, useContainer, useUnmounted } from '../../utils';
|
|
6
6
|
import { classes, style } from './snackbarBase.style';
|
|
7
7
|
import { TransitionGroup } from 'react-transition-group';
|
|
8
8
|
import { StatusIcon, statusMapToIconDefinition } from '../status';
|
|
@@ -43,7 +43,7 @@ export const SnackbarBase = memo(({ methods, useTo, max = useTo === 'message' ?
|
|
|
43
43
|
: { content: props };
|
|
44
44
|
const { placement = useTo === 'message' ? 'top' : 'topRight', duration = useTo === 'message' ? 3000 : 5000, ...restProps } = propsObject;
|
|
45
45
|
const index = placementToIndex[placement];
|
|
46
|
-
let id =
|
|
46
|
+
let id = getRandomId();
|
|
47
47
|
const onCloseButtonClick = () => {
|
|
48
48
|
!isUnmounted.current && setStacks(o => {
|
|
49
49
|
o[index] = o[index].filter(s => s.id !== id);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
2
2
|
import { memo, useImperativeHandle, useRef } from 'react';
|
|
3
3
|
import { classes, style } from './upload.style';
|
|
4
|
-
import { clsx,
|
|
4
|
+
import { clsx, getRandomId, onDndDragEnd, useControlled, useDndSensors, mergeComponentProps } from '../../utils';
|
|
5
5
|
import { Button } from '../button';
|
|
6
6
|
import { FileItem } from './fileItem';
|
|
7
7
|
import { TransitionGroup } from 'react-transition-group';
|
|
@@ -17,7 +17,7 @@ import { faUpload } from '@fortawesome/free-solid-svg-icons/faUpload';
|
|
|
17
17
|
const markFileId = (files) => {
|
|
18
18
|
if (files) {
|
|
19
19
|
for (const file of files) {
|
|
20
|
-
file.id ||=
|
|
20
|
+
file.id ||= getRandomId();
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
};
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
import { Ref, ReactNode, ElementType, ComponentProps } from 'react';
|
|
2
2
|
import { Id, Obj } from '../types';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
* @param namespace
|
|
4
|
+
* 获取UUID
|
|
6
5
|
*/
|
|
7
|
-
export declare function
|
|
8
|
-
/**
|
|
9
|
-
* 获取任意长度由随机字母组成的ID
|
|
10
|
-
* @param length
|
|
11
|
-
*/
|
|
12
|
-
export declare function getShortID(length?: number): string;
|
|
6
|
+
export declare function getRandomId(): `${string}-${string}-${string}-${string}-${string}`;
|
|
13
7
|
/**
|
|
14
8
|
* 拼接元素的类名
|
|
15
9
|
* @param classes
|
package/dist/esm/utils/utils.js
CHANGED
|
@@ -1,22 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* @param namespace
|
|
2
|
+
* 获取UUID
|
|
4
3
|
*/
|
|
5
|
-
export function
|
|
6
|
-
return
|
|
7
|
-
}
|
|
8
|
-
const randomIdAlphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-';
|
|
9
|
-
/**
|
|
10
|
-
* 获取任意长度由随机字母组成的ID
|
|
11
|
-
* @param length
|
|
12
|
-
*/
|
|
13
|
-
export function getShortID(length = 8) {
|
|
14
|
-
const { length: alphabetLength } = randomIdAlphabet;
|
|
15
|
-
let id = '';
|
|
16
|
-
while (length--) {
|
|
17
|
-
id += randomIdAlphabet[Math.floor(Math.random() * alphabetLength)];
|
|
18
|
-
}
|
|
19
|
-
return id;
|
|
4
|
+
export function getRandomId() {
|
|
5
|
+
return crypto.randomUUID();
|
|
20
6
|
}
|
|
21
7
|
/**
|
|
22
8
|
* 拼接元素的类名
|
|
@@ -387,11 +373,12 @@ export function mergeComponentProps(...props) {
|
|
|
387
373
|
target.style = { ...source.style, ...target.style };
|
|
388
374
|
continue;
|
|
389
375
|
default:
|
|
390
|
-
const
|
|
391
|
-
if (typeof
|
|
376
|
+
const sourceFn = source[p];
|
|
377
|
+
if (typeof sourceFn === 'function') {
|
|
378
|
+
const targetFn = target[p];
|
|
392
379
|
target[p] = (...args) => {
|
|
393
|
-
|
|
394
|
-
|
|
380
|
+
targetFn(...args);
|
|
381
|
+
sourceFn(...args);
|
|
395
382
|
};
|
|
396
383
|
continue;
|
|
397
384
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canlooks/can-ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.146",
|
|
4
4
|
"author": "C.CanLiang <canlooks@gmail.com>",
|
|
5
5
|
"description": "My ui framework",
|
|
6
6
|
"license": "MIT",
|
|
@@ -20,9 +20,6 @@
|
|
|
20
20
|
"url": "https://github.com/canlooks/canui/issues",
|
|
21
21
|
"email": "canlooks@gmail.com"
|
|
22
22
|
},
|
|
23
|
-
"bin": {
|
|
24
|
-
"can-ui-doc": "documentation/bootstrap.mjs"
|
|
25
|
-
},
|
|
26
23
|
"main": "dist/cjs/index.js",
|
|
27
24
|
"module": "dist/esm/index.js",
|
|
28
25
|
"types": "dist/esm/index.d.ts",
|