@canlooks/can-ui 0.0.52 → 0.0.54
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/curd/curd.d.ts +9 -3
- package/dist/cjs/components/curd/curd.js +16 -1
- package/dist/cjs/components/curd/curd.style.js +5 -0
- package/dist/cjs/components/curd/curdDialog.d.ts +3 -0
- package/dist/cjs/components/curd/curdDialog.js +47 -15
- package/dist/cjs/components/pickerDialog/pickerDialog.js +7 -7
- package/dist/cjs/utils/curd.d.ts +3 -2
- package/dist/esm/components/curd/curd.d.ts +9 -3
- package/dist/esm/components/curd/curd.js +17 -2
- package/dist/esm/components/curd/curd.style.js +5 -0
- package/dist/esm/components/curd/curdDialog.d.ts +3 -0
- package/dist/esm/components/curd/curdDialog.js +48 -16
- package/dist/esm/components/pickerDialog/pickerDialog.js +7 -7
- package/dist/esm/utils/curd.d.ts +3 -2
- package/documentation/dist/assets/{index-0lpazctB.js → index-GiFWv3kZ.js} +691 -687
- package/documentation/dist/index.html +1 -1
- package/package.json +1 -1
|
@@ -24,7 +24,13 @@ export type LoadRowsReturn<R extends RowType> = {
|
|
|
24
24
|
total: number;
|
|
25
25
|
};
|
|
26
26
|
type EachRowType<R extends RowType, T> = T | ((row: R) => T);
|
|
27
|
-
export
|
|
27
|
+
export type CurdRef<R extends RowType = RowType, F extends FormValue = FormValue> = {
|
|
28
|
+
openCreateDialog(initialValue?: R): Promise<F> | undefined;
|
|
29
|
+
selectSingle(): Promise<R> | undefined;
|
|
30
|
+
selectMultiple(selected?: Id[]): Promise<Id[]> | undefined;
|
|
31
|
+
};
|
|
32
|
+
export interface CurdBaseProps<R extends RowType, F extends FormValue> extends Omit<DataGridBaseProps<R>, 'ref'> {
|
|
33
|
+
ref?: Ref<CurdRef<R, F>>;
|
|
28
34
|
/** 默认属性会传递给DataGrid组件,外层包裹元素的属性使用wrapperProps */
|
|
29
35
|
wrapperProps?: DivProps;
|
|
30
36
|
wrapperRef?: Ref<HTMLDivElement>;
|
|
@@ -87,9 +93,9 @@ export interface CurdBaseProps<R extends RowType, F extends FormValue> extends D
|
|
|
87
93
|
formProps?: FormProps<F>;
|
|
88
94
|
formRef?: Ref<FormRef<F>>;
|
|
89
95
|
}
|
|
90
|
-
interface CurdSingleProps<R extends RowType, F extends FormValue = FormValue, V extends Id = Id> extends Omit<DataGridSingleProps<R, V>, 'columns'>, CurdBaseProps<R, F> {
|
|
96
|
+
interface CurdSingleProps<R extends RowType, F extends FormValue = FormValue, V extends Id = Id> extends Omit<DataGridSingleProps<R, V>, 'ref' | 'columns'>, CurdBaseProps<R, F> {
|
|
91
97
|
}
|
|
92
|
-
interface CurdMultipleProps<R extends RowType, F extends FormValue = FormValue, V extends Id = Id> extends Omit<DataGridMultipleProps<R, V>, 'columns'>, CurdBaseProps<R, F> {
|
|
98
|
+
interface CurdMultipleProps<R extends RowType, F extends FormValue = FormValue, V extends Id = Id> extends Omit<DataGridMultipleProps<R, V>, 'ref' | 'columns'>, CurdBaseProps<R, F> {
|
|
93
99
|
}
|
|
94
100
|
export type CurdProps<R extends RowType, F extends FormValue = FormValue, V extends Id = Id> = CurdSingleProps<R, F, V> | CurdMultipleProps<R, F, V>;
|
|
95
101
|
export declare const Curd: {
|
|
@@ -23,7 +23,22 @@ const faPenToSquare_1 = require("@fortawesome/free-regular-svg-icons/faPenToSqua
|
|
|
23
23
|
const faPlus_1 = require("@fortawesome/free-solid-svg-icons/faPlus");
|
|
24
24
|
const faRotateRight_1 = require("@fortawesome/free-solid-svg-icons/faRotateRight");
|
|
25
25
|
exports.Curd = (0, react_1.memo)((props) => {
|
|
26
|
-
const { wrapperProps, wrapperRef, variant = 'standard', loadRows, columns, toolbarLeft, toolbarRight, reloadable = true, onReload, resizable = true, columnConfigurable = true, filterProps, filterRef, initialFilterValue, onFilter, renderFilter, copyable, creatable = true, updatable = true, deletable = true, createButtonProps, updateButtonProps, deleteButtonProps, deleteConfirmProps, controlColumnTitle = '操作', renderExtraControl, titleKey, dataName = '', createName = '添加', updateName = '编辑', deleteName = '删除', onCreate, onUpdate, onDelete, postData, dialogProps, formProps, formRef, onChange, ...dataGridProps } = props;
|
|
26
|
+
const { ref, wrapperProps, wrapperRef, variant = 'standard', loadRows, columns, toolbarLeft, toolbarRight, reloadable = true, onReload, resizable = true, columnConfigurable = true, filterProps, filterRef, initialFilterValue, onFilter, renderFilter, copyable, creatable = true, updatable = true, deletable = true, createButtonProps, updateButtonProps, deleteButtonProps, deleteConfirmProps, controlColumnTitle = '操作', renderExtraControl, titleKey, dataName = '', createName = '添加', updateName = '编辑', deleteName = '删除', onCreate, onUpdate, onDelete, postData, dialogProps, formProps, formRef, onChange, ...dataGridProps } = props;
|
|
27
|
+
/**
|
|
28
|
+
* -------------------------------------------------------------
|
|
29
|
+
* ref
|
|
30
|
+
*/
|
|
31
|
+
(0, react_1.useImperativeHandle)(ref, () => ({
|
|
32
|
+
openCreateDialog(initialValue) {
|
|
33
|
+
return curdDialogRef.current?.open(initialValue);
|
|
34
|
+
},
|
|
35
|
+
selectSingle() {
|
|
36
|
+
return curdDialogRef.current?.selectSingle();
|
|
37
|
+
},
|
|
38
|
+
selectMultiple(selected) {
|
|
39
|
+
return curdDialogRef.current?.selectMultiple(selected);
|
|
40
|
+
}
|
|
41
|
+
}));
|
|
27
42
|
/**
|
|
28
43
|
* -------------------------------------------------------------
|
|
29
44
|
* 筛选部分
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.dialogStyle = exports.style = exports.classes = void 0;
|
|
4
4
|
const react_1 = require("@emotion/react");
|
|
5
5
|
const utils_1 = require("../../utils");
|
|
6
|
+
const button_style_1 = require("../button/button.style");
|
|
6
7
|
exports.classes = (0, utils_1.defineInnerClasses)('curd', [
|
|
7
8
|
'filter',
|
|
8
9
|
'filterGridContainer',
|
|
@@ -94,5 +95,9 @@ exports.dialogStyle = (0, utils_1.defineCss)(({ spacing }) => (0, react_1.css) `
|
|
|
94
95
|
display: flex;
|
|
95
96
|
align-items: center;
|
|
96
97
|
gap: ${spacing[8]}px;
|
|
98
|
+
|
|
99
|
+
.${button_style_1.classes.root} {
|
|
100
|
+
font-size: 1rem;
|
|
101
|
+
}
|
|
97
102
|
}
|
|
98
103
|
`);
|
|
@@ -3,8 +3,11 @@ import { DialogProps } from '../dialog';
|
|
|
3
3
|
import { RowType } from '../dataGrid';
|
|
4
4
|
import { FormValue } from '../form';
|
|
5
5
|
import { CurdBaseProps } from './curd';
|
|
6
|
+
import { Id } from '../../types';
|
|
6
7
|
export type CurdDialogRef<R extends RowType = RowType, F extends FormValue = FormValue> = {
|
|
7
8
|
open(activeRow?: R): Promise<F>;
|
|
9
|
+
selectSingle(): Promise<R>;
|
|
10
|
+
selectMultiple(selected?: Id[]): Promise<Id[]>;
|
|
8
11
|
};
|
|
9
12
|
export interface CurdDialogProps<R extends RowType, F extends FormValue = FormValue> extends Omit<DialogProps, 'ref'> {
|
|
10
13
|
ref?: Ref<CurdDialogRef<R, F>>;
|
|
@@ -23,26 +23,40 @@ curdProps, ...props }) => {
|
|
|
23
23
|
* ref与promise部分
|
|
24
24
|
*/
|
|
25
25
|
const innerFormRef = (0, react_2.useRef)(null);
|
|
26
|
-
const
|
|
26
|
+
const openResolvers = (0, react_2.useRef)(void 0);
|
|
27
27
|
const [innerOpen, setInnerOpen] = (0, utils_1.useControlled)(props.defaultOpen, props.open);
|
|
28
28
|
const closeHandler = (reason) => {
|
|
29
29
|
if (reason === 'confirmed') {
|
|
30
30
|
return;
|
|
31
31
|
}
|
|
32
32
|
props.onClose?.(reason);
|
|
33
|
-
|
|
33
|
+
openResolvers.current?.reject({
|
|
34
34
|
type: 'canceled',
|
|
35
35
|
value: innerFormRef.current.getFormValue()
|
|
36
36
|
});
|
|
37
37
|
setInnerOpen(false);
|
|
38
38
|
};
|
|
39
|
+
const [selectMode, setSelectMode] = (0, react_2.useState)('single');
|
|
40
|
+
const selectResolvers = (0, react_2.useRef)(void 0);
|
|
39
41
|
(0, react_2.useImperativeHandle)(ref, () => ({
|
|
40
42
|
open(row) {
|
|
41
43
|
innerFormRef.current?.resetForm();
|
|
42
44
|
setInnerOpen(true);
|
|
43
45
|
setActiveRow(row);
|
|
44
|
-
const { promise } =
|
|
46
|
+
const { promise } = openResolvers.current = Promise.withResolvers();
|
|
45
47
|
return promise;
|
|
48
|
+
},
|
|
49
|
+
selectSingle() {
|
|
50
|
+
isCopying.current = false;
|
|
51
|
+
setSelectMode('single');
|
|
52
|
+
pickerDialogRef.current.open().then();
|
|
53
|
+
const { promise } = selectResolvers.current = Promise.withResolvers();
|
|
54
|
+
return promise;
|
|
55
|
+
},
|
|
56
|
+
selectMultiple(selected) {
|
|
57
|
+
isCopying.current = false;
|
|
58
|
+
setSelectMode('multiple');
|
|
59
|
+
return pickerDialogRef.current.open(selected);
|
|
46
60
|
}
|
|
47
61
|
}));
|
|
48
62
|
/**
|
|
@@ -58,7 +72,13 @@ curdProps, ...props }) => {
|
|
|
58
72
|
innerOpen.current && setFormValue(activeRow);
|
|
59
73
|
}, [innerOpen.current]); // 依赖innerOpen而不依赖activeRow的原因是,有可能连续两次打开的activeRow是相同的
|
|
60
74
|
const renderedFormItems = (0, react_2.useMemo)(() => {
|
|
61
|
-
return (0, utils_1.columnsToFormItem)(columns, activeRow)?.map(
|
|
75
|
+
return (0, utils_1.columnsToFormItem)(columns, activeRow)?.map(col => {
|
|
76
|
+
if ((0, react_2.isValidElement)(col)) {
|
|
77
|
+
return col;
|
|
78
|
+
}
|
|
79
|
+
const { key, ...p } = col;
|
|
80
|
+
return (0, react_1.createElement)(form_1.FormItem, { ...p, key: key });
|
|
81
|
+
});
|
|
62
82
|
}, [columns, activeRow]);
|
|
63
83
|
/**
|
|
64
84
|
* ----------------------------------------------------------------
|
|
@@ -69,7 +89,7 @@ curdProps, ...props }) => {
|
|
|
69
89
|
};
|
|
70
90
|
const [innerLoading, finishHandler] = (0, utils_1.useLoading)(async (value) => {
|
|
71
91
|
formProps?.onFinish?.(value);
|
|
72
|
-
|
|
92
|
+
openResolvers.current?.resolve(value);
|
|
73
93
|
await onFinish?.(value);
|
|
74
94
|
setInnerOpen(false);
|
|
75
95
|
}, props.confirmLoading);
|
|
@@ -77,20 +97,32 @@ curdProps, ...props }) => {
|
|
|
77
97
|
* ----------------------------------------------------------------
|
|
78
98
|
* 复制
|
|
79
99
|
*/
|
|
100
|
+
const isCopying = (0, react_2.useRef)(false);
|
|
80
101
|
const pickerDialogRef = (0, react_2.useRef)(null);
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
102
|
+
const onCopyButtonClick = () => {
|
|
103
|
+
isCopying.current = true;
|
|
104
|
+
setSelectMode('single');
|
|
105
|
+
pickerDialogRef.current.open().then();
|
|
106
|
+
};
|
|
107
|
+
const toggleHandler = (checked, value, row) => {
|
|
108
|
+
if (isCopying.current) {
|
|
109
|
+
const title = !(0, utils_1.isUnset)(titleKey) ? row[titleKey] : void 0;
|
|
110
|
+
typeof title === 'string'
|
|
111
|
+
? setFormValue({
|
|
112
|
+
...row,
|
|
113
|
+
[titleKey]: `${title} - 副本`
|
|
114
|
+
})
|
|
115
|
+
: setFormValue(row);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
// 处理selectSingle
|
|
119
|
+
selectResolvers.current?.resolve(row);
|
|
120
|
+
}
|
|
89
121
|
};
|
|
90
122
|
const rowTitle = activeRow && !(0, utils_1.isUnset)(titleKey) ? activeRow[titleKey] : void 0;
|
|
91
123
|
return ((0, jsx_runtime_1.jsxs)(dialog_1.Dialog, { css: curd_style_1.dialogStyle, width: 600, title: activeRow
|
|
92
124
|
? `${updateName}${dataName}${rowTitle ? ' - ' + rowTitle : ''}`
|
|
93
125
|
: (0, jsx_runtime_1.jsxs)("div", { className: curd_style_1.classes.dialogTitle, children: [(0, jsx_runtime_1.jsxs)("span", { children: [createName, dataName] }), copyable &&
|
|
94
|
-
(0, jsx_runtime_1.jsxs)(button_1.Button, { variant: "plain", prefix: (0, jsx_runtime_1.jsx)(__1.Icon, { icon: faCopy_1.faCopy }), onClick:
|
|
95
|
-
(0, jsx_runtime_1.jsx)(pickerDialog_1.PickerDialog, { ref: pickerDialogRef, onToggle:
|
|
126
|
+
(0, jsx_runtime_1.jsxs)(button_1.Button, { variant: "plain", prefix: (0, jsx_runtime_1.jsx)(__1.Icon, { icon: faCopy_1.faCopy }), onClick: onCopyButtonClick, children: ["\u4ECE\u5DF2\u6709", dataName || '数据', "\u590D\u5236"] })] }), ...props, open: innerOpen.current, onClose: closeHandler, onConfirm: confirmHandler, confirmLoading: innerLoading.current, children: [(0, jsx_runtime_1.jsx)(loading_1.Loading, { open: transforming.current, children: (0, jsx_runtime_1.jsx)(form_1.Form, { labelWidth: "20%", ...formProps, ref: (0, utils_1.cloneRef)(formRef, innerFormRef), onFinish: finishHandler, children: renderedFormItems }) }), copyable &&
|
|
127
|
+
(0, jsx_runtime_1.jsx)(pickerDialog_1.PickerDialog, { ref: pickerDialogRef, multiple: selectMode === 'multiple', onToggle: toggleHandler, children: (0, jsx_runtime_1.jsx)(curd_1.Curd, { ...curdProps, variant: "embeded", copyable: false, creatable: false, updatable: false, deletable: false }) })] }));
|
|
96
128
|
});
|
|
@@ -16,13 +16,6 @@ exports.PickerDialog = (({ ref, dialogRef, multiple, children, showSelectedList
|
|
|
16
16
|
// 以下属性从SelectionContextBaseProps继承
|
|
17
17
|
options = rows ?? nodes, primaryKey = 'id', childrenKey = 'children', relation = 'dependent', integration = 'shallowest', disabled, clearable = !!multiple, onToggle, ...props }) => {
|
|
18
18
|
const resolvers = (0, react_1.useRef)(void 0);
|
|
19
|
-
const [innerValue, _setInnerValue] = (0, react_1.useState)(multiple ? [] : null);
|
|
20
|
-
const setInnerValue = (value) => {
|
|
21
|
-
_setInnerValue(value);
|
|
22
|
-
// 单选模式,值每次改变都触发确认
|
|
23
|
-
!multiple && confirmHandler(value);
|
|
24
|
-
};
|
|
25
|
-
const [innerOpen, setInnerOpen] = (0, utils_1.useControlled)(props.defaultOpen, props.open);
|
|
26
19
|
(0, react_1.useImperativeHandle)(ref, () => ({
|
|
27
20
|
open(value) {
|
|
28
21
|
_setInnerValue(value ?? null);
|
|
@@ -31,6 +24,13 @@ options = rows ?? nodes, primaryKey = 'id', childrenKey = 'children', relation =
|
|
|
31
24
|
return promise;
|
|
32
25
|
}
|
|
33
26
|
}));
|
|
27
|
+
const [innerValue, _setInnerValue] = (0, react_1.useState)(multiple ? [] : null);
|
|
28
|
+
const setInnerValue = (value) => {
|
|
29
|
+
_setInnerValue(value);
|
|
30
|
+
// 单选模式,值每次改变都触发确认
|
|
31
|
+
!multiple && confirmHandler(value);
|
|
32
|
+
};
|
|
33
|
+
const [innerOpen, setInnerOpen] = (0, utils_1.useControlled)(props.defaultOpen, props.open);
|
|
34
34
|
const onCloseHandler = (reason) => {
|
|
35
35
|
if (reason === 'confirmed') {
|
|
36
36
|
return;
|
package/dist/cjs/utils/curd.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
1
2
|
import { CurdColumn, CurdFormItemProps, CurdProps } from '../components/curd';
|
|
2
3
|
import { ColumnType, RowType } from '../components/dataGrid';
|
|
3
4
|
import { Id, Obj } from '../types';
|
|
@@ -6,13 +7,13 @@ import { FormValue } from '../components/form';
|
|
|
6
7
|
* 将Curd的Columns转换为FilterItem
|
|
7
8
|
* @param columns
|
|
8
9
|
*/
|
|
9
|
-
export declare function columnsToFilterItem(columns?: (CurdColumn<any> | symbol)[]): CurdFormItemProps[] | undefined;
|
|
10
|
+
export declare function columnsToFilterItem(columns?: (CurdColumn<any> | symbol)[]): (ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | CurdFormItemProps)[] | undefined;
|
|
10
11
|
/**
|
|
11
12
|
* 将Curd的Columns转换为FormItem
|
|
12
13
|
* @param columns
|
|
13
14
|
* @param row
|
|
14
15
|
*/
|
|
15
|
-
export declare function columnsToFormItem(columns?: (CurdColumn<any> | symbol)[], row?: Obj): CurdFormItemProps[] | undefined;
|
|
16
|
+
export declare function columnsToFormItem(columns?: (CurdColumn<any> | symbol)[], row?: Obj): (ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | CurdFormItemProps)[] | undefined;
|
|
16
17
|
/**
|
|
17
18
|
* 统一处理Columns
|
|
18
19
|
*/
|
|
@@ -24,7 +24,13 @@ export type LoadRowsReturn<R extends RowType> = {
|
|
|
24
24
|
total: number;
|
|
25
25
|
};
|
|
26
26
|
type EachRowType<R extends RowType, T> = T | ((row: R) => T);
|
|
27
|
-
export
|
|
27
|
+
export type CurdRef<R extends RowType = RowType, F extends FormValue = FormValue> = {
|
|
28
|
+
openCreateDialog(initialValue?: R): Promise<F> | undefined;
|
|
29
|
+
selectSingle(): Promise<R> | undefined;
|
|
30
|
+
selectMultiple(selected?: Id[]): Promise<Id[]> | undefined;
|
|
31
|
+
};
|
|
32
|
+
export interface CurdBaseProps<R extends RowType, F extends FormValue> extends Omit<DataGridBaseProps<R>, 'ref'> {
|
|
33
|
+
ref?: Ref<CurdRef<R, F>>;
|
|
28
34
|
/** 默认属性会传递给DataGrid组件,外层包裹元素的属性使用wrapperProps */
|
|
29
35
|
wrapperProps?: DivProps;
|
|
30
36
|
wrapperRef?: Ref<HTMLDivElement>;
|
|
@@ -87,9 +93,9 @@ export interface CurdBaseProps<R extends RowType, F extends FormValue> extends D
|
|
|
87
93
|
formProps?: FormProps<F>;
|
|
88
94
|
formRef?: Ref<FormRef<F>>;
|
|
89
95
|
}
|
|
90
|
-
interface CurdSingleProps<R extends RowType, F extends FormValue = FormValue, V extends Id = Id> extends Omit<DataGridSingleProps<R, V>, 'columns'>, CurdBaseProps<R, F> {
|
|
96
|
+
interface CurdSingleProps<R extends RowType, F extends FormValue = FormValue, V extends Id = Id> extends Omit<DataGridSingleProps<R, V>, 'ref' | 'columns'>, CurdBaseProps<R, F> {
|
|
91
97
|
}
|
|
92
|
-
interface CurdMultipleProps<R extends RowType, F extends FormValue = FormValue, V extends Id = Id> extends Omit<DataGridMultipleProps<R, V>, 'columns'>, CurdBaseProps<R, F> {
|
|
98
|
+
interface CurdMultipleProps<R extends RowType, F extends FormValue = FormValue, V extends Id = Id> extends Omit<DataGridMultipleProps<R, V>, 'ref' | 'columns'>, CurdBaseProps<R, F> {
|
|
93
99
|
}
|
|
94
100
|
export type CurdProps<R extends RowType, F extends FormValue = FormValue, V extends Id = Id> = CurdSingleProps<R, F, V> | CurdMultipleProps<R, F, V>;
|
|
95
101
|
export declare const Curd: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "@emotion/react/jsx-runtime";
|
|
2
|
-
import { memo, useCallback, useEffect, useMemo, useRef } from 'react';
|
|
2
|
+
import { memo, useCallback, useEffect, useMemo, useRef, useImperativeHandle } from 'react';
|
|
3
3
|
import { DataGrid } from '../dataGrid';
|
|
4
4
|
import { CurdFilter } from './curdFilter';
|
|
5
5
|
import { classes, style } from './curd.style';
|
|
@@ -20,7 +20,22 @@ import { faPenToSquare } from '@fortawesome/free-regular-svg-icons/faPenToSquare
|
|
|
20
20
|
import { faPlus } from '@fortawesome/free-solid-svg-icons/faPlus';
|
|
21
21
|
import { faRotateRight } from '@fortawesome/free-solid-svg-icons/faRotateRight';
|
|
22
22
|
export const Curd = memo((props) => {
|
|
23
|
-
const { wrapperProps, wrapperRef, variant = 'standard', loadRows, columns, toolbarLeft, toolbarRight, reloadable = true, onReload, resizable = true, columnConfigurable = true, filterProps, filterRef, initialFilterValue, onFilter, renderFilter, copyable, creatable = true, updatable = true, deletable = true, createButtonProps, updateButtonProps, deleteButtonProps, deleteConfirmProps, controlColumnTitle = '操作', renderExtraControl, titleKey, dataName = '', createName = '添加', updateName = '编辑', deleteName = '删除', onCreate, onUpdate, onDelete, postData, dialogProps, formProps, formRef, onChange, ...dataGridProps } = props;
|
|
23
|
+
const { ref, wrapperProps, wrapperRef, variant = 'standard', loadRows, columns, toolbarLeft, toolbarRight, reloadable = true, onReload, resizable = true, columnConfigurable = true, filterProps, filterRef, initialFilterValue, onFilter, renderFilter, copyable, creatable = true, updatable = true, deletable = true, createButtonProps, updateButtonProps, deleteButtonProps, deleteConfirmProps, controlColumnTitle = '操作', renderExtraControl, titleKey, dataName = '', createName = '添加', updateName = '编辑', deleteName = '删除', onCreate, onUpdate, onDelete, postData, dialogProps, formProps, formRef, onChange, ...dataGridProps } = props;
|
|
24
|
+
/**
|
|
25
|
+
* -------------------------------------------------------------
|
|
26
|
+
* ref
|
|
27
|
+
*/
|
|
28
|
+
useImperativeHandle(ref, () => ({
|
|
29
|
+
openCreateDialog(initialValue) {
|
|
30
|
+
return curdDialogRef.current?.open(initialValue);
|
|
31
|
+
},
|
|
32
|
+
selectSingle() {
|
|
33
|
+
return curdDialogRef.current?.selectSingle();
|
|
34
|
+
},
|
|
35
|
+
selectMultiple(selected) {
|
|
36
|
+
return curdDialogRef.current?.selectMultiple(selected);
|
|
37
|
+
}
|
|
38
|
+
}));
|
|
24
39
|
/**
|
|
25
40
|
* -------------------------------------------------------------
|
|
26
41
|
* 筛选部分
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { css } from '@emotion/react';
|
|
2
2
|
import { defineInnerClasses, defineCss } from '../../utils';
|
|
3
|
+
import { classes as buttonClasses } from '../button/button.style';
|
|
3
4
|
export const classes = defineInnerClasses('curd', [
|
|
4
5
|
'filter',
|
|
5
6
|
'filterGridContainer',
|
|
@@ -91,5 +92,9 @@ export const dialogStyle = defineCss(({ spacing }) => css `
|
|
|
91
92
|
display: flex;
|
|
92
93
|
align-items: center;
|
|
93
94
|
gap: ${spacing[8]}px;
|
|
95
|
+
|
|
96
|
+
.${buttonClasses.root} {
|
|
97
|
+
font-size: 1rem;
|
|
98
|
+
}
|
|
94
99
|
}
|
|
95
100
|
`);
|
|
@@ -3,8 +3,11 @@ import { DialogProps } from '../dialog';
|
|
|
3
3
|
import { RowType } from '../dataGrid';
|
|
4
4
|
import { FormValue } from '../form';
|
|
5
5
|
import { CurdBaseProps } from './curd';
|
|
6
|
+
import { Id } from '../../types';
|
|
6
7
|
export type CurdDialogRef<R extends RowType = RowType, F extends FormValue = FormValue> = {
|
|
7
8
|
open(activeRow?: R): Promise<F>;
|
|
9
|
+
selectSingle(): Promise<R>;
|
|
10
|
+
selectMultiple(selected?: Id[]): Promise<Id[]>;
|
|
8
11
|
};
|
|
9
12
|
export interface CurdDialogProps<R extends RowType, F extends FormValue = FormValue> extends Omit<DialogProps, 'ref'> {
|
|
10
13
|
ref?: Ref<CurdDialogRef<R, F>>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
2
2
|
import { createElement as _createElement } from "@emotion/react";
|
|
3
|
-
import { memo, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
3
|
+
import { memo, useEffect, useImperativeHandle, useMemo, useRef, useState, isValidElement } from 'react';
|
|
4
4
|
import { Dialog } from '../dialog';
|
|
5
5
|
import { Form, FormItem } from '../form';
|
|
6
6
|
import { Curd } from './curd';
|
|
@@ -20,26 +20,40 @@ curdProps, ...props }) => {
|
|
|
20
20
|
* ref与promise部分
|
|
21
21
|
*/
|
|
22
22
|
const innerFormRef = useRef(null);
|
|
23
|
-
const
|
|
23
|
+
const openResolvers = useRef(void 0);
|
|
24
24
|
const [innerOpen, setInnerOpen] = useControlled(props.defaultOpen, props.open);
|
|
25
25
|
const closeHandler = (reason) => {
|
|
26
26
|
if (reason === 'confirmed') {
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
29
|
props.onClose?.(reason);
|
|
30
|
-
|
|
30
|
+
openResolvers.current?.reject({
|
|
31
31
|
type: 'canceled',
|
|
32
32
|
value: innerFormRef.current.getFormValue()
|
|
33
33
|
});
|
|
34
34
|
setInnerOpen(false);
|
|
35
35
|
};
|
|
36
|
+
const [selectMode, setSelectMode] = useState('single');
|
|
37
|
+
const selectResolvers = useRef(void 0);
|
|
36
38
|
useImperativeHandle(ref, () => ({
|
|
37
39
|
open(row) {
|
|
38
40
|
innerFormRef.current?.resetForm();
|
|
39
41
|
setInnerOpen(true);
|
|
40
42
|
setActiveRow(row);
|
|
41
|
-
const { promise } =
|
|
43
|
+
const { promise } = openResolvers.current = Promise.withResolvers();
|
|
42
44
|
return promise;
|
|
45
|
+
},
|
|
46
|
+
selectSingle() {
|
|
47
|
+
isCopying.current = false;
|
|
48
|
+
setSelectMode('single');
|
|
49
|
+
pickerDialogRef.current.open().then();
|
|
50
|
+
const { promise } = selectResolvers.current = Promise.withResolvers();
|
|
51
|
+
return promise;
|
|
52
|
+
},
|
|
53
|
+
selectMultiple(selected) {
|
|
54
|
+
isCopying.current = false;
|
|
55
|
+
setSelectMode('multiple');
|
|
56
|
+
return pickerDialogRef.current.open(selected);
|
|
43
57
|
}
|
|
44
58
|
}));
|
|
45
59
|
/**
|
|
@@ -55,7 +69,13 @@ curdProps, ...props }) => {
|
|
|
55
69
|
innerOpen.current && setFormValue(activeRow);
|
|
56
70
|
}, [innerOpen.current]); // 依赖innerOpen而不依赖activeRow的原因是,有可能连续两次打开的activeRow是相同的
|
|
57
71
|
const renderedFormItems = useMemo(() => {
|
|
58
|
-
return columnsToFormItem(columns, activeRow)?.map(
|
|
72
|
+
return columnsToFormItem(columns, activeRow)?.map(col => {
|
|
73
|
+
if (isValidElement(col)) {
|
|
74
|
+
return col;
|
|
75
|
+
}
|
|
76
|
+
const { key, ...p } = col;
|
|
77
|
+
return _createElement(FormItem, { ...p, key: key });
|
|
78
|
+
});
|
|
59
79
|
}, [columns, activeRow]);
|
|
60
80
|
/**
|
|
61
81
|
* ----------------------------------------------------------------
|
|
@@ -66,7 +86,7 @@ curdProps, ...props }) => {
|
|
|
66
86
|
};
|
|
67
87
|
const [innerLoading, finishHandler] = useLoading(async (value) => {
|
|
68
88
|
formProps?.onFinish?.(value);
|
|
69
|
-
|
|
89
|
+
openResolvers.current?.resolve(value);
|
|
70
90
|
await onFinish?.(value);
|
|
71
91
|
setInnerOpen(false);
|
|
72
92
|
}, props.confirmLoading);
|
|
@@ -74,20 +94,32 @@ curdProps, ...props }) => {
|
|
|
74
94
|
* ----------------------------------------------------------------
|
|
75
95
|
* 复制
|
|
76
96
|
*/
|
|
97
|
+
const isCopying = useRef(false);
|
|
77
98
|
const pickerDialogRef = useRef(null);
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
99
|
+
const onCopyButtonClick = () => {
|
|
100
|
+
isCopying.current = true;
|
|
101
|
+
setSelectMode('single');
|
|
102
|
+
pickerDialogRef.current.open().then();
|
|
103
|
+
};
|
|
104
|
+
const toggleHandler = (checked, value, row) => {
|
|
105
|
+
if (isCopying.current) {
|
|
106
|
+
const title = !isUnset(titleKey) ? row[titleKey] : void 0;
|
|
107
|
+
typeof title === 'string'
|
|
108
|
+
? setFormValue({
|
|
109
|
+
...row,
|
|
110
|
+
[titleKey]: `${title} - 副本`
|
|
111
|
+
})
|
|
112
|
+
: setFormValue(row);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
// 处理selectSingle
|
|
116
|
+
selectResolvers.current?.resolve(row);
|
|
117
|
+
}
|
|
86
118
|
};
|
|
87
119
|
const rowTitle = activeRow && !isUnset(titleKey) ? activeRow[titleKey] : void 0;
|
|
88
120
|
return (_jsxs(Dialog, { css: dialogStyle, width: 600, title: activeRow
|
|
89
121
|
? `${updateName}${dataName}${rowTitle ? ' - ' + rowTitle : ''}`
|
|
90
122
|
: _jsxs("div", { className: classes.dialogTitle, children: [_jsxs("span", { children: [createName, dataName] }), copyable &&
|
|
91
|
-
_jsxs(Button, { variant: "plain", prefix: _jsx(Icon, { icon: faCopy }), onClick:
|
|
92
|
-
_jsx(PickerDialog, { ref: pickerDialogRef, onToggle:
|
|
123
|
+
_jsxs(Button, { variant: "plain", prefix: _jsx(Icon, { icon: faCopy }), onClick: onCopyButtonClick, children: ["\u4ECE\u5DF2\u6709", dataName || '数据', "\u590D\u5236"] })] }), ...props, open: innerOpen.current, onClose: closeHandler, onConfirm: confirmHandler, confirmLoading: innerLoading.current, children: [_jsx(Loading, { open: transforming.current, children: _jsx(Form, { labelWidth: "20%", ...formProps, ref: cloneRef(formRef, innerFormRef), onFinish: finishHandler, children: renderedFormItems }) }), copyable &&
|
|
124
|
+
_jsx(PickerDialog, { ref: pickerDialogRef, multiple: selectMode === 'multiple', onToggle: toggleHandler, children: _jsx(Curd, { ...curdProps, variant: "embeded", copyable: false, creatable: false, updatable: false, deletable: false }) })] }));
|
|
93
125
|
});
|
|
@@ -13,13 +13,6 @@ export const PickerDialog = (({ ref, dialogRef, multiple, children, showSelected
|
|
|
13
13
|
// 以下属性从SelectionContextBaseProps继承
|
|
14
14
|
options = rows ?? nodes, primaryKey = 'id', childrenKey = 'children', relation = 'dependent', integration = 'shallowest', disabled, clearable = !!multiple, onToggle, ...props }) => {
|
|
15
15
|
const resolvers = useRef(void 0);
|
|
16
|
-
const [innerValue, _setInnerValue] = useState(multiple ? [] : null);
|
|
17
|
-
const setInnerValue = (value) => {
|
|
18
|
-
_setInnerValue(value);
|
|
19
|
-
// 单选模式,值每次改变都触发确认
|
|
20
|
-
!multiple && confirmHandler(value);
|
|
21
|
-
};
|
|
22
|
-
const [innerOpen, setInnerOpen] = useControlled(props.defaultOpen, props.open);
|
|
23
16
|
useImperativeHandle(ref, () => ({
|
|
24
17
|
open(value) {
|
|
25
18
|
_setInnerValue(value ?? null);
|
|
@@ -28,6 +21,13 @@ options = rows ?? nodes, primaryKey = 'id', childrenKey = 'children', relation =
|
|
|
28
21
|
return promise;
|
|
29
22
|
}
|
|
30
23
|
}));
|
|
24
|
+
const [innerValue, _setInnerValue] = useState(multiple ? [] : null);
|
|
25
|
+
const setInnerValue = (value) => {
|
|
26
|
+
_setInnerValue(value);
|
|
27
|
+
// 单选模式,值每次改变都触发确认
|
|
28
|
+
!multiple && confirmHandler(value);
|
|
29
|
+
};
|
|
30
|
+
const [innerOpen, setInnerOpen] = useControlled(props.defaultOpen, props.open);
|
|
31
31
|
const onCloseHandler = (reason) => {
|
|
32
32
|
if (reason === 'confirmed') {
|
|
33
33
|
return;
|
package/dist/esm/utils/curd.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
1
2
|
import { CurdColumn, CurdFormItemProps, CurdProps } from '../components/curd';
|
|
2
3
|
import { ColumnType, RowType } from '../components/dataGrid';
|
|
3
4
|
import { Id, Obj } from '../types';
|
|
@@ -6,13 +7,13 @@ import { FormValue } from '../components/form';
|
|
|
6
7
|
* 将Curd的Columns转换为FilterItem
|
|
7
8
|
* @param columns
|
|
8
9
|
*/
|
|
9
|
-
export declare function columnsToFilterItem(columns?: (CurdColumn<any> | symbol)[]): CurdFormItemProps[] | undefined;
|
|
10
|
+
export declare function columnsToFilterItem(columns?: (CurdColumn<any> | symbol)[]): (ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | CurdFormItemProps)[] | undefined;
|
|
10
11
|
/**
|
|
11
12
|
* 将Curd的Columns转换为FormItem
|
|
12
13
|
* @param columns
|
|
13
14
|
* @param row
|
|
14
15
|
*/
|
|
15
|
-
export declare function columnsToFormItem(columns?: (CurdColumn<any> | symbol)[], row?: Obj): CurdFormItemProps[] | undefined;
|
|
16
|
+
export declare function columnsToFormItem(columns?: (CurdColumn<any> | symbol)[], row?: Obj): (ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | CurdFormItemProps)[] | undefined;
|
|
16
17
|
/**
|
|
17
18
|
* 统一处理Columns
|
|
18
19
|
*/
|