@canlooks/can-ui 0.0.175 → 0.0.177
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 +1 -1
- package/dist/cjs/components/app/app.d.ts +2 -1
- package/dist/cjs/components/app/app.js +7 -12
- package/dist/cjs/components/autocomplete/autocomplete.js +2 -2
- package/dist/cjs/components/form/form.d.ts +2 -3
- package/dist/cjs/components/form/form.js +1 -1
- package/dist/cjs/components/waterfall/waterfall.js +1 -1
- package/dist/cjs/extensions/reactiveForm/reactiveFormItem.js +4 -0
- package/dist/cjs/utils/hooks.d.ts +5 -5
- package/dist/cjs/utils/hooks.js +32 -22
- package/dist/esm/components/anchorList/anchorList.js +2 -2
- package/dist/esm/components/app/app.d.ts +2 -1
- package/dist/esm/components/app/app.js +8 -13
- package/dist/esm/components/autocomplete/autocomplete.js +2 -2
- package/dist/esm/components/form/form.d.ts +2 -3
- package/dist/esm/components/form/form.js +1 -1
- package/dist/esm/components/waterfall/waterfall.js +2 -2
- package/dist/esm/extensions/reactiveForm/reactiveFormItem.js +4 -0
- package/dist/esm/utils/hooks.d.ts +5 -5
- package/dist/esm/utils/hooks.js +32 -22
- package/package.json +1 -1
|
@@ -14,7 +14,7 @@ exports.AnchorList = (0, react_1.memo)(({ anchors, renderAnchorItem, indent = 24
|
|
|
14
14
|
* 初始化高亮与滚动位置
|
|
15
15
|
*/
|
|
16
16
|
const mounted = (0, react_1.useRef)(false);
|
|
17
|
-
(0,
|
|
17
|
+
(0, react_1.useEffect)(() => {
|
|
18
18
|
if (routeMode === 'history') {
|
|
19
19
|
mounted.current ||= scrollToId(location.hash.slice(1));
|
|
20
20
|
}
|
|
@@ -15,10 +15,11 @@ export declare function useAppContext(): {
|
|
|
15
15
|
notification: AppNotificationMethods<import("./appNotification").AppNotificationProps>;
|
|
16
16
|
actionSheet: AppActionSheetMethods;
|
|
17
17
|
};
|
|
18
|
-
export
|
|
18
|
+
export type AppMethods = {
|
|
19
19
|
dialog: AppDialogMethods;
|
|
20
20
|
message: AppMessageMethods;
|
|
21
21
|
notification: AppNotificationMethods;
|
|
22
22
|
actionSheet: AppActionSheetMethods;
|
|
23
23
|
};
|
|
24
|
+
export declare const App: OverridableComponent<AppOwnProps> & AppMethods;
|
|
24
25
|
export declare function InnerApp({ component: Component, theme, children, fill, ...props }: OverridableProps<AppProps, 'div'>): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
@@ -27,17 +27,12 @@ exports.App = (({ theme, ...props }) => {
|
|
|
27
27
|
return ((0, jsx_runtime_1.jsx)(globalEventDelegation_1.GlobalEventDelegation, { children: (0, jsx_runtime_1.jsx)(theme_1.ThemeProvider, { theme: theme, children: (0, jsx_runtime_1.jsx)(InnerApp, { ...props }) }) }));
|
|
28
28
|
});
|
|
29
29
|
function InnerApp({ component: Component = 'div', theme, children, fill = true, ...props }) {
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
exports.App.dialog ||= appValue.dialog;
|
|
37
|
-
exports.App.message ||= appValue.message;
|
|
38
|
-
exports.App.notification ||= appValue.notification;
|
|
39
|
-
exports.App.actionSheet ||= appValue.actionSheet;
|
|
40
|
-
return ((0, jsx_runtime_1.jsxs)(AppContext, { value: appValue, children: [Component
|
|
30
|
+
const appContext = useAppContext();
|
|
31
|
+
exports.App.dialog = appContext.dialog;
|
|
32
|
+
exports.App.message = appContext.message;
|
|
33
|
+
exports.App.notification = appContext.notification;
|
|
34
|
+
exports.App.actionSheet = appContext.actionSheet;
|
|
35
|
+
return ((0, jsx_runtime_1.jsxs)(AppContext, { value: appContext, children: [Component
|
|
41
36
|
? (0, jsx_runtime_1.jsx)(Component, { ...props, css: [
|
|
42
37
|
app_style_1.style,
|
|
43
38
|
(0, utils_1.defineCss)(({ background }) => (0, react_2.css) `
|
|
@@ -49,5 +44,5 @@ function InnerApp({ component: Component = 'div', theme, children, fill = true,
|
|
|
49
44
|
flex: 1;
|
|
50
45
|
`
|
|
51
46
|
], className: (0, utils_1.clsx)(app_style_1.classes.root, props.className), children: children })
|
|
52
|
-
: children, (0, jsx_runtime_1.jsx)(appDialog_1.AppDialog, { methods:
|
|
47
|
+
: children, (0, jsx_runtime_1.jsx)(appDialog_1.AppDialog, { methods: appContext.dialog }), (0, jsx_runtime_1.jsx)(appMessage_1.AppMessage, { methods: appContext.message }), (0, jsx_runtime_1.jsx)(appNotification_1.AppNotification, { methods: appContext.notification }), (0, jsx_runtime_1.jsx)(appActionSheet_1.AppActionSheet, { methods: appContext.actionSheet })] }));
|
|
53
48
|
}
|
|
@@ -17,7 +17,7 @@ exports.Autocomplete = (0, react_1.memo)(({ children, loading, options, loadOpti
|
|
|
17
17
|
};
|
|
18
18
|
const [innerValue, setInnerValue] = (0, utils_1.useControlled)(defaultValue, value);
|
|
19
19
|
const changedBySelect = (0, react_1.useRef)(false);
|
|
20
|
-
const changeHandler = (e, isSelect
|
|
20
|
+
const changeHandler = (e, isSelect) => {
|
|
21
21
|
changedBySelect.current = isSelect;
|
|
22
22
|
onChange?.(e);
|
|
23
23
|
setInnerValue(e.target.value);
|
|
@@ -80,7 +80,7 @@ exports.Autocomplete = (0, react_1.memo)(({ children, loading, options, loadOpti
|
|
|
80
80
|
className: autocomplete_style_1.classes.root,
|
|
81
81
|
loading: innerLoading.current,
|
|
82
82
|
value: innerValue.current,
|
|
83
|
-
onChange: changeHandler,
|
|
83
|
+
onChange: e => changeHandler(e, false),
|
|
84
84
|
onFocus: () => setFocused(true),
|
|
85
85
|
onBlur: () => setFocused(false)
|
|
86
86
|
});
|
|
@@ -19,7 +19,7 @@ interface FormOwnProps<V extends FormValue = FormValue> extends FormSharedProps,
|
|
|
19
19
|
wrapperRef?: Ref<HTMLFormElement>;
|
|
20
20
|
initialValue?: V;
|
|
21
21
|
onChange?(field: FieldPath, value: any, formValue: V): void;
|
|
22
|
-
onFinish?(value: V):
|
|
22
|
+
onFinish?(value: V): any;
|
|
23
23
|
items?: (FormItemProps & Obj)[];
|
|
24
24
|
descriptionsProps?: DescriptionsProps;
|
|
25
25
|
}
|
|
@@ -39,8 +39,7 @@ declare const FormValueContext: React.Context<FormValueContext<any>>;
|
|
|
39
39
|
export declare function useFormValueContext<V extends FormValue>(): FormValueContext<V>;
|
|
40
40
|
export declare function useFormStyleContext(): FormSharedProps;
|
|
41
41
|
export type FormRef<V extends FormValue = FormValue> = {
|
|
42
|
-
|
|
43
|
-
submit(): Promise<V | null>;
|
|
42
|
+
submit(): Promise<V>;
|
|
44
43
|
getFieldValue<T = any>(field: FieldPath): T;
|
|
45
44
|
getFormValue(): V;
|
|
46
45
|
getFieldError(field: FieldPath): FieldError | undefined;
|
|
@@ -81,7 +81,7 @@ inline, columnCount = 1, gap, columnGap, rowGap, ...props }) => {
|
|
|
81
81
|
await Promise.all([...itemsContainer.current].map(async ([field, item]) => {
|
|
82
82
|
return await item.validate() || Promise.reject(new TypeError(`Invalid field: "${field}"`));
|
|
83
83
|
}));
|
|
84
|
-
onFinish?.(formValue.current);
|
|
84
|
+
await onFinish?.(formValue.current);
|
|
85
85
|
return formValue.current;
|
|
86
86
|
};
|
|
87
87
|
const formRef = (0, react_1.useRef)(null);
|
|
@@ -33,7 +33,7 @@ const Waterfall = ({ columnCount = { xs: 4 }, gap = 0, columnGap, rowGap, ...pro
|
|
|
33
33
|
});
|
|
34
34
|
});
|
|
35
35
|
(0, utils_1.useUpdateEffect)(computeItemOrder, [columnCountNum.current]);
|
|
36
|
-
(0, utils_1.
|
|
36
|
+
(0, utils_1.useUnmounted)(() => {
|
|
37
37
|
resizeObserver.current.disconnect();
|
|
38
38
|
});
|
|
39
39
|
return ((0, jsx_runtime_1.jsx)("div", { ...props, ref: (0, utils_1.cloneRef)(containerRef, props.ref), css: (0, waterfall_style_1.useStyle)({ columnCount, columnGap, rowGap }), className: (0, utils_1.clsx)(waterfall_style_1.classes.root, props.className), children: react_1.Children.map(props.children, child => {
|
|
@@ -26,6 +26,10 @@ function InnerFormItem({ dependencies, checked, value, onChange, ...props }) {
|
|
|
26
26
|
props.children.props?.onChange?.(e);
|
|
27
27
|
onChange?.(e);
|
|
28
28
|
context.onChange?.();
|
|
29
|
+
},
|
|
30
|
+
onkeydown(e) {
|
|
31
|
+
e.preventDefault();
|
|
32
|
+
props.children.props?.onkeydown?.(e);
|
|
29
33
|
}
|
|
30
34
|
};
|
|
31
35
|
return ((0, jsx_runtime_1.jsx)(form_1.FormItem, { ...props, ref: (0, utils_1.cloneRef)(formItemRef, props.ref), _fieldValue: checked ?? value, children: (_, styleProps, key) => {
|
|
@@ -24,10 +24,10 @@ export declare function useDerivedState<T>(referredState: (prevState: T | undefi
|
|
|
24
24
|
export declare function useDerivedState<T>(referredState: T, deps?: any[]): [RefObject<T>, Dispatch<SetStateAction<T>>];
|
|
25
25
|
export declare function useMounted(): void;
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
28
|
-
* @
|
|
27
|
+
* 得到一个RefObject,用于判断组件是否卸载
|
|
28
|
+
* @param onUnmount 回调函数,卸载时触发
|
|
29
29
|
*/
|
|
30
|
-
export declare function useUnmounted(): RefObject<boolean>;
|
|
30
|
+
export declare function useUnmounted(onUnmount?: () => void): RefObject<boolean>;
|
|
31
31
|
/**
|
|
32
32
|
* 处理受控组件的外部属性与内部属性
|
|
33
33
|
* @param defaultValue
|
|
@@ -55,7 +55,7 @@ export declare function useContainer<T extends HTMLElement | null>(container?: D
|
|
|
55
55
|
/**
|
|
56
56
|
* 使用外部类,该方法可避免`StrictMode`下,React渲染行为与外部类实例生命周期不同步的问题
|
|
57
57
|
*/
|
|
58
|
-
export declare function useExternalClass<T>(setup: () => T, cleanup?: (instance: T) => void): T
|
|
58
|
+
export declare function useExternalClass<T>(setup: () => T, cleanup?: (instance: T) => void): RefObject<T>;
|
|
59
59
|
/**
|
|
60
60
|
* 用法同{@link useEffect},但StrictMode下不会执行两次
|
|
61
61
|
*/
|
|
@@ -67,4 +67,4 @@ export declare function useUpdateEffect(effect: EffectCallback, deps?: Dependenc
|
|
|
67
67
|
/**
|
|
68
68
|
* 用法同{@link useMemo},但StrictMode下不会执行两次
|
|
69
69
|
*/
|
|
70
|
-
export declare function useStrictMemo<T>(factory: () => T, deps
|
|
70
|
+
export declare function useStrictMemo<T>(factory: () => T, deps: DependencyList): T | undefined;
|
package/dist/cjs/utils/hooks.js
CHANGED
|
@@ -47,7 +47,7 @@ function useForceUpdate() {
|
|
|
47
47
|
function useDerivedState(referredState, deps) {
|
|
48
48
|
const derivedState = (0, react_1.useRef)(void 0);
|
|
49
49
|
(0, react_1.useMemo)(() => {
|
|
50
|
-
// StrictMode
|
|
50
|
+
// StrictMode下,需要重置2次,使prevState保持正确
|
|
51
51
|
derivedState.current = void 0;
|
|
52
52
|
}, []);
|
|
53
53
|
const updateState = (state) => {
|
|
@@ -73,14 +73,21 @@ function useDerivedState(referredState, deps) {
|
|
|
73
73
|
function useMounted() {
|
|
74
74
|
}
|
|
75
75
|
/**
|
|
76
|
-
*
|
|
77
|
-
* @
|
|
76
|
+
* 得到一个RefObject,用于判断组件是否卸载
|
|
77
|
+
* @param onUnmount 回调函数,卸载时触发
|
|
78
78
|
*/
|
|
79
|
-
function useUnmounted() {
|
|
79
|
+
function useUnmounted(onUnmount) {
|
|
80
80
|
const isUnmounted = (0, react_1.useRef)(false);
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
const mountTimes = (0, react_1.useRef)(0);
|
|
82
|
+
(0, react_1.useMemo)(() => {
|
|
83
|
+
mountTimes.current++;
|
|
84
|
+
}, []);
|
|
85
|
+
(0, react_1.useEffect)(() => () => {
|
|
86
|
+
if (!--mountTimes.current) {
|
|
87
|
+
isUnmounted.current = true;
|
|
88
|
+
onUnmount?.();
|
|
89
|
+
}
|
|
90
|
+
}, []);
|
|
84
91
|
return isUnmounted;
|
|
85
92
|
}
|
|
86
93
|
function useControlled(defaultValue, value, onChange) {
|
|
@@ -152,31 +159,34 @@ function useContainer(container, effectContainer, defaultContainer) {
|
|
|
152
159
|
* 使用外部类,该方法可避免`StrictMode`下,React渲染行为与外部类实例生命周期不同步的问题
|
|
153
160
|
*/
|
|
154
161
|
function useExternalClass(setup, cleanup) {
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
return prevInstance.current;
|
|
162
|
+
const instance = (0, react_1.useRef)(void 0);
|
|
163
|
+
instance.current ||= setup();
|
|
164
|
+
useUnmounted(() => {
|
|
165
|
+
cleanup?.(instance.current);
|
|
166
|
+
instance.current = void 0;
|
|
162
167
|
});
|
|
163
|
-
(0, react_1.useEffect)(() => () => {
|
|
164
|
-
!--mountTimes.current && cleanup?.(instance);
|
|
165
|
-
}, []);
|
|
166
168
|
return instance;
|
|
167
169
|
}
|
|
168
170
|
/**
|
|
169
171
|
* 用法同{@link useEffect},但StrictMode下不会执行两次
|
|
170
172
|
*/
|
|
171
173
|
function useStrictEffect(effect, deps) {
|
|
172
|
-
const
|
|
174
|
+
const hasRun = (0, react_1.useRef)(false);
|
|
175
|
+
const prevDeps = (0, react_1.useRef)(deps);
|
|
176
|
+
const prevCleanup = (0, react_1.useRef)(void 0);
|
|
173
177
|
(0, react_1.useEffect)(() => {
|
|
174
|
-
const isDepsChanged =
|
|
175
|
-
if (isDepsChanged) {
|
|
178
|
+
const isDepsChanged = !(0, utils_1.arrayShallowEqual)(prevDeps.current, deps);
|
|
179
|
+
if (!hasRun.current || isDepsChanged) {
|
|
180
|
+
prevCleanup.current?.();
|
|
181
|
+
prevCleanup.current = effect();
|
|
182
|
+
hasRun.current = true;
|
|
176
183
|
prevDeps.current = deps;
|
|
177
|
-
return effect();
|
|
178
184
|
}
|
|
179
185
|
});
|
|
186
|
+
useUnmounted(() => {
|
|
187
|
+
prevCleanup.current?.();
|
|
188
|
+
prevCleanup.current = void 0;
|
|
189
|
+
});
|
|
180
190
|
}
|
|
181
191
|
/**
|
|
182
192
|
* 用法同{@link useEffect},但会排除首次渲染
|
|
@@ -200,7 +210,7 @@ function useStrictMemo(factory, deps) {
|
|
|
200
210
|
const isDepsChanged = prevDeps.current ? !(0, utils_1.arrayShallowEqual)(prevDeps.current, deps) : true;
|
|
201
211
|
if (isDepsChanged) {
|
|
202
212
|
prevDeps.current = deps;
|
|
203
|
-
|
|
213
|
+
memoizedValue.current = factory();
|
|
204
214
|
}
|
|
205
215
|
return memoizedValue.current;
|
|
206
216
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
2
2
|
import { classes, style } from './anchorList.style.js';
|
|
3
|
-
import { clsx, listenAllPredecessorsScroll, useDerivedState,
|
|
3
|
+
import { clsx, listenAllPredecessorsScroll, useDerivedState, useSyncState } from '../../utils/index.js';
|
|
4
4
|
import { memo, useEffect, useRef } from 'react';
|
|
5
5
|
import { Flex } from '../flex/index.js';
|
|
6
6
|
import { ActiveIndicator } from './activeIndicator.js';
|
|
@@ -11,7 +11,7 @@ export const AnchorList = memo(({ anchors, renderAnchorItem, indent = 24, scroll
|
|
|
11
11
|
* 初始化高亮与滚动位置
|
|
12
12
|
*/
|
|
13
13
|
const mounted = useRef(false);
|
|
14
|
-
|
|
14
|
+
useEffect(() => {
|
|
15
15
|
if (routeMode === 'history') {
|
|
16
16
|
mounted.current ||= scrollToId(location.hash.slice(1));
|
|
17
17
|
}
|
|
@@ -15,10 +15,11 @@ export declare function useAppContext(): {
|
|
|
15
15
|
notification: AppNotificationMethods<import("./appNotification.js").AppNotificationProps>;
|
|
16
16
|
actionSheet: AppActionSheetMethods;
|
|
17
17
|
};
|
|
18
|
-
export
|
|
18
|
+
export type AppMethods = {
|
|
19
19
|
dialog: AppDialogMethods;
|
|
20
20
|
message: AppMessageMethods;
|
|
21
21
|
notification: AppNotificationMethods;
|
|
22
22
|
actionSheet: AppActionSheetMethods;
|
|
23
23
|
};
|
|
24
|
+
export declare const App: OverridableComponent<AppOwnProps> & AppMethods;
|
|
24
25
|
export declare function InnerApp({ component: Component, theme, children, fill, ...props }: OverridableProps<AppProps, 'div'>): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
2
2
|
import { createContext, useContext } from 'react';
|
|
3
|
-
import { clsx, defineCss
|
|
3
|
+
import { clsx, defineCss } from '../../utils/index.js';
|
|
4
4
|
import { classes, style } from './app.style.js';
|
|
5
5
|
import { ThemeProvider } from '../theme/index.js';
|
|
6
6
|
import { AppDialog, AppDialogMethods } from './appDialog.js';
|
|
@@ -22,17 +22,12 @@ export const App = (({ theme, ...props }) => {
|
|
|
22
22
|
return (_jsx(GlobalEventDelegation, { children: _jsx(ThemeProvider, { theme: theme, children: _jsx(InnerApp, { ...props }) }) }));
|
|
23
23
|
});
|
|
24
24
|
export function InnerApp({ component: Component = 'div', theme, children, fill = true, ...props }) {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
App.dialog ||= appValue.dialog;
|
|
32
|
-
App.message ||= appValue.message;
|
|
33
|
-
App.notification ||= appValue.notification;
|
|
34
|
-
App.actionSheet ||= appValue.actionSheet;
|
|
35
|
-
return (_jsxs(AppContext, { value: appValue, children: [Component
|
|
25
|
+
const appContext = useAppContext();
|
|
26
|
+
App.dialog = appContext.dialog;
|
|
27
|
+
App.message = appContext.message;
|
|
28
|
+
App.notification = appContext.notification;
|
|
29
|
+
App.actionSheet = appContext.actionSheet;
|
|
30
|
+
return (_jsxs(AppContext, { value: appContext, children: [Component
|
|
36
31
|
? _jsx(Component, { ...props, css: [
|
|
37
32
|
style,
|
|
38
33
|
defineCss(({ background }) => css `
|
|
@@ -44,5 +39,5 @@ export function InnerApp({ component: Component = 'div', theme, children, fill =
|
|
|
44
39
|
flex: 1;
|
|
45
40
|
`
|
|
46
41
|
], className: clsx(classes.root, props.className), children: children })
|
|
47
|
-
: children, _jsx(AppDialog, { methods:
|
|
42
|
+
: children, _jsx(AppDialog, { methods: appContext.dialog }), _jsx(AppMessage, { methods: appContext.message }), _jsx(AppNotification, { methods: appContext.notification }), _jsx(AppActionSheet, { methods: appContext.actionSheet })] }));
|
|
48
43
|
}
|
|
@@ -14,7 +14,7 @@ export const Autocomplete = memo(({ children, loading, options, loadOptions, pri
|
|
|
14
14
|
};
|
|
15
15
|
const [innerValue, setInnerValue] = useControlled(defaultValue, value);
|
|
16
16
|
const changedBySelect = useRef(false);
|
|
17
|
-
const changeHandler = (e, isSelect
|
|
17
|
+
const changeHandler = (e, isSelect) => {
|
|
18
18
|
changedBySelect.current = isSelect;
|
|
19
19
|
onChange?.(e);
|
|
20
20
|
setInnerValue(e.target.value);
|
|
@@ -77,7 +77,7 @@ export const Autocomplete = memo(({ children, loading, options, loadOptions, pri
|
|
|
77
77
|
className: classes.root,
|
|
78
78
|
loading: innerLoading.current,
|
|
79
79
|
value: innerValue.current,
|
|
80
|
-
onChange: changeHandler,
|
|
80
|
+
onChange: e => changeHandler(e, false),
|
|
81
81
|
onFocus: () => setFocused(true),
|
|
82
82
|
onBlur: () => setFocused(false)
|
|
83
83
|
});
|
|
@@ -19,7 +19,7 @@ interface FormOwnProps<V extends FormValue = FormValue> extends FormSharedProps,
|
|
|
19
19
|
wrapperRef?: Ref<HTMLFormElement>;
|
|
20
20
|
initialValue?: V;
|
|
21
21
|
onChange?(field: FieldPath, value: any, formValue: V): void;
|
|
22
|
-
onFinish?(value: V):
|
|
22
|
+
onFinish?(value: V): any;
|
|
23
23
|
items?: (FormItemProps & Obj)[];
|
|
24
24
|
descriptionsProps?: DescriptionsProps;
|
|
25
25
|
}
|
|
@@ -39,8 +39,7 @@ declare const FormValueContext: React.Context<FormValueContext<any>>;
|
|
|
39
39
|
export declare function useFormValueContext<V extends FormValue>(): FormValueContext<V>;
|
|
40
40
|
export declare function useFormStyleContext(): FormSharedProps;
|
|
41
41
|
export type FormRef<V extends FormValue = FormValue> = {
|
|
42
|
-
|
|
43
|
-
submit(): Promise<V | null>;
|
|
42
|
+
submit(): Promise<V>;
|
|
44
43
|
getFieldValue<T = any>(field: FieldPath): T;
|
|
45
44
|
getFormValue(): V;
|
|
46
45
|
getFieldError(field: FieldPath): FieldError | undefined;
|
|
@@ -75,7 +75,7 @@ inline, columnCount = 1, gap, columnGap, rowGap, ...props }) => {
|
|
|
75
75
|
await Promise.all([...itemsContainer.current].map(async ([field, item]) => {
|
|
76
76
|
return await item.validate() || Promise.reject(new TypeError(`Invalid field: "${field}"`));
|
|
77
77
|
}));
|
|
78
|
-
onFinish?.(formValue.current);
|
|
78
|
+
await onFinish?.(formValue.current);
|
|
79
79
|
return formValue.current;
|
|
80
80
|
};
|
|
81
81
|
const formRef = useRef(null);
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
|
2
2
|
import { Children, isValidElement, useLayoutEffect, useRef } from 'react';
|
|
3
3
|
import { classes, useStyle } from './waterfall.style.js';
|
|
4
4
|
import { WaterfallItem } from './waterfallItem.js';
|
|
5
|
-
import { cloneRef, clsx, toResponsiveValue,
|
|
5
|
+
import { cloneRef, clsx, toResponsiveValue, useResponsiveValue, useUnmounted, useUpdateEffect } from '../../utils/index.js';
|
|
6
6
|
export const Waterfall = ({ columnCount = { xs: 4 }, gap = 0, columnGap, rowGap, ...props }) => {
|
|
7
7
|
columnCount = toResponsiveValue(columnCount);
|
|
8
8
|
gap = toResponsiveValue(gap);
|
|
@@ -30,7 +30,7 @@ export const Waterfall = ({ columnCount = { xs: 4 }, gap = 0, columnGap, rowGap,
|
|
|
30
30
|
});
|
|
31
31
|
});
|
|
32
32
|
useUpdateEffect(computeItemOrder, [columnCountNum.current]);
|
|
33
|
-
|
|
33
|
+
useUnmounted(() => {
|
|
34
34
|
resizeObserver.current.disconnect();
|
|
35
35
|
});
|
|
36
36
|
return (_jsx("div", { ...props, ref: cloneRef(containerRef, props.ref), css: useStyle({ columnCount, columnGap, rowGap }), className: clsx(classes.root, props.className), children: Children.map(props.children, child => {
|
|
@@ -23,6 +23,10 @@ function InnerFormItem({ dependencies, checked, value, onChange, ...props }) {
|
|
|
23
23
|
props.children.props?.onChange?.(e);
|
|
24
24
|
onChange?.(e);
|
|
25
25
|
context.onChange?.();
|
|
26
|
+
},
|
|
27
|
+
onkeydown(e) {
|
|
28
|
+
e.preventDefault();
|
|
29
|
+
props.children.props?.onkeydown?.(e);
|
|
26
30
|
}
|
|
27
31
|
};
|
|
28
32
|
return (_jsx(FormItem, { ...props, ref: cloneRef(formItemRef, props.ref), _fieldValue: checked ?? value, children: (_, styleProps, key) => {
|
|
@@ -24,10 +24,10 @@ export declare function useDerivedState<T>(referredState: (prevState: T | undefi
|
|
|
24
24
|
export declare function useDerivedState<T>(referredState: T, deps?: any[]): [RefObject<T>, Dispatch<SetStateAction<T>>];
|
|
25
25
|
export declare function useMounted(): void;
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
28
|
-
* @
|
|
27
|
+
* 得到一个RefObject,用于判断组件是否卸载
|
|
28
|
+
* @param onUnmount 回调函数,卸载时触发
|
|
29
29
|
*/
|
|
30
|
-
export declare function useUnmounted(): RefObject<boolean>;
|
|
30
|
+
export declare function useUnmounted(onUnmount?: () => void): RefObject<boolean>;
|
|
31
31
|
/**
|
|
32
32
|
* 处理受控组件的外部属性与内部属性
|
|
33
33
|
* @param defaultValue
|
|
@@ -55,7 +55,7 @@ export declare function useContainer<T extends HTMLElement | null>(container?: D
|
|
|
55
55
|
/**
|
|
56
56
|
* 使用外部类,该方法可避免`StrictMode`下,React渲染行为与外部类实例生命周期不同步的问题
|
|
57
57
|
*/
|
|
58
|
-
export declare function useExternalClass<T>(setup: () => T, cleanup?: (instance: T) => void): T
|
|
58
|
+
export declare function useExternalClass<T>(setup: () => T, cleanup?: (instance: T) => void): RefObject<T>;
|
|
59
59
|
/**
|
|
60
60
|
* 用法同{@link useEffect},但StrictMode下不会执行两次
|
|
61
61
|
*/
|
|
@@ -67,4 +67,4 @@ export declare function useUpdateEffect(effect: EffectCallback, deps?: Dependenc
|
|
|
67
67
|
/**
|
|
68
68
|
* 用法同{@link useMemo},但StrictMode下不会执行两次
|
|
69
69
|
*/
|
|
70
|
-
export declare function useStrictMemo<T>(factory: () => T, deps
|
|
70
|
+
export declare function useStrictMemo<T>(factory: () => T, deps: DependencyList): T | undefined;
|
package/dist/esm/utils/hooks.js
CHANGED
|
@@ -32,7 +32,7 @@ export function useForceUpdate() {
|
|
|
32
32
|
export function useDerivedState(referredState, deps) {
|
|
33
33
|
const derivedState = useRef(void 0);
|
|
34
34
|
useMemo(() => {
|
|
35
|
-
// StrictMode
|
|
35
|
+
// StrictMode下,需要重置2次,使prevState保持正确
|
|
36
36
|
derivedState.current = void 0;
|
|
37
37
|
}, []);
|
|
38
38
|
const updateState = (state) => {
|
|
@@ -58,14 +58,21 @@ export function useDerivedState(referredState, deps) {
|
|
|
58
58
|
export function useMounted() {
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
|
-
*
|
|
62
|
-
* @
|
|
61
|
+
* 得到一个RefObject,用于判断组件是否卸载
|
|
62
|
+
* @param onUnmount 回调函数,卸载时触发
|
|
63
63
|
*/
|
|
64
|
-
export function useUnmounted() {
|
|
64
|
+
export function useUnmounted(onUnmount) {
|
|
65
65
|
const isUnmounted = useRef(false);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
const mountTimes = useRef(0);
|
|
67
|
+
useMemo(() => {
|
|
68
|
+
mountTimes.current++;
|
|
69
|
+
}, []);
|
|
70
|
+
useEffect(() => () => {
|
|
71
|
+
if (!--mountTimes.current) {
|
|
72
|
+
isUnmounted.current = true;
|
|
73
|
+
onUnmount?.();
|
|
74
|
+
}
|
|
75
|
+
}, []);
|
|
69
76
|
return isUnmounted;
|
|
70
77
|
}
|
|
71
78
|
export function useControlled(defaultValue, value, onChange) {
|
|
@@ -137,31 +144,34 @@ export function useContainer(container, effectContainer, defaultContainer) {
|
|
|
137
144
|
* 使用外部类,该方法可避免`StrictMode`下,React渲染行为与外部类实例生命周期不同步的问题
|
|
138
145
|
*/
|
|
139
146
|
export function useExternalClass(setup, cleanup) {
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
return prevInstance.current;
|
|
147
|
+
const instance = useRef(void 0);
|
|
148
|
+
instance.current ||= setup();
|
|
149
|
+
useUnmounted(() => {
|
|
150
|
+
cleanup?.(instance.current);
|
|
151
|
+
instance.current = void 0;
|
|
147
152
|
});
|
|
148
|
-
useEffect(() => () => {
|
|
149
|
-
!--mountTimes.current && cleanup?.(instance);
|
|
150
|
-
}, []);
|
|
151
153
|
return instance;
|
|
152
154
|
}
|
|
153
155
|
/**
|
|
154
156
|
* 用法同{@link useEffect},但StrictMode下不会执行两次
|
|
155
157
|
*/
|
|
156
158
|
export function useStrictEffect(effect, deps) {
|
|
157
|
-
const
|
|
159
|
+
const hasRun = useRef(false);
|
|
160
|
+
const prevDeps = useRef(deps);
|
|
161
|
+
const prevCleanup = useRef(void 0);
|
|
158
162
|
useEffect(() => {
|
|
159
|
-
const isDepsChanged =
|
|
160
|
-
if (isDepsChanged) {
|
|
163
|
+
const isDepsChanged = !arrayShallowEqual(prevDeps.current, deps);
|
|
164
|
+
if (!hasRun.current || isDepsChanged) {
|
|
165
|
+
prevCleanup.current?.();
|
|
166
|
+
prevCleanup.current = effect();
|
|
167
|
+
hasRun.current = true;
|
|
161
168
|
prevDeps.current = deps;
|
|
162
|
-
return effect();
|
|
163
169
|
}
|
|
164
170
|
});
|
|
171
|
+
useUnmounted(() => {
|
|
172
|
+
prevCleanup.current?.();
|
|
173
|
+
prevCleanup.current = void 0;
|
|
174
|
+
});
|
|
165
175
|
}
|
|
166
176
|
/**
|
|
167
177
|
* 用法同{@link useEffect},但会排除首次渲染
|
|
@@ -185,7 +195,7 @@ export function useStrictMemo(factory, deps) {
|
|
|
185
195
|
const isDepsChanged = prevDeps.current ? !arrayShallowEqual(prevDeps.current, deps) : true;
|
|
186
196
|
if (isDepsChanged) {
|
|
187
197
|
prevDeps.current = deps;
|
|
188
|
-
|
|
198
|
+
memoizedValue.current = factory();
|
|
189
199
|
}
|
|
190
200
|
return memoizedValue.current;
|
|
191
201
|
}
|