@fe-free/core 1.4.20 → 1.5.1
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/CHANGELOG.md +17 -0
- package/package.json +2 -2
- package/src/button/button.stories.ts +9 -1
- package/src/crud/crud.stories.tsx +54 -1
- package/src/crud/crud_detail.tsx +1 -1
- package/src/crud/crud_of_simple.stories.tsx +1 -1
- package/src/editor/editor.stories.tsx +1 -1
- package/src/editor_javascript/editor_javascript.stories.tsx +1 -1
- package/src/editor_json/editor_json.stories.tsx +1 -1
- package/src/editor_logs/editor_logs.stories.tsx +1 -1
- package/src/editor_markdown/editor_markdown.stories.tsx +1 -1
- package/src/form/form.stories.tsx +43 -8
- package/src/form/form_list/form_list.tsx +127 -0
- package/src/form/form_list/form_list_helper.tsx +74 -0
- package/src/form/form_list/form_list_modal_helper.tsx +123 -0
- package/src/form/index.tsx +4 -0
- package/src/form/pro_form_editor.tsx +2 -3
- package/src/form/pro_form_javascript.tsx +2 -3
- package/src/form/pro_form_json.tsx +2 -3
- package/src/form/pro_form_switch_number.tsx +1 -2
- package/src/index.ts +4 -0
- package/src/table/index.tsx +9 -5
- package/src/table/table.stories.tsx +41 -26
- package/src/value_type_map/value_type_map.stories.tsx +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @fe-free/core
|
|
2
2
|
|
|
3
|
+
## 1.5.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- fix: form
|
|
8
|
+
- @fe-free/tool@1.5.1
|
|
9
|
+
|
|
10
|
+
## 1.5.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- feat: form
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- @fe-free/tool@1.5.0
|
|
19
|
+
|
|
3
20
|
## 1.4.20
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fe-free/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"author": "",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"react-syntax-highlighter": "^15.5.0",
|
|
37
37
|
"vanilla-jsoneditor": "^0.23.1",
|
|
38
38
|
"zustand": "^4.5.4",
|
|
39
|
-
"@fe-free/tool": "1.
|
|
39
|
+
"@fe-free/tool": "1.5.1"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"@ant-design/pro-components": "^2.8.7",
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import { LoadingButton } from '@fe-free/core';
|
|
2
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
3
3
|
|
|
4
4
|
const meta: Meta<typeof LoadingButton> = {
|
|
5
5
|
title: '@fe-free/core/LoadingButton',
|
|
6
6
|
component: LoadingButton,
|
|
7
7
|
tags: ['autodocs'],
|
|
8
|
+
parameters: {
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component:
|
|
12
|
+
'LoadingButton 是一个带有加载状态的按钮组件,适用于异步操作场景。<br/>区别于 antd Button 需要手动传 loading props。',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
8
16
|
};
|
|
9
17
|
|
|
10
18
|
export default meta;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ProColumns } from '@ant-design/pro-components';
|
|
2
2
|
import { ProForm, ProFormSwitch, ProFormText } from '@ant-design/pro-components';
|
|
3
3
|
import { CRUD, proFormSelectSearchProps } from '@fe-free/core';
|
|
4
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
4
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
5
5
|
import { Button } from 'antd';
|
|
6
6
|
import { useRef } from 'react';
|
|
7
7
|
import {
|
|
@@ -500,3 +500,56 @@ export const RowSelection: Story = {
|
|
|
500
500
|
);
|
|
501
501
|
},
|
|
502
502
|
};
|
|
503
|
+
|
|
504
|
+
export const ExpandedRowRender: Story = {
|
|
505
|
+
render: () => {
|
|
506
|
+
const columns = [
|
|
507
|
+
{
|
|
508
|
+
title: 'id',
|
|
509
|
+
dataIndex: 'id',
|
|
510
|
+
search: true,
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
title: '名字(省略)',
|
|
514
|
+
dataIndex: 'name',
|
|
515
|
+
search: true,
|
|
516
|
+
ellipsis: true,
|
|
517
|
+
},
|
|
518
|
+
];
|
|
519
|
+
|
|
520
|
+
return (
|
|
521
|
+
<CRUD
|
|
522
|
+
actions={['create', 'read', 'delete', 'update']}
|
|
523
|
+
tableProps={{
|
|
524
|
+
columns,
|
|
525
|
+
request: fakeRequest,
|
|
526
|
+
defaultExpandAllRows: true,
|
|
527
|
+
expandable: {
|
|
528
|
+
expandedRowKeys: ['0', '1'],
|
|
529
|
+
expandedRowRender: () => {
|
|
530
|
+
return <div>123</div>;
|
|
531
|
+
},
|
|
532
|
+
},
|
|
533
|
+
}}
|
|
534
|
+
requestDeleteByRecord={fakeDeleteByRecord}
|
|
535
|
+
deleteProps={{
|
|
536
|
+
nameIndex: 'name',
|
|
537
|
+
}}
|
|
538
|
+
detailForm={() => (
|
|
539
|
+
<>
|
|
540
|
+
<ProFormText
|
|
541
|
+
name="name"
|
|
542
|
+
label="名字"
|
|
543
|
+
required
|
|
544
|
+
rules={[{ required: true }]}
|
|
545
|
+
extra="extra extra extra extra"
|
|
546
|
+
/>
|
|
547
|
+
</>
|
|
548
|
+
)}
|
|
549
|
+
requestGetByRecord={fakeGetByRecord}
|
|
550
|
+
requestCreateByValues={fakeCreate}
|
|
551
|
+
requestUpdateById={fakeUpdateById}
|
|
552
|
+
/>
|
|
553
|
+
);
|
|
554
|
+
},
|
|
555
|
+
};
|
package/src/crud/crud_detail.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ProFormText } from '@ant-design/pro-components';
|
|
2
2
|
import { CRUDOfSimple } from '@fe-free/core';
|
|
3
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
4
4
|
import { fakeCreate, fakeDeleteByRecord, fakeRequest } from './demo/data';
|
|
5
5
|
|
|
6
6
|
const meta: Meta<typeof CRUDOfSimple> = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EditorProps } from '@fe-free/core';
|
|
2
2
|
import { Editor } from '@fe-free/core';
|
|
3
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
4
4
|
import { useState } from 'react';
|
|
5
5
|
|
|
6
6
|
const meta: Meta<typeof Editor> = {
|
|
@@ -1,15 +1,31 @@
|
|
|
1
1
|
import { ProForm } from '@ant-design/pro-components';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
ProFormEditor,
|
|
4
|
+
ProFormJSON,
|
|
5
|
+
ProFormJavascript,
|
|
6
|
+
ProFormListNumber,
|
|
7
|
+
ProFormListText,
|
|
8
|
+
ProFormSwitchNumber,
|
|
9
|
+
} from '@fe-free/core';
|
|
10
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
4
11
|
import { useState } from 'react';
|
|
5
12
|
|
|
6
|
-
const meta: Meta = {
|
|
13
|
+
const meta: Meta<typeof ProForm> = {
|
|
7
14
|
title: '@fe-free/core/Form',
|
|
15
|
+
component: ProForm,
|
|
8
16
|
tags: ['autodocs'],
|
|
17
|
+
parameters: {
|
|
18
|
+
docs: {
|
|
19
|
+
description: {
|
|
20
|
+
component:
|
|
21
|
+
'Form 组件基于 Ant Design ProForm,支持多种表单类型和扩展字段,适用于复杂表单场景。',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
9
25
|
};
|
|
10
26
|
|
|
11
27
|
export default meta;
|
|
12
|
-
type Story = StoryObj<typeof
|
|
28
|
+
type Story = StoryObj<typeof ProForm>;
|
|
13
29
|
|
|
14
30
|
function ProFormBase({
|
|
15
31
|
children,
|
|
@@ -23,9 +39,11 @@ function ProFormBase({
|
|
|
23
39
|
return (
|
|
24
40
|
<ProForm
|
|
25
41
|
initialValues={initialValues}
|
|
26
|
-
onValuesChange={(
|
|
27
|
-
|
|
28
|
-
|
|
42
|
+
onValuesChange={(newValues) => {
|
|
43
|
+
setValues({
|
|
44
|
+
...values,
|
|
45
|
+
...newValues,
|
|
46
|
+
});
|
|
29
47
|
}}
|
|
30
48
|
onFinish={(values) => {
|
|
31
49
|
console.log('values', values);
|
|
@@ -46,7 +64,7 @@ console.log('hello', name);
|
|
|
46
64
|
`,
|
|
47
65
|
}}
|
|
48
66
|
>
|
|
49
|
-
<ProFormEditor name="code" fieldProps={{ language: 'javascript', height: '
|
|
67
|
+
<ProFormEditor name="code" fieldProps={{ language: 'javascript', height: '400px' }} />
|
|
50
68
|
</ProFormBase>
|
|
51
69
|
),
|
|
52
70
|
};
|
|
@@ -101,3 +119,20 @@ export const ProFormSwitchNumberComponent: Story = {
|
|
|
101
119
|
</ProFormBase>
|
|
102
120
|
),
|
|
103
121
|
};
|
|
122
|
+
|
|
123
|
+
export const ProFormListTextComponent: Story = {
|
|
124
|
+
render: () => (
|
|
125
|
+
<ProFormBase>
|
|
126
|
+
<ProFormListText name="listText" />
|
|
127
|
+
</ProFormBase>
|
|
128
|
+
),
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export const ProFormListNumberComponent: Story = {
|
|
132
|
+
render: () => (
|
|
133
|
+
<ProFormBase>
|
|
134
|
+
<ProFormListNumber name="listNumber" label="listNumber" />
|
|
135
|
+
<ProFormListNumber name="listInteger" label="listInteger" fieldProps={{ precision: 0 }} />
|
|
136
|
+
</ProFormBase>
|
|
137
|
+
),
|
|
138
|
+
};
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type { ProFormItemProps } from '@ant-design/pro-components';
|
|
2
|
+
import { ProForm } from '@ant-design/pro-components';
|
|
3
|
+
import { Input, InputNumber } from 'antd';
|
|
4
|
+
|
|
5
|
+
import { ProFormListHelper } from './form_list_helper';
|
|
6
|
+
|
|
7
|
+
interface ListTextProps {
|
|
8
|
+
value?: (string | { value: string; label: string })[];
|
|
9
|
+
onChange?: (value: (string | { value: string; label: string })[]) => void;
|
|
10
|
+
isValueLabel?: boolean;
|
|
11
|
+
placeholder?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function ListText(props: ListTextProps) {
|
|
15
|
+
const { isValueLabel, placeholder } = props;
|
|
16
|
+
return (
|
|
17
|
+
<ProFormListHelper value={props.value} onChange={props.onChange} getAdd={() => ''}>
|
|
18
|
+
{({ item, onItemChange }) => {
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
const value = isValueLabel ? item.value : item;
|
|
21
|
+
return (
|
|
22
|
+
<Input
|
|
23
|
+
placeholder={placeholder}
|
|
24
|
+
value={value}
|
|
25
|
+
onChange={(e) => {
|
|
26
|
+
if (isValueLabel) {
|
|
27
|
+
onItemChange({ value: e.target.value, label: e.target.value });
|
|
28
|
+
} else {
|
|
29
|
+
onItemChange(e.target.value);
|
|
30
|
+
}
|
|
31
|
+
}}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
}}
|
|
35
|
+
</ProFormListHelper>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface ListNumberProps {
|
|
40
|
+
value?: (number | { value: number; label: string })[];
|
|
41
|
+
onChange?: (value: (number | { value: number; label: string })[]) => void;
|
|
42
|
+
isValueLabel?: boolean;
|
|
43
|
+
placeholder?: string;
|
|
44
|
+
precision?: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function ListNumber(props: ListNumberProps) {
|
|
48
|
+
const { isValueLabel, placeholder, precision } = props;
|
|
49
|
+
return (
|
|
50
|
+
<ProFormListHelper value={props.value} onChange={props.onChange} getAdd={() => 0}>
|
|
51
|
+
{({ item, onItemChange }) => {
|
|
52
|
+
// @ts-ignore
|
|
53
|
+
const value = isValueLabel ? item.value : item;
|
|
54
|
+
return (
|
|
55
|
+
<InputNumber
|
|
56
|
+
value={value}
|
|
57
|
+
onChange={(nv) => {
|
|
58
|
+
if (isValueLabel) {
|
|
59
|
+
onItemChange({ value: nv, label: nv.toString() });
|
|
60
|
+
} else {
|
|
61
|
+
onItemChange(nv);
|
|
62
|
+
}
|
|
63
|
+
}}
|
|
64
|
+
precision={precision}
|
|
65
|
+
style={{ width: '100%' }}
|
|
66
|
+
placeholder={placeholder}
|
|
67
|
+
/>
|
|
68
|
+
);
|
|
69
|
+
}}
|
|
70
|
+
</ProFormListHelper>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function ProFormListBase(props) {
|
|
75
|
+
const { fieldProps, ...rest } = props;
|
|
76
|
+
|
|
77
|
+
const isValueLabel = fieldProps?.isValueLabel;
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<ProForm.Item
|
|
81
|
+
{...rest}
|
|
82
|
+
required={props.required ?? true}
|
|
83
|
+
rules={[
|
|
84
|
+
...(props.rules || []),
|
|
85
|
+
// { required: true },
|
|
86
|
+
{
|
|
87
|
+
validator: async (_, value) => {
|
|
88
|
+
if (isValueLabel) {
|
|
89
|
+
if (value?.some((item) => item.value === undefined)) {
|
|
90
|
+
return Promise.reject('每个选项都不能为空');
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
if (value?.some((item) => item === undefined)) {
|
|
94
|
+
return Promise.reject('每个选项都不能为空');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return Promise.resolve();
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
]}
|
|
101
|
+
>
|
|
102
|
+
{props.children}
|
|
103
|
+
</ProForm.Item>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function ProFormListText(props: ProFormItemProps<ListTextProps>) {
|
|
108
|
+
const { fieldProps, ...rest } = props;
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<ProFormListBase {...rest}>
|
|
112
|
+
<ListText {...fieldProps} />
|
|
113
|
+
</ProFormListBase>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function ProFormListNumber(props: ProFormItemProps<ListNumberProps>) {
|
|
118
|
+
const { fieldProps, ...rest } = props;
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<ProFormListBase {...rest}>
|
|
122
|
+
<ListNumber {...fieldProps} />
|
|
123
|
+
</ProFormListBase>
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export { ProFormListNumber, ProFormListText };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
|
|
2
|
+
import { Button } from 'antd';
|
|
3
|
+
|
|
4
|
+
interface ProFormListHelperProps<T> {
|
|
5
|
+
value?: T[];
|
|
6
|
+
onChange?: (value: T[]) => void;
|
|
7
|
+
children: (props: {
|
|
8
|
+
value?: T[];
|
|
9
|
+
item: T;
|
|
10
|
+
index: number;
|
|
11
|
+
onItemChange: (newItem: T) => void;
|
|
12
|
+
}) => React.ReactNode;
|
|
13
|
+
addText?: string;
|
|
14
|
+
getAdd: () => T;
|
|
15
|
+
readOnly?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const emptyArr = [];
|
|
19
|
+
function ProFormListHelper<T = any>(props: ProFormListHelperProps<T>) {
|
|
20
|
+
const options = props.value || emptyArr;
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<div className="flex flex-col gap-2">
|
|
24
|
+
<div className="flex flex-col gap-2">
|
|
25
|
+
{options.map((item, index) => {
|
|
26
|
+
return (
|
|
27
|
+
<div key={index} className="flex">
|
|
28
|
+
<div className="flex-1 overflow-hidden">
|
|
29
|
+
{props.children({
|
|
30
|
+
value: props.value,
|
|
31
|
+
item,
|
|
32
|
+
index,
|
|
33
|
+
onItemChange: (newItem) => {
|
|
34
|
+
const newOptions = [...options];
|
|
35
|
+
newOptions[index] = newItem;
|
|
36
|
+
props.onChange?.(newOptions);
|
|
37
|
+
},
|
|
38
|
+
})}
|
|
39
|
+
</div>
|
|
40
|
+
{!props.readOnly && (
|
|
41
|
+
<Button
|
|
42
|
+
icon={<DeleteOutlined />}
|
|
43
|
+
type="text"
|
|
44
|
+
onClick={() => {
|
|
45
|
+
const newOptions = [...options];
|
|
46
|
+
newOptions.splice(index, 1);
|
|
47
|
+
props.onChange?.(newOptions);
|
|
48
|
+
}}
|
|
49
|
+
/>
|
|
50
|
+
)}
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
})}
|
|
54
|
+
</div>
|
|
55
|
+
{!props.readOnly && (
|
|
56
|
+
<div className="flex justify-center">
|
|
57
|
+
<Button
|
|
58
|
+
size="small"
|
|
59
|
+
icon={<PlusOutlined />}
|
|
60
|
+
onClick={() => {
|
|
61
|
+
const newOptions = [...options];
|
|
62
|
+
newOptions.push(props.getAdd());
|
|
63
|
+
props.onChange?.(newOptions);
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
{props.addText || '添加'}
|
|
67
|
+
</Button>
|
|
68
|
+
</div>
|
|
69
|
+
)}
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { ProFormListHelper };
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { DeleteOutlined, EditOutlined, PlusOutlined } from '@ant-design/icons';
|
|
2
|
+
import { ModalForm } from '@ant-design/pro-components';
|
|
3
|
+
import { Button } from 'antd';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
|
|
6
|
+
const emptyArr = [];
|
|
7
|
+
|
|
8
|
+
function Edit<T>(props: {
|
|
9
|
+
children: JSX.Element;
|
|
10
|
+
values?: T;
|
|
11
|
+
onChange: (values: T) => void;
|
|
12
|
+
detailForm: JSX.Element;
|
|
13
|
+
editForm?: any;
|
|
14
|
+
disabledSubmitter?: boolean;
|
|
15
|
+
}) {
|
|
16
|
+
const handleFinish = async (newValues) => {
|
|
17
|
+
props.onChange(newValues as T);
|
|
18
|
+
|
|
19
|
+
return true;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<ModalForm
|
|
24
|
+
title={props.values ? '编辑' : '添加'}
|
|
25
|
+
trigger={props.children}
|
|
26
|
+
onFinish={handleFinish}
|
|
27
|
+
formRef={props?.editForm}
|
|
28
|
+
initialValues={props.values || undefined}
|
|
29
|
+
submitter={props.disabledSubmitter ? false : undefined}
|
|
30
|
+
>
|
|
31
|
+
{props.detailForm}
|
|
32
|
+
</ModalForm>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface ProFormListModalHelperProps<T> {
|
|
37
|
+
value?: T[];
|
|
38
|
+
onChange?: (value: T[]) => void;
|
|
39
|
+
children: (props: { value?: T[]; item: T; index: number }) => React.ReactNode;
|
|
40
|
+
readOnly?: boolean;
|
|
41
|
+
detailForm: JSX.Element;
|
|
42
|
+
// 如果 addForm 存在,则使用 addForm 作为添加按钮
|
|
43
|
+
addForm?: JSX.Element;
|
|
44
|
+
// 禁用添加的提交按钮
|
|
45
|
+
disabledSubmitter?: boolean;
|
|
46
|
+
|
|
47
|
+
disabledAdd?: boolean;
|
|
48
|
+
// 触发添加
|
|
49
|
+
addTrigger?: JSX.Element;
|
|
50
|
+
|
|
51
|
+
editForm?: any;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function ProFormListModalHelper<T = any>(props: ProFormListModalHelperProps<T>) {
|
|
55
|
+
const options = props.value || emptyArr;
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<div className="flex flex-col gap-2">
|
|
59
|
+
<div className="flex flex-col gap-2">
|
|
60
|
+
{options.map((item, index) => {
|
|
61
|
+
return (
|
|
62
|
+
<div key={index} className="group relative">
|
|
63
|
+
<div className="flex-1">
|
|
64
|
+
{props.children({
|
|
65
|
+
value: props.value,
|
|
66
|
+
item,
|
|
67
|
+
index,
|
|
68
|
+
})}
|
|
69
|
+
</div>
|
|
70
|
+
{!props.readOnly && (
|
|
71
|
+
<div className="absolute right-1 top-1 hidden items-center bg-white group-hover:flex">
|
|
72
|
+
<Edit<T>
|
|
73
|
+
values={item}
|
|
74
|
+
onChange={(newValues) => {
|
|
75
|
+
const newOptions = [...options];
|
|
76
|
+
newOptions[index] = newValues;
|
|
77
|
+
props.onChange?.(newOptions);
|
|
78
|
+
}}
|
|
79
|
+
detailForm={props.detailForm}
|
|
80
|
+
editForm={props?.editForm}
|
|
81
|
+
>
|
|
82
|
+
<Button icon={<EditOutlined />} type="text" size="small" />
|
|
83
|
+
</Edit>
|
|
84
|
+
<Button
|
|
85
|
+
icon={<DeleteOutlined />}
|
|
86
|
+
type="text"
|
|
87
|
+
size="small"
|
|
88
|
+
onClick={() => {
|
|
89
|
+
const newOptions = [...options];
|
|
90
|
+
newOptions.splice(index, 1);
|
|
91
|
+
props.onChange?.(newOptions);
|
|
92
|
+
}}
|
|
93
|
+
/>
|
|
94
|
+
</div>
|
|
95
|
+
)}
|
|
96
|
+
</div>
|
|
97
|
+
);
|
|
98
|
+
})}
|
|
99
|
+
</div>
|
|
100
|
+
{!props.readOnly && !props.disabledAdd && (
|
|
101
|
+
<div className="flex justify-center">
|
|
102
|
+
<Edit<T>
|
|
103
|
+
onChange={(newValues) => {
|
|
104
|
+
props.onChange?.([...options, newValues]);
|
|
105
|
+
}}
|
|
106
|
+
detailForm={props.addForm || props.detailForm}
|
|
107
|
+
editForm={props?.editForm}
|
|
108
|
+
disabledSubmitter={props.disabledSubmitter}
|
|
109
|
+
>
|
|
110
|
+
{props.addTrigger || (
|
|
111
|
+
<Button size="small" icon={<PlusOutlined />}>
|
|
112
|
+
添加
|
|
113
|
+
</Button>
|
|
114
|
+
)}
|
|
115
|
+
</Edit>
|
|
116
|
+
</div>
|
|
117
|
+
)}
|
|
118
|
+
</div>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export { ProFormListModalHelper };
|
|
123
|
+
export type { ProFormListModalHelperProps };
|
package/src/form/index.tsx
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
export { ProFormListNumber, ProFormListText } from './form_list/form_list';
|
|
2
|
+
export { ProFormListHelper } from './form_list/form_list_helper';
|
|
3
|
+
export { ProFormListModalHelper } from './form_list/form_list_modal_helper';
|
|
4
|
+
|
|
1
5
|
export { ProFormEditor } from './pro_form_editor';
|
|
2
6
|
export { ProFormJavascript } from './pro_form_javascript';
|
|
3
7
|
export { ProFormJSON } from './pro_form_json';
|
|
@@ -8,12 +8,11 @@ function EditorItem(props: EditorProps) {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
function ProFormEditor(props: ProFormItemProps<EditorProps>) {
|
|
11
|
-
|
|
12
|
-
const { fieldProps, readonly, ...rest } = props;
|
|
11
|
+
const { fieldProps, ...rest } = props;
|
|
13
12
|
|
|
14
13
|
return (
|
|
15
14
|
<ProForm.Item {...rest}>
|
|
16
|
-
<EditorItem
|
|
15
|
+
<EditorItem {...fieldProps} />
|
|
17
16
|
</ProForm.Item>
|
|
18
17
|
);
|
|
19
18
|
}
|
|
@@ -12,12 +12,11 @@ function JavascriptItem(props: EditorJavascriptProps) {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
function ProFormJavascript(props: ProFormItemProps<EditorJavascriptProps>) {
|
|
15
|
-
|
|
16
|
-
const { fieldProps, readonly, ...rest } = props;
|
|
15
|
+
const { fieldProps, ...rest } = props;
|
|
17
16
|
|
|
18
17
|
return (
|
|
19
18
|
<ProForm.Item {...rest}>
|
|
20
|
-
<JavascriptItem
|
|
19
|
+
<JavascriptItem {...(fieldProps as EditorJavascriptProps)} />
|
|
21
20
|
</ProForm.Item>
|
|
22
21
|
);
|
|
23
22
|
}
|
|
@@ -12,12 +12,11 @@ function JSONItem(props: EditorJSONProps) {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
function ProFormJSON(props: ProFormItemProps<EditorJSONProps>) {
|
|
15
|
-
|
|
16
|
-
const { fieldProps, readonly, ...rest } = props;
|
|
15
|
+
const { fieldProps, ...rest } = props;
|
|
17
16
|
|
|
18
17
|
return (
|
|
19
18
|
<ProForm.Item {...rest}>
|
|
20
|
-
<JSONItem
|
|
19
|
+
<JSONItem {...(fieldProps as EditorJSONProps)} />
|
|
21
20
|
</ProForm.Item>
|
|
22
21
|
);
|
|
23
22
|
}
|
|
@@ -25,8 +25,7 @@ function SwitchNumber(props: SwitchNumberProps) {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
function ProFormSwitchNumber(props: ProFormItemProps<SwitchNumberProps>) {
|
|
28
|
-
|
|
29
|
-
const { fieldProps, readonly, ...rest } = props;
|
|
28
|
+
const { fieldProps, ...rest } = props;
|
|
30
29
|
|
|
31
30
|
return (
|
|
32
31
|
<ProForm.Item {...rest}>
|
package/src/index.ts
CHANGED
package/src/table/index.tsx
CHANGED
|
@@ -47,11 +47,15 @@ function Table<
|
|
|
47
47
|
columns={newColumns}
|
|
48
48
|
scroll={getTableScroll(newColumns)}
|
|
49
49
|
search={
|
|
50
|
-
hasSearch
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
hasSearch
|
|
51
|
+
? {
|
|
52
|
+
labelWidth: 'auto',
|
|
53
|
+
defaultCollapsed: false,
|
|
54
|
+
...search,
|
|
55
|
+
}
|
|
56
|
+
: {
|
|
57
|
+
...search,
|
|
58
|
+
}
|
|
55
59
|
}
|
|
56
60
|
{...rest}
|
|
57
61
|
/>
|
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
import type { ProColumns } from '@ant-design/pro-components';
|
|
2
2
|
import { Table } from '@fe-free/core';
|
|
3
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
4
4
|
import { fakeData } from '../crud/demo/data';
|
|
5
5
|
|
|
6
|
-
const meta: Meta = {
|
|
6
|
+
const meta: Meta<typeof Table> = {
|
|
7
7
|
title: '@fe-free/core/Table',
|
|
8
|
+
component: Table,
|
|
8
9
|
tags: ['autodocs'],
|
|
10
|
+
parameters: {
|
|
11
|
+
docs: {
|
|
12
|
+
description: {
|
|
13
|
+
component: `Table 基于 ProTable 做了一些封装:<br>
|
|
14
|
+
- props column 需要显示的提供 search: true;
|
|
15
|
+
- 列宽默认 120,和滚动条
|
|
16
|
+
- 搜索样式做了默认设置,具体见代码
|
|
17
|
+
- 页码做了默认设置,具体见代码
|
|
18
|
+
`,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
9
22
|
};
|
|
10
23
|
|
|
11
24
|
export default meta;
|
|
12
|
-
type Story = StoryObj<typeof
|
|
25
|
+
type Story = StoryObj<typeof Table>;
|
|
13
26
|
|
|
14
27
|
// 定义列配置
|
|
15
28
|
const columns: ProColumns[] = [
|
|
@@ -51,30 +64,32 @@ export const Basic: Story = {
|
|
|
51
64
|
),
|
|
52
65
|
};
|
|
53
66
|
|
|
54
|
-
export const
|
|
67
|
+
export const ScrollX: Story = {
|
|
55
68
|
render: () => (
|
|
56
|
-
<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
69
|
+
<div className="w-[400px]">
|
|
70
|
+
<Table
|
|
71
|
+
rowKey="id"
|
|
72
|
+
columns={[
|
|
73
|
+
{
|
|
74
|
+
title: 'id',
|
|
75
|
+
dataIndex: 'id',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
title: '名字(省略)',
|
|
79
|
+
dataIndex: 'name',
|
|
65
80
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
81
|
+
ellipsis: true,
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
title: 'city',
|
|
85
|
+
dataIndex: 'city',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
title: 'area',
|
|
89
|
+
dataIndex: 'area',
|
|
90
|
+
},
|
|
91
|
+
]}
|
|
92
|
+
/>
|
|
93
|
+
</div>
|
|
79
94
|
),
|
|
80
95
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ProConfigProvider } from '@ant-design/pro-components';
|
|
2
2
|
import { CRUD, CustomValueTypeEnum, customValueTypeMap } from '@fe-free/core';
|
|
3
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
4
4
|
import dayjs from 'dayjs';
|
|
5
5
|
import { range } from 'lodash-es';
|
|
6
6
|
|