@ecoding/components.antd 0.3.57 → 0.3.59

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.
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import type { UploadFile } from 'antd';
3
+ interface IProps {
4
+ message?: string;
5
+ showMessage?: boolean;
6
+ actionParams?: any;
7
+ i18n?: any;
8
+ value?: UploadFile[] | string[];
9
+ headers?: any;
10
+ data?: any;
11
+ gif?: boolean;
12
+ disabled?: boolean;
13
+ isTip?: boolean;
14
+ name?: string;
15
+ action: string | (() => string);
16
+ buttonText?: string;
17
+ maxCount?: number;
18
+ onChange?: (infos: string[]) => void;
19
+ }
20
+ /**
21
+ * @returns 返回地址的string
22
+ */
23
+ declare const MultipleImgUpload: React.FC<IProps>;
24
+ export default MultipleImgUpload;
@@ -0,0 +1,154 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import React, { useState } from 'react';
11
+ import { Upload, Image } from 'antd';
12
+ import { PlusOutlined } from '@ant-design/icons';
13
+ import Toast from "../../core/toast";
14
+ import Loading from "../../core/loading";
15
+ import { DndContext, PointerSensor, useSensor } from '@dnd-kit/core';
16
+ import { arrayMove, SortableContext, useSortable, horizontalListSortingStrategy, } from '@dnd-kit/sortable';
17
+ import { CSS } from '@dnd-kit/utilities';
18
+ const DraggableUploadListItem = ({ originNode, file }) => {
19
+ const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
20
+ id: file.uid,
21
+ });
22
+ const style = {
23
+ transform: CSS.Translate.toString(transform),
24
+ transition,
25
+ cursor: 'move',
26
+ height: '102px',
27
+ width: '102px',
28
+ };
29
+ return (React.createElement("div", Object.assign({ ref: setNodeRef, style: style,
30
+ // prevent preview event when drag end
31
+ className: isDragging ? 'is-dragging' : '' }, attributes, listeners), file.status === 'error' && isDragging ? originNode.props.children : originNode));
32
+ };
33
+ /**
34
+ * @returns 返回地址的string
35
+ */
36
+ const MultipleImgUpload = (props) => {
37
+ const { action, name, buttonText, maxCount, disabled, value, onChange } = props;
38
+ const [imgList, setImgList] = useState((value === null || value === void 0 ? void 0 : value.map((url, index) => {
39
+ if (typeof url === "string") {
40
+ return {
41
+ uid: String(index),
42
+ status: 'done',
43
+ url,
44
+ name: url.substring(url.lastIndexOf('/') + 1, url.lastIndexOf('.'))
45
+ };
46
+ }
47
+ else {
48
+ return url;
49
+ }
50
+ })) || []);
51
+ const updateItems = (newItems) => {
52
+ setImgList(newItems);
53
+ let isEmpty = true;
54
+ const urls = newItems.map((item) => item.url);
55
+ urls.forEach((item) => {
56
+ if (item) {
57
+ isEmpty = false;
58
+ return;
59
+ }
60
+ });
61
+ onChange && (onChange === null || onChange === void 0 ? void 0 : onChange(!isEmpty ? urls : undefined));
62
+ };
63
+ const handleChange = (info) => {
64
+ switch (info.file.status) {
65
+ case 'uploading':
66
+ Loading.show();
67
+ break;
68
+ case 'done': {
69
+ Loading.hide();
70
+ const response = info.file.response;
71
+ if (response && response.code === 200) {
72
+ const data = response.data || {};
73
+ const temp = imgList.concat([Object.assign({}, data)]);
74
+ updateItems(temp);
75
+ }
76
+ else {
77
+ Toast.error({
78
+ mask: true,
79
+ title: response.message || '服务出错,图片上传失败'
80
+ });
81
+ }
82
+ break;
83
+ }
84
+ case 'error': {
85
+ const response = info.file.response;
86
+ console.log(response.data);
87
+ Toast.error({
88
+ mask: true,
89
+ title: response.message || '服务出错,图片上传失败'
90
+ });
91
+ Loading.hide();
92
+ break;
93
+ }
94
+ default:
95
+ break;
96
+ }
97
+ };
98
+ const handleRemove = (file) => {
99
+ const lefts = imgList.filter(item => item.uid !== file.uid);
100
+ updateItems(lefts);
101
+ };
102
+ const [previewOpen, setPreviewOpen] = useState(false);
103
+ const [previewImage, setPreviewImage] = useState('');
104
+ const getBase64 = (file) => new Promise((resolve, reject) => {
105
+ const reader = new FileReader();
106
+ reader.readAsDataURL(file);
107
+ reader.onload = () => resolve(reader.result);
108
+ reader.onerror = (error) => reject(error);
109
+ });
110
+ const handlePreview = (file) => __awaiter(void 0, void 0, void 0, function* () {
111
+ if (!file.url && !file.preview) {
112
+ file.preview = yield getBase64(file.originFileObj);
113
+ }
114
+ setPreviewImage(file.url || file.preview);
115
+ setPreviewOpen(true);
116
+ });
117
+ const uploadButton = (React.createElement("button", { style: { border: 0, background: 'none' }, type: "button" },
118
+ React.createElement(PlusOutlined, null),
119
+ React.createElement("div", { style: { marginTop: 8 } }, buttonText ? buttonText : '上传')));
120
+ const sensor = useSensor(PointerSensor, {
121
+ activationConstraint: { distance: 10 },
122
+ });
123
+ const onDragEnd = ({ active, over }) => {
124
+ if (!imgList || imgList.length == 0) {
125
+ return;
126
+ }
127
+ if (active.id !== (over === null || over === void 0 ? void 0 : over.id)) {
128
+ const temp = [...imgList];
129
+ const activeIndex = temp.findIndex((i) => i.uid === active.id);
130
+ const overIndex = temp.findIndex((i) => i.uid === (over === null || over === void 0 ? void 0 : over.id));
131
+ // 使用arrayMove计算新的排序结果
132
+ const newItems = arrayMove(temp, activeIndex, overIndex);
133
+ updateItems(newItems);
134
+ }
135
+ };
136
+ return (React.createElement(DndContext, { sensors: [sensor], onDragEnd: onDragEnd },
137
+ React.createElement(SortableContext, { items: imgList === null || imgList === void 0 ? void 0 : imgList.map((i) => i.uid), strategy: horizontalListSortingStrategy },
138
+ React.createElement(Upload, { listType: "picture-card", fileList: imgList, action: action, onPreview: handlePreview, onChange: handleChange, onRemove: handleRemove, name: name, multiple: true, disabled: disabled, withCredentials: true, itemRender: (originNode, file) => (React.createElement(DraggableUploadListItem, { originNode: originNode, file: file })) }, maxCount && imgList.length >= maxCount ? null : uploadButton),
139
+ previewImage && (React.createElement(Image, { wrapperStyle: { display: 'none' }, preview: {
140
+ visible: previewOpen,
141
+ onVisibleChange: (visible) => setPreviewOpen(visible),
142
+ afterOpenChange: (visible) => !visible && setPreviewImage('')
143
+ }, src: previewImage })))));
144
+ };
145
+ MultipleImgUpload.defaultProps = {
146
+ action: "/api/upload/img",
147
+ name: "file",
148
+ gif: false,
149
+ buttonText: '上传图片',
150
+ data: {},
151
+ isTip: true,
152
+ actionParams: {},
153
+ };
154
+ export default MultipleImgUpload;
@@ -1,5 +1,5 @@
1
1
  import React, { useEffect, useState } from 'react';
2
- import { Space, Alert } from 'antd';
2
+ import { Flex, Alert } from 'antd';
3
3
  import { DragOutlined } from '@ant-design/icons';
4
4
  import { DndContext, closestCenter, PointerSensor, useSensor, useSensors } from '@dnd-kit/core';
5
5
  import { arrayMove, SortableContext, horizontalListSortingStrategy, useSortable } from '@dnd-kit/sortable';
@@ -14,7 +14,8 @@ const SortableItem = (props) => {
14
14
  transform: CSS.Transform.toString(transform),
15
15
  transition,
16
16
  position: 'relative',
17
- margin: '0 8px'
17
+ margin: '0 8px',
18
+ fontSize: 0
18
19
  };
19
20
  const handleChange = (url) => {
20
21
  const newItems = [...items];
@@ -36,7 +37,15 @@ const SortableItem = (props) => {
36
37
  alignItems: 'center',
37
38
  justifyContent: 'center'
38
39
  } }),
39
- React.createElement(DragOutlined, null)),
40
+ React.createElement(DragOutlined, { style: { fontSize: 14 } })),
41
+ index == 0 ? (React.createElement("div", { style: {
42
+ position: 'absolute',
43
+ bottom: 0,
44
+ left: 0,
45
+ padding: '0 2px',
46
+ fontSize: '12px',
47
+ background: 'rgba(0,0,0,0.1)',
48
+ } }, "\u4E3B\u56FE")) : null,
40
49
  React.createElement(ImgUpload, Object.assign({}, props, { value: props.value, onChange: handleChange }))));
41
50
  };
42
51
  const MultiPileImgUpload = (props) => {
@@ -56,7 +65,15 @@ const MultiPileImgUpload = (props) => {
56
65
  const updateItems = (newItems) => {
57
66
  var _a;
58
67
  setItems(newItems);
59
- props.onChange && ((_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, newItems.map((item) => item.url)));
68
+ let isEmpty = true;
69
+ const urls = newItems.map((item) => item.url);
70
+ urls.forEach((item) => {
71
+ if (item) {
72
+ isEmpty = false;
73
+ return;
74
+ }
75
+ });
76
+ props.onChange && ((_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, !isEmpty ? urls : undefined));
60
77
  };
61
78
  useEffect(() => {
62
79
  const initItems = Array(props.max)
@@ -74,8 +91,8 @@ const MultiPileImgUpload = (props) => {
74
91
  setItems(initItems);
75
92
  }
76
93
  }, [props.value]);
77
- return (React.createElement("div", null,
78
- props.showMessage && (React.createElement(Alert, { className: 'mb20', message: props.message ? props.message : (React.createElement(Space, null,
94
+ return (React.createElement(React.Fragment, null,
95
+ props.showMessage && (React.createElement(Alert, { className: 'mb20', message: props.message ? props.message : (React.createElement(Flex, { gap: 10 },
79
96
  React.createElement("div", null,
80
97
  props.i18n ? props.i18n.$t("global.size", "大小") : "大小",
81
98
  "\uFF1A",
@@ -97,7 +114,7 @@ const MultiPileImgUpload = (props) => {
97
114
  ";"))), type: "warning", showIcon: true })),
98
115
  React.createElement(DndContext, { sensors: sensors, collisionDetection: closestCenter, onDragEnd: handleDragEnd },
99
116
  React.createElement(SortableContext, { items: items, strategy: horizontalListSortingStrategy },
100
- React.createElement(Space, { wrap: true, align: "start" }, items.map((item, index) => (React.createElement(SortableItem, Object.assign({}, props, { index: index, items: items, updateItems: updateItems, value: item.url, key: item.id, id: item.id })))))))));
117
+ React.createElement(Flex, { wrap: true, align: "start" }, items.map((item, index) => (React.createElement(SortableItem, Object.assign({}, props, { index: index, items: items, updateItems: updateItems, value: item.url, key: item.id, id: item.id })))))))));
101
118
  };
102
119
  MultiPileImgUpload.defaultProps = {
103
120
  showMessage: true,
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import React, { useCallback, useEffect, useMemo, useState } from "react";
11
- import { Upload, message, Space, Image as Img } from "antd";
11
+ import { Upload, message, Flex, Image as Img } from "antd";
12
12
  import { LoadingOutlined, PlusOutlined, DeleteOutlined } from "@ant-design/icons";
13
13
  import { buildURL } from "@ecoding/helper.url";
14
14
  import Toast from "../../core/toast";
@@ -123,7 +123,7 @@ const ImgUpload = (props) => {
123
123
  setImageUrl(props.value);
124
124
  }
125
125
  }, [props.value]);
126
- return (React.createElement(Space, null,
126
+ return (React.createElement(Flex, { style: { fontSize: 0 } },
127
127
  imageUrl ? (React.createElement("div", { style: { position: "relative" } },
128
128
  React.createElement("span", { style: {
129
129
  position: "absolute",
@@ -133,14 +133,13 @@ const ImgUpload = (props) => {
133
133
  height: "18px",
134
134
  opacity: ".9",
135
135
  cursor: "pointer",
136
- zIndex: 10
137
136
  }, onClick: (e) => {
138
137
  e.stopPropagation();
139
138
  clear();
140
139
  } },
141
- React.createElement(DeleteOutlined, null)),
140
+ React.createElement(DeleteOutlined, { style: { fontSize: 14 } })),
142
141
  React.createElement(Img, { style: { width: "102px", height: "102px", objectFit: "contain", cursor: "pointer" }, src: imageUrl }))) : (React.createElement(Upload, { withCredentials: true, beforeUpload: beforeUpload, name: props.name, data: props.data, headers: props.headers, disabled: props.disabled, listType: "picture-card", showUploadList: false, action: action, onChange: handleChange }, uploadButton)),
143
- props.isTip ? (React.createElement("div", null,
142
+ props.isTip ? (React.createElement("div", { style: { fontSize: '13px', marginLeft: '18px', lineHeight: '30px' } },
144
143
  React.createElement("p", null,
145
144
  props.i18n ? props.i18n.$t("global.size", "大小") : "大小",
146
145
  "\uFF1A",
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ interface IProps {
3
+ value?: string[];
4
+ onChange?: any;
5
+ className?: string;
6
+ disabled?: boolean;
7
+ fixedFirst?: boolean;
8
+ addTagText?: string;
9
+ }
10
+ declare const C: React.FC<IProps>;
11
+ export default C;
@@ -0,0 +1,97 @@
1
+ import React, { useEffect, useRef, useState } from 'react';
2
+ import { PlusOutlined } from '@ant-design/icons';
3
+ import { isEqual } from "@ecoding/helper.is";
4
+ import { Flex, Input, Tag, theme, Tooltip } from 'antd';
5
+ const tagInputStyle = {
6
+ width: 64,
7
+ height: 22,
8
+ marginInlineEnd: 8,
9
+ verticalAlign: 'top'
10
+ };
11
+ const C = (props) => {
12
+ const { token } = theme.useToken();
13
+ const [tags, setTags] = useState([]);
14
+ const [inputVisible, setInputVisible] = useState(false);
15
+ const [inputValue, setInputValue] = useState('');
16
+ const [editInputIndex, setEditInputIndex] = useState(-1);
17
+ const [editInputValue, setEditInputValue] = useState('');
18
+ const inputRef = useRef(null);
19
+ const editInputRef = useRef(null);
20
+ useEffect(() => {
21
+ var _a;
22
+ if (inputVisible) {
23
+ (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
24
+ }
25
+ }, [inputVisible]);
26
+ useEffect(() => {
27
+ var _a;
28
+ (_a = editInputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
29
+ }, [editInputValue]);
30
+ const handleClose = (removedTag) => {
31
+ const newTags = tags.filter((tag) => tag !== removedTag);
32
+ setTags(newTags);
33
+ props.onChange && props.onChange(newTags && newTags.length > 0 ? newTags : undefined);
34
+ };
35
+ const showInput = () => {
36
+ setInputVisible(true);
37
+ };
38
+ const handleInputChange = (e) => {
39
+ setInputValue(e.target.value);
40
+ };
41
+ const handleInputConfirm = () => {
42
+ if (inputValue && !tags.includes(inputValue)) {
43
+ const values = [...tags, inputValue];
44
+ setTags(values);
45
+ props.onChange && props.onChange(values && values.length > 0 ? values : undefined);
46
+ }
47
+ setInputVisible(false);
48
+ setInputValue('');
49
+ };
50
+ const handleEditInputChange = (e) => {
51
+ setEditInputValue(e.target.value);
52
+ };
53
+ const handleEditInputConfirm = () => {
54
+ const newTags = [...(tags || [])];
55
+ newTags[editInputIndex] = editInputValue;
56
+ setTags(newTags);
57
+ props.onChange && props.onChange(newTags && newTags.length > 0 ? newTags : undefined);
58
+ setEditInputIndex(-1);
59
+ setEditInputValue('');
60
+ };
61
+ const tagPlusStyle = {
62
+ height: 22,
63
+ background: token.colorBgContainer,
64
+ borderStyle: 'dashed'
65
+ };
66
+ useEffect(() => {
67
+ if (props.value && !isEqual(props.value, tags)) {
68
+ setTags(props.value);
69
+ }
70
+ }, [props.value]);
71
+ return (React.createElement(Flex, { gap: "4px 0", wrap: "wrap" },
72
+ tags.map((tag, index) => {
73
+ if (editInputIndex === index) {
74
+ return (React.createElement(Input, { ref: editInputRef, key: tag, size: "small", style: tagInputStyle, value: editInputValue, onChange: handleEditInputChange, onBlur: handleEditInputConfirm, onPressEnter: handleEditInputConfirm }));
75
+ }
76
+ const isLongTag = tag.length > 20;
77
+ const tagElem = (React.createElement(Tag, { key: tag, closable: props.fixedFirst ? index !== 0 : true, style: { userSelect: 'none' }, onClose: () => handleClose(tag) },
78
+ React.createElement("span", { onDoubleClick: (e) => {
79
+ if (props.disabled) {
80
+ return;
81
+ }
82
+ if (props.fixedFirst ? index !== 0 : true) {
83
+ setEditInputIndex(index);
84
+ setEditInputValue(tag);
85
+ e.preventDefault();
86
+ }
87
+ } }, isLongTag ? `${tag.slice(0, 20)}...` : tag)));
88
+ return isLongTag ? (React.createElement(Tooltip, { title: tag, key: tag }, tagElem)) : (tagElem);
89
+ }),
90
+ props.disabled ? null : inputVisible ? (React.createElement(Input, { ref: inputRef, type: "text", size: "small", style: tagInputStyle, value: inputValue, onChange: handleInputChange, onBlur: handleInputConfirm, onPressEnter: handleInputConfirm })) : (React.createElement(Tag, { style: tagPlusStyle, icon: React.createElement(PlusOutlined, null), onClick: showInput }, props.addTagText))));
91
+ };
92
+ C.defaultProps = {
93
+ disabled: false,
94
+ fixedFirst: false,
95
+ addTagText: 'New Tag'
96
+ };
97
+ export default C;
package/lib/index.d.ts CHANGED
@@ -12,6 +12,7 @@ export { default as RangePicker } from "./core/range-picker";
12
12
  export { default as DatePicker } from "./core/date.picker";
13
13
  export { default as SingleImgUpload } from "./core/single-img-upload";
14
14
  export { default as MultipleSingleImgUpload } from "./core/multiple-single-img-upload";
15
+ export { default as MultipleImgUpload } from "./core/multiple-img-upload";
15
16
  export { default as SingleFileUpload } from "./core/single-file-upload";
16
17
  export { default as MultipleUpload } from "./core/multiple-upload";
17
18
  export { default as FormLabel } from "./core/form.label";
@@ -19,5 +20,6 @@ export { default as FormLabelAttachment } from "./core/form.label.attachment";
19
20
  export { default as FormList } from "./core/form.list";
20
21
  export { default as AsyncSelect } from "./core/async-select";
21
22
  export { default as AsyncTransfer } from "./core/async-transfer";
23
+ export { default as TagItems } from "./core/tag.items";
22
24
  export { default as TablePro } from "./core/table-pro";
23
25
  export { default as http } from "./helpers/http";
package/lib/index.js CHANGED
@@ -12,6 +12,7 @@ export { default as RangePicker } from "./core/range-picker";
12
12
  export { default as DatePicker } from "./core/date.picker";
13
13
  export { default as SingleImgUpload } from "./core/single-img-upload";
14
14
  export { default as MultipleSingleImgUpload } from "./core/multiple-single-img-upload";
15
+ export { default as MultipleImgUpload } from "./core/multiple-img-upload";
15
16
  export { default as SingleFileUpload } from "./core/single-file-upload";
16
17
  export { default as MultipleUpload } from "./core/multiple-upload";
17
18
  export { default as FormLabel } from "./core/form.label";
@@ -19,5 +20,6 @@ export { default as FormLabelAttachment } from "./core/form.label.attachment";
19
20
  export { default as FormList } from "./core/form.list";
20
21
  export { default as AsyncSelect } from "./core/async-select";
21
22
  export { default as AsyncTransfer } from "./core/async-transfer";
23
+ export { default as TagItems } from "./core/tag.items";
22
24
  export { default as TablePro } from "./core/table-pro";
23
25
  export { default as http } from "./helpers/http";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ecoding/components.antd",
3
- "version": "0.3.57",
3
+ "version": "0.3.59",
4
4
  "author": "cxc",
5
5
  "homepage": "",
6
6
  "license": "MIT",
@@ -24,6 +24,8 @@
24
24
  "build": "rm -rf lib && tsc && rollup -c"
25
25
  },
26
26
  "peerDependencies": {
27
+ "@dnd-kit/core": ">=6.3.1",
28
+ "@dnd-kit/sortable": ">=10.0.0",
27
29
  "@ecoding/helper.event": "*",
28
30
  "@ecoding/helper.is": "*",
29
31
  "@ecoding/helper.json": "*",
@@ -45,5 +47,5 @@
45
47
  "antd": "5.27.0",
46
48
  "axios": "^1.1.2"
47
49
  },
48
- "gitHead": "2a522cbf03eb8695fb6abf0d8df807743fd7fdd9"
50
+ "gitHead": "7c271775a18b32dedae8fea1707efcdadef6592f"
49
51
  }