@hw-component/form 0.0.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/.babelrc +23 -0
- package/.eslintrc.js +8 -0
- package/.husky/pre-commit +4 -0
- package/.stylelintrc.js +5 -0
- package/es/Select/components/AllSelect.d.ts +7 -0
- package/es/Select/components/AllSelect.js +34 -0
- package/es/Select/components/CheckBoxOption.d.ts +7 -0
- package/es/Select/components/CheckBoxOption.js +14 -0
- package/es/Select/components/DropdownComponent.d.ts +9 -0
- package/es/Select/components/DropdownComponent.js +39 -0
- package/es/Select/components/NoFindItem.d.ts +6 -0
- package/es/Select/components/NoFindItem.js +13 -0
- package/es/Select/components/NotFoundContent.d.ts +7 -0
- package/es/Select/components/NotFoundContent.js +40 -0
- package/es/Select/defaultConfig.d.ts +7 -0
- package/es/Select/defaultConfig.js +37 -0
- package/es/Select/hooks/changeHooks.d.ts +5 -0
- package/es/Select/hooks/changeHooks.js +190 -0
- package/es/Select/hooks/norHooks.d.ts +12 -0
- package/es/Select/hooks/norHooks.js +102 -0
- package/es/Select/index.d.ts +4 -0
- package/es/Select/index.js +116 -0
- package/es/Select/index.less.js +5 -0
- package/es/Select/modal.d.ts +30 -0
- package/es/index.css +3 -0
- package/es/index.d.ts +1 -0
- package/es/index.js +3 -0
- package/lib/Select/components/AllSelect.d.ts +7 -0
- package/lib/Select/components/AllSelect.js +37 -0
- package/lib/Select/components/CheckBoxOption.d.ts +7 -0
- package/lib/Select/components/CheckBoxOption.js +17 -0
- package/lib/Select/components/DropdownComponent.d.ts +9 -0
- package/lib/Select/components/DropdownComponent.js +42 -0
- package/lib/Select/components/NoFindItem.d.ts +6 -0
- package/lib/Select/components/NoFindItem.js +16 -0
- package/lib/Select/components/NotFoundContent.d.ts +7 -0
- package/lib/Select/components/NotFoundContent.js +43 -0
- package/lib/Select/defaultConfig.d.ts +7 -0
- package/lib/Select/defaultConfig.js +40 -0
- package/lib/Select/hooks/changeHooks.d.ts +5 -0
- package/lib/Select/hooks/changeHooks.js +191 -0
- package/lib/Select/hooks/norHooks.d.ts +12 -0
- package/lib/Select/hooks/norHooks.js +104 -0
- package/lib/Select/index.d.ts +4 -0
- package/lib/Select/index.js +119 -0
- package/lib/Select/index.less.js +8 -0
- package/lib/Select/modal.d.ts +30 -0
- package/lib/index.css +3 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +8 -0
- package/package.json +80 -0
- package/public/index.html +19 -0
- package/scripts/rollup.config.js +80 -0
- package/scripts/webpack.config.js +72 -0
- package/src/Layout.tsx +61 -0
- package/src/app.tsx +33 -0
- package/src/components/Select/components/AllSelect.tsx +38 -0
- package/src/components/Select/components/CheckBoxOption.tsx +14 -0
- package/src/components/Select/components/DropdownComponent.tsx +35 -0
- package/src/components/Select/components/NoFindItem.tsx +7 -0
- package/src/components/Select/components/NotFoundContent.tsx +25 -0
- package/src/components/Select/defaultConfig.tsx +28 -0
- package/src/components/Select/hooks/changeHooks.tsx +141 -0
- package/src/components/Select/hooks/norHooks.ts +74 -0
- package/src/components/Select/index.less +5 -0
- package/src/components/Select/index.tsx +108 -0
- package/src/components/Select/modal.ts +30 -0
- package/src/components/index.tsx +1 -0
- package/src/components/typings.d.ts +11 -0
- package/src/index.less +20 -0
- package/src/index.tsx +12 -0
- package/src/pages/Select/index.tsx +54 -0
- package/src/routes.tsx +35 -0
- package/tsconfig.json +29 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Space, Checkbox } from "antd";
|
|
2
|
+
import React from "react";
|
|
3
|
+
interface ICheckBoxOptionProps {
|
|
4
|
+
label?: React.ReactNode;
|
|
5
|
+
checked: boolean;
|
|
6
|
+
}
|
|
7
|
+
export default ({ label, checked }: ICheckBoxOptionProps) => {
|
|
8
|
+
return (
|
|
9
|
+
<Space>
|
|
10
|
+
<Checkbox checked={checked} />
|
|
11
|
+
{label}
|
|
12
|
+
</Space>
|
|
13
|
+
);
|
|
14
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Spin, Row, Space, Typography } from "antd";
|
|
3
|
+
import NotFoundContent from "./NotFoundContent";
|
|
4
|
+
interface IProps {
|
|
5
|
+
loading?: boolean;
|
|
6
|
+
options?: any[];
|
|
7
|
+
error?: Error;
|
|
8
|
+
reload: VoidFunction;
|
|
9
|
+
}
|
|
10
|
+
const { Text } = Typography;
|
|
11
|
+
const Index: React.FC<IProps> = ({
|
|
12
|
+
loading,
|
|
13
|
+
error,
|
|
14
|
+
options = [],
|
|
15
|
+
reload,
|
|
16
|
+
children,
|
|
17
|
+
}) => {
|
|
18
|
+
const len = options?.length;
|
|
19
|
+
if (loading && len === 0) {
|
|
20
|
+
return (
|
|
21
|
+
<Row style={{ height: 125 }} justify="center" align={"middle"}>
|
|
22
|
+
<Space direction={"vertical"} align={"center"}>
|
|
23
|
+
<Spin />
|
|
24
|
+
<Text type={"secondary"}>拼命加载中...</Text>
|
|
25
|
+
</Space>
|
|
26
|
+
</Row>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
if (error && len === 0) {
|
|
30
|
+
return <NotFoundContent error={error} reload={reload} />;
|
|
31
|
+
}
|
|
32
|
+
return <>{children}</>;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default Index;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Empty, Row, Space, Typography, Button } from "antd";
|
|
2
|
+
import { ExclamationCircleOutlined } from "@ant-design/icons";
|
|
3
|
+
const { Text } = Typography;
|
|
4
|
+
interface IProps {
|
|
5
|
+
error?: Error;
|
|
6
|
+
reload: VoidFunction;
|
|
7
|
+
}
|
|
8
|
+
export default ({ error, reload }: IProps) => {
|
|
9
|
+
if (error) {
|
|
10
|
+
return (
|
|
11
|
+
<Row justify={"center"} align={"middle"} style={{ height: 125 }}>
|
|
12
|
+
<Space align={"center"} direction={"vertical"}>
|
|
13
|
+
<Text type={"danger"}>
|
|
14
|
+
<ExclamationCircleOutlined style={{ fontSize: 24 }} />
|
|
15
|
+
</Text>
|
|
16
|
+
<Text type={"danger"}>{error.message}</Text>
|
|
17
|
+
<Button type="primary" size={"small"} onClick={reload}>
|
|
18
|
+
重新加载
|
|
19
|
+
</Button>
|
|
20
|
+
</Space>
|
|
21
|
+
</Row>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
return <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />;
|
|
25
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import CheckBoxOption from "./components/CheckBoxOption";
|
|
2
|
+
import NoFindItem from "./components/NoFindItem";
|
|
3
|
+
import type { HSelectProps } from "@/components/Select/modal";
|
|
4
|
+
|
|
5
|
+
export const defaultModeConfig: HSelectProps["modeConfig"] = {
|
|
6
|
+
multiple: {
|
|
7
|
+
icon: null,
|
|
8
|
+
render: (item, value) => {
|
|
9
|
+
const checkVal = value?.map((itemVal) => {
|
|
10
|
+
return itemVal.value;
|
|
11
|
+
});
|
|
12
|
+
const newVal = checkVal || [];
|
|
13
|
+
const checked = newVal.indexOf(item.value) !== -1;
|
|
14
|
+
return <CheckBoxOption label={item.label} checked={checked} />;
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const defaultFieldNames: HSelectProps["fieldNames"] = {
|
|
20
|
+
label: "label",
|
|
21
|
+
value: "value",
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const defaultSelectConfig = {
|
|
25
|
+
noMatchItemRender: () => {
|
|
26
|
+
return <NoFindItem label={"选项被删除,请重新选择"} />;
|
|
27
|
+
},
|
|
28
|
+
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
OptionType,
|
|
3
|
+
PartialHSelectProps,
|
|
4
|
+
} from "@/components/Select/modal";
|
|
5
|
+
import { useEffect, useState } from "react";
|
|
6
|
+
import type { FilterDataModal } from "@/components/Select/modal";
|
|
7
|
+
|
|
8
|
+
const single = ({ options, value, noMatchItemRender }: PartialHSelectProps) => {
|
|
9
|
+
const newOptions = options || [];
|
|
10
|
+
const index = newOptions.findIndex((item) => {
|
|
11
|
+
return item.value === value;
|
|
12
|
+
});
|
|
13
|
+
if (index !== -1) {
|
|
14
|
+
const { label } = newOptions[index];
|
|
15
|
+
return {
|
|
16
|
+
value,
|
|
17
|
+
label,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
value,
|
|
22
|
+
label: noMatchItemRender?.({ value }) || value,
|
|
23
|
+
};
|
|
24
|
+
}; //单选模式
|
|
25
|
+
const findNewValInOldVal = (val, oldVal?: any[]) => {
|
|
26
|
+
if (!oldVal) {
|
|
27
|
+
return -1;
|
|
28
|
+
}
|
|
29
|
+
return oldVal.findIndex((item) => {
|
|
30
|
+
return item.value === val;
|
|
31
|
+
});
|
|
32
|
+
}; //查询新增的 value
|
|
33
|
+
const sourceDataProvider = (
|
|
34
|
+
{ options, value }: PartialHSelectProps,
|
|
35
|
+
oldVal?: any[]
|
|
36
|
+
) => {
|
|
37
|
+
const oldData: FilterDataModal[] = [];
|
|
38
|
+
const newData: FilterDataModal[] = [];
|
|
39
|
+
value.forEach((item, i) => {
|
|
40
|
+
const index = findNewValInOldVal(item, oldVal);
|
|
41
|
+
if (index === -1) {
|
|
42
|
+
newData.push({
|
|
43
|
+
value: item,
|
|
44
|
+
index: i,
|
|
45
|
+
});
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const newVal = oldVal?.[index];
|
|
49
|
+
oldData.push({
|
|
50
|
+
...newVal,
|
|
51
|
+
index: i,
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
oldData,
|
|
56
|
+
newData,
|
|
57
|
+
};
|
|
58
|
+
}; //创建新旧数据
|
|
59
|
+
const resultProvider = (
|
|
60
|
+
newData: FilterDataModal[],
|
|
61
|
+
oldData: FilterDataModal[],
|
|
62
|
+
value: any[]
|
|
63
|
+
) => {
|
|
64
|
+
const newResult = new Array(value.length);
|
|
65
|
+
oldData.forEach((item) => {
|
|
66
|
+
const { index, ...val } = item;
|
|
67
|
+
newResult[index] = {
|
|
68
|
+
...val,
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
newData.forEach((item) => {
|
|
72
|
+
const { index, ...val } = item;
|
|
73
|
+
newResult[index] = {
|
|
74
|
+
...val,
|
|
75
|
+
};
|
|
76
|
+
});
|
|
77
|
+
return newResult;
|
|
78
|
+
};
|
|
79
|
+
const multiple = (
|
|
80
|
+
{ options, value, noMatchItemRender }: PartialHSelectProps,
|
|
81
|
+
oldVal?: any[]
|
|
82
|
+
) => {
|
|
83
|
+
const { newData, oldData } = sourceDataProvider({ options, value }, oldVal);
|
|
84
|
+
const newMatchVal = newData.map((item) => {
|
|
85
|
+
const { value: itemVal, index } = item;
|
|
86
|
+
const newItem = single({ options, value: itemVal, noMatchItemRender });
|
|
87
|
+
return {
|
|
88
|
+
...newItem,
|
|
89
|
+
index,
|
|
90
|
+
};
|
|
91
|
+
});
|
|
92
|
+
return resultProvider(newMatchVal, oldData, value);
|
|
93
|
+
}; //多选
|
|
94
|
+
const tag = ({ options, value }: PartialHSelectProps, oldVal?: any[]) => {
|
|
95
|
+
const { newData, oldData } = sourceDataProvider({ options, value }, oldVal);
|
|
96
|
+
return resultProvider(newData, oldData, value);
|
|
97
|
+
}; //tags模式
|
|
98
|
+
const matchNotFind = (
|
|
99
|
+
{ options, value, mode, noMatchItemRender }: PartialHSelectProps,
|
|
100
|
+
oldVale?: OptionType[]
|
|
101
|
+
) => {
|
|
102
|
+
if (!mode) {
|
|
103
|
+
return single({ options, value, noMatchItemRender });
|
|
104
|
+
}
|
|
105
|
+
if (mode === "multiple") {
|
|
106
|
+
return multiple({ options, value, noMatchItemRender }, oldVale);
|
|
107
|
+
}
|
|
108
|
+
return tag({ options, value }, oldVale);
|
|
109
|
+
}; //不匹配
|
|
110
|
+
export const useValueChange = (params: PartialHSelectProps) => {
|
|
111
|
+
const { labelInValue, onChange, value, options, mode, noMatchItemRender } =
|
|
112
|
+
params;
|
|
113
|
+
const [val, setVal] = useState<any>();
|
|
114
|
+
const change = (changeVal) => {
|
|
115
|
+
if (!onChange) {
|
|
116
|
+
setVal(changeVal);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
let newChangeVal = changeVal.value;
|
|
120
|
+
if (labelInValue) {
|
|
121
|
+
newChangeVal = changeVal;
|
|
122
|
+
}
|
|
123
|
+
if (Array.isArray(changeVal)) {
|
|
124
|
+
newChangeVal = changeVal.map((item) => {
|
|
125
|
+
return item.value;
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
onChange(newChangeVal);
|
|
129
|
+
};
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
if (options && value) {
|
|
132
|
+
setVal((oldVale) => {
|
|
133
|
+
return matchNotFind(params, oldVale);
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}, [value, options, mode, noMatchItemRender]);
|
|
137
|
+
return {
|
|
138
|
+
val,
|
|
139
|
+
change,
|
|
140
|
+
};
|
|
141
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import type {
|
|
3
|
+
HSelectProps,
|
|
4
|
+
OptionType,
|
|
5
|
+
PartialHSelectProps,
|
|
6
|
+
} from "@/components/Select/modal";
|
|
7
|
+
import { useRequest } from "ahooks";
|
|
8
|
+
|
|
9
|
+
const resultProvider = (
|
|
10
|
+
data?: any[],
|
|
11
|
+
fieldNames?: HSelectProps["fieldNames"]
|
|
12
|
+
) => {
|
|
13
|
+
return data?.map((item) => {
|
|
14
|
+
const { label = "label", value = "value" } = fieldNames || {};
|
|
15
|
+
return {
|
|
16
|
+
label: item[label],
|
|
17
|
+
value: item[value],
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
export const useOptionReq = ({
|
|
22
|
+
manual,
|
|
23
|
+
fieldNames,
|
|
24
|
+
request,
|
|
25
|
+
options,
|
|
26
|
+
serviceSearch,
|
|
27
|
+
}: PartialHSelectProps) => {
|
|
28
|
+
const [data, setData] = useState<OptionType[] | undefined>();
|
|
29
|
+
const { run, loading, error } = useRequest(
|
|
30
|
+
async (params = {}, type = "init") => {
|
|
31
|
+
if (type === "init") {
|
|
32
|
+
setData(undefined);
|
|
33
|
+
}
|
|
34
|
+
if (request) {
|
|
35
|
+
const result = await request(params);
|
|
36
|
+
return resultProvider(result, fieldNames);
|
|
37
|
+
}
|
|
38
|
+
const resultOpt = resultProvider(options, fieldNames);
|
|
39
|
+
return Promise.resolve(resultOpt);
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
manual,
|
|
43
|
+
debounceInterval: 300,
|
|
44
|
+
onSuccess: (resultData) => {
|
|
45
|
+
setData(resultData);
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
const onSearch = (inputValue: string) => {
|
|
50
|
+
if (!serviceSearch) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
run({ inputValue });
|
|
54
|
+
};
|
|
55
|
+
return {
|
|
56
|
+
run,
|
|
57
|
+
loading,
|
|
58
|
+
error,
|
|
59
|
+
data,
|
|
60
|
+
onSearch,
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const useFilterOption = ({
|
|
65
|
+
filterOption,
|
|
66
|
+
serviceSearch,
|
|
67
|
+
}: PartialHSelectProps) => {
|
|
68
|
+
if (serviceSearch) {
|
|
69
|
+
return () => {
|
|
70
|
+
return true;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return filterOption;
|
|
74
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { Select } from "antd";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { useFilterOption, useOptionReq } from "./hooks/norHooks";
|
|
4
|
+
import { useValueChange } from "./hooks/changeHooks";
|
|
5
|
+
import type { HSelectProps } from "./modal";
|
|
6
|
+
import {
|
|
7
|
+
defaultFieldNames,
|
|
8
|
+
defaultModeConfig,
|
|
9
|
+
defaultSelectConfig,
|
|
10
|
+
} from "./defaultConfig";
|
|
11
|
+
import DropdownComponent from "./components/DropdownComponent";
|
|
12
|
+
import AllSelect from "./components/AllSelect";
|
|
13
|
+
import { FieldNames } from "rc-select/lib/Select";
|
|
14
|
+
const { Option } = Select;
|
|
15
|
+
|
|
16
|
+
export default ({
|
|
17
|
+
style = { width: "100%" },
|
|
18
|
+
mode,
|
|
19
|
+
options,
|
|
20
|
+
modeConfig = defaultModeConfig,
|
|
21
|
+
value,
|
|
22
|
+
onChange,
|
|
23
|
+
fieldNames = defaultFieldNames,
|
|
24
|
+
request,
|
|
25
|
+
manual,
|
|
26
|
+
optionLabelProp = "label",
|
|
27
|
+
filterProvider,
|
|
28
|
+
optionFilterProp = "filterlabel",
|
|
29
|
+
serviceSearch,
|
|
30
|
+
onSearch: propsOnSearch,
|
|
31
|
+
filterOption,
|
|
32
|
+
showSearch,
|
|
33
|
+
labelInValue,
|
|
34
|
+
noMatchItemRender = defaultSelectConfig.noMatchItemRender,
|
|
35
|
+
allSelect,
|
|
36
|
+
...props
|
|
37
|
+
}: HSelectProps) => {
|
|
38
|
+
const { icon, render } = modeConfig?.[mode || ""] || {};
|
|
39
|
+
const selfFilterOption = useFilterOption({ filterOption, serviceSearch });
|
|
40
|
+
const { run, loading, data, error, onSearch } = useOptionReq({
|
|
41
|
+
options,
|
|
42
|
+
manual,
|
|
43
|
+
fieldNames,
|
|
44
|
+
request,
|
|
45
|
+
serviceSearch,
|
|
46
|
+
});
|
|
47
|
+
const { val, change } = useValueChange({
|
|
48
|
+
labelInValue,
|
|
49
|
+
onChange,
|
|
50
|
+
value,
|
|
51
|
+
options: data,
|
|
52
|
+
mode,
|
|
53
|
+
noMatchItemRender,
|
|
54
|
+
});
|
|
55
|
+
return (
|
|
56
|
+
<Select
|
|
57
|
+
style={style}
|
|
58
|
+
mode={mode}
|
|
59
|
+
loading={loading}
|
|
60
|
+
value={val}
|
|
61
|
+
onSearch={propsOnSearch || onSearch}
|
|
62
|
+
onChange={change}
|
|
63
|
+
dropdownRender={(node) => {
|
|
64
|
+
return (
|
|
65
|
+
<DropdownComponent
|
|
66
|
+
loading={loading}
|
|
67
|
+
reload={run}
|
|
68
|
+
error={error}
|
|
69
|
+
options={data}
|
|
70
|
+
>
|
|
71
|
+
<AllSelect
|
|
72
|
+
allSelect={allSelect}
|
|
73
|
+
options={data}
|
|
74
|
+
mode={mode}
|
|
75
|
+
value={val}
|
|
76
|
+
onChange={change}
|
|
77
|
+
/>
|
|
78
|
+
{node}
|
|
79
|
+
</DropdownComponent>
|
|
80
|
+
);
|
|
81
|
+
}}
|
|
82
|
+
optionLabelProp={optionLabelProp}
|
|
83
|
+
menuItemSelectedIcon={icon}
|
|
84
|
+
optionFilterProp={optionFilterProp}
|
|
85
|
+
filterOption={selfFilterOption}
|
|
86
|
+
showSearch={showSearch}
|
|
87
|
+
labelInValue={true}
|
|
88
|
+
{...props}
|
|
89
|
+
>
|
|
90
|
+
{data?.map((item) => {
|
|
91
|
+
const { value: optionValue, label } = item;
|
|
92
|
+
const result = filterProvider?.(item) || label;
|
|
93
|
+
const filer = { [optionFilterProp]: result };
|
|
94
|
+
return (
|
|
95
|
+
<Option
|
|
96
|
+
value={optionValue}
|
|
97
|
+
key={optionValue}
|
|
98
|
+
label={label}
|
|
99
|
+
mode={mode}
|
|
100
|
+
{...filer}
|
|
101
|
+
>
|
|
102
|
+
{render ? render(item, val) : label}
|
|
103
|
+
</Option>
|
|
104
|
+
);
|
|
105
|
+
})}
|
|
106
|
+
</Select>
|
|
107
|
+
);
|
|
108
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { SelectProps } from "antd";
|
|
2
|
+
import type React from "react";
|
|
3
|
+
|
|
4
|
+
export type OptionType = Record<string, any>;
|
|
5
|
+
export type PartialHSelectProps = Partial<HSelectProps>;
|
|
6
|
+
export type RenderFn = (data: OptionType) => React.ReactNode;
|
|
7
|
+
interface ModeConfigItem {
|
|
8
|
+
icon?: React.ReactNode | null;
|
|
9
|
+
render?: (item: OptionType, value: any[]) => React.ReactNode;
|
|
10
|
+
}
|
|
11
|
+
export interface ModeConfig {
|
|
12
|
+
multiple?: ModeConfigItem;
|
|
13
|
+
tags?: ModeConfigItem;
|
|
14
|
+
}
|
|
15
|
+
export interface HSelectProps extends Omit<SelectProps, "options"> {
|
|
16
|
+
style?: React.CSSProperties;
|
|
17
|
+
request?: (params: any) => Promise<OptionType[]>;
|
|
18
|
+
manual?: boolean;
|
|
19
|
+
modeConfig?: ModeConfig;
|
|
20
|
+
onChange?: (val: any) => void;
|
|
21
|
+
filterProvider?: (item: any) => string;
|
|
22
|
+
serviceSearch?: boolean;
|
|
23
|
+
options?: OptionType[];
|
|
24
|
+
noMatchItemRender?: RenderFn;
|
|
25
|
+
allSelect?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface FilterDataModal {
|
|
28
|
+
value: any;
|
|
29
|
+
index: number;
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {default as HSelect} from './Select'
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
declare module "*.css";
|
|
2
|
+
declare module "*.less";
|
|
3
|
+
declare module "*.scss";
|
|
4
|
+
declare module "*.sass";
|
|
5
|
+
declare module "*.svg";
|
|
6
|
+
declare module "*.png";
|
|
7
|
+
declare module "*.jpg";
|
|
8
|
+
declare module "*.jpeg";
|
|
9
|
+
declare module "*.gif";
|
|
10
|
+
declare module "*.bmp";
|
|
11
|
+
declare module "*.tiff";
|
package/src/index.less
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
.layout {
|
|
2
|
+
position: fixed;
|
|
3
|
+
top: 0;
|
|
4
|
+
right: 0;
|
|
5
|
+
bottom: 0;
|
|
6
|
+
left: 0;
|
|
7
|
+
display: flex;
|
|
8
|
+
}
|
|
9
|
+
.menu {
|
|
10
|
+
width: 256px !important;
|
|
11
|
+
height: 100vh;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.body {
|
|
15
|
+
width: calc(100vw - 256px);
|
|
16
|
+
height: 100vh;
|
|
17
|
+
padding: 16px;
|
|
18
|
+
overflow: hidden;
|
|
19
|
+
background-color: #fff;
|
|
20
|
+
}
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { render } from "react-dom";
|
|
2
|
+
import App from "./app";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import "antd/dist/antd.css";
|
|
5
|
+
import zhCN from "antd/es/locale/zh_CN";
|
|
6
|
+
import { ConfigProvider } from "antd";
|
|
7
|
+
render(
|
|
8
|
+
<ConfigProvider locale={zhCN}>
|
|
9
|
+
<App />
|
|
10
|
+
</ConfigProvider>,
|
|
11
|
+
document.getElementById("root")
|
|
12
|
+
);
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { HSelect } from "../../components";
|
|
2
|
+
import { Space, Card } from "antd";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
export default () => {
|
|
5
|
+
return (
|
|
6
|
+
<Space size={"large"} direction={"vertical"} style={{ width: "100%" }}>
|
|
7
|
+
<HSelect
|
|
8
|
+
options={[{ label: "测试", value: 1 }]}
|
|
9
|
+
value={100}
|
|
10
|
+
placeholder="基础"
|
|
11
|
+
/>
|
|
12
|
+
<HSelect
|
|
13
|
+
fieldNames={{ label: "name", value: "value" }}
|
|
14
|
+
options={[
|
|
15
|
+
{ name: "测试1", value: 10 },
|
|
16
|
+
{ name: "测试2", value: 20 },
|
|
17
|
+
]}
|
|
18
|
+
placeholder="多选"
|
|
19
|
+
mode={"multiple"}
|
|
20
|
+
allSelect={true}
|
|
21
|
+
/>
|
|
22
|
+
<HSelect
|
|
23
|
+
mode={"tags"}
|
|
24
|
+
placeholder="tags模式"
|
|
25
|
+
showSearch={true}
|
|
26
|
+
options={[
|
|
27
|
+
{ label: "测试1", value: 10 },
|
|
28
|
+
{ label: "测试2", value: 20 },
|
|
29
|
+
]}
|
|
30
|
+
/>
|
|
31
|
+
<HSelect
|
|
32
|
+
serviceSearch={true}
|
|
33
|
+
request={(params) => {
|
|
34
|
+
return new Promise((resolve) => {
|
|
35
|
+
setTimeout(() => {
|
|
36
|
+
resolve([
|
|
37
|
+
{
|
|
38
|
+
label: `我是搜索文案${params.inputValue}`,
|
|
39
|
+
value: new Date().valueOf(),
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
label: `我是搜索文案${params.inputValue}`,
|
|
43
|
+
value: new Date().valueOf() + 1,
|
|
44
|
+
},
|
|
45
|
+
]);
|
|
46
|
+
}, 2000);
|
|
47
|
+
});
|
|
48
|
+
}}
|
|
49
|
+
placeholder="远程搜索"
|
|
50
|
+
mode={"multiple"}
|
|
51
|
+
/>
|
|
52
|
+
</Space>
|
|
53
|
+
);
|
|
54
|
+
};
|
package/src/routes.tsx
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Navigate } from "react-router-dom";
|
|
3
|
+
import Select from "./pages/Select";
|
|
4
|
+
export interface RouteModal {
|
|
5
|
+
path?: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
children?: RouteModal[];
|
|
8
|
+
element?: JSX.Element;
|
|
9
|
+
index?: boolean;
|
|
10
|
+
errorElement?: JSX.Element;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const routes: RouteModal[] = [
|
|
14
|
+
{
|
|
15
|
+
index: true,
|
|
16
|
+
element: <Navigate to="/form/select" replace={true} />,
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
path: "/form",
|
|
20
|
+
name: "表单",
|
|
21
|
+
children: [
|
|
22
|
+
{
|
|
23
|
+
path: "/form/select",
|
|
24
|
+
name: "下拉框",
|
|
25
|
+
element: <Select />,
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
path: "/table",
|
|
31
|
+
name: "列表",
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
export default routes;
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"allowUnreachableCode": true,
|
|
4
|
+
"allowUnusedLabels": false,
|
|
5
|
+
"alwaysStrict": false,
|
|
6
|
+
"baseUrl": ".",
|
|
7
|
+
"experimentalDecorators": true,
|
|
8
|
+
"jsx": "preserve",
|
|
9
|
+
"sourceMap": true,
|
|
10
|
+
"module": "ESNext",
|
|
11
|
+
"noImplicitAny": false,
|
|
12
|
+
"removeComments": true,
|
|
13
|
+
"allowSyntheticDefaultImports": true,
|
|
14
|
+
"moduleResolution": "Node",
|
|
15
|
+
"strict": true,
|
|
16
|
+
"types": ["node"],
|
|
17
|
+
"target": "ESNext",
|
|
18
|
+
"outDir": "./build",
|
|
19
|
+
"declaration": true,
|
|
20
|
+
"allowJs": true,
|
|
21
|
+
"lib": ["es5", "es2015", "es2016", "es2017", "es2018", "dom"],
|
|
22
|
+
"typeRoots": ["./node_modules/@types/", "./src/typings.d.ts"],
|
|
23
|
+
"paths": {
|
|
24
|
+
"@/*": ["./src/*"]
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"include": ["src/**/*"],
|
|
28
|
+
"exclude": ["node_modules", "**/*.spec.ts", "**/*.css", "**/*.less"]
|
|
29
|
+
}
|