@d-matrix/utils 1.7.0 → 1.9.0
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/algorithm.js +7 -16
- package/dist/clipboard.js +45 -79
- package/dist/date.js +10 -19
- package/dist/dom.js +3 -8
- package/dist/file.d.ts +10 -0
- package/dist/file.js +40 -63
- package/dist/index.js +8 -30
- package/dist/react/enhancedComponent.d.ts +12 -0
- package/dist/react/enhancedComponent.js +16 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +7 -17
- package/dist/react/renderToString.js +7 -15
- package/dist/react/useCopyToClipboard.js +14 -18
- package/dist/react/useDeepCompareRef.d.ts +2 -0
- package/dist/react/useDeepCompareRef.js +11 -0
- package/dist/react/useDisableContextMenu.js +8 -13
- package/dist/react/useIsMounted.js +6 -10
- package/dist/react/useStateCallback.js +6 -10
- package/dist/support.js +3 -9
- package/dist/timer.d.ts +5 -0
- package/dist/timer.js +5 -0
- package/dist/types.js +1 -2
- package/package.json +8 -2
- package/readme.md +51 -0
package/dist/algorithm.js
CHANGED
|
@@ -1,21 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
return to;
|
|
6
|
-
};
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.moveMulti = void 0;
|
|
9
|
-
var removeSymbol = Symbol('Placeholder for removed element');
|
|
10
|
-
var moveMulti = function (arr, indexes, start) {
|
|
11
|
-
var cloned = arr.slice();
|
|
12
|
-
for (var i = 0; i < cloned.length; i++) {
|
|
1
|
+
const removeSymbol = Symbol('Placeholder for removed element');
|
|
2
|
+
export const moveMulti = (arr, indexes, start) => {
|
|
3
|
+
const cloned = arr.slice();
|
|
4
|
+
for (let i = 0; i < cloned.length; i++) {
|
|
13
5
|
if (indexes.includes(i)) {
|
|
14
6
|
cloned[i] = removeSymbol;
|
|
15
7
|
}
|
|
16
8
|
}
|
|
17
|
-
|
|
18
|
-
cloned.splice
|
|
19
|
-
return cloned.filter(
|
|
9
|
+
const els = arr.filter((__, i) => indexes.includes(i));
|
|
10
|
+
cloned.splice(start, 0, ...els);
|
|
11
|
+
return cloned.filter((v) => v !== removeSymbol);
|
|
20
12
|
};
|
|
21
|
-
exports.moveMulti = moveMulti;
|
package/dist/clipboard.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
2
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
3
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -8,87 +7,54 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
8
|
});
|
|
10
9
|
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
10
|
+
export function writeImage(element) {
|
|
11
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
if (!element)
|
|
14
|
+
return reject('element is not defined');
|
|
15
|
+
const canvas = document.createElement('canvas');
|
|
16
|
+
const ctx = canvas.getContext('2d');
|
|
17
|
+
if (ctx === null) {
|
|
18
|
+
reject('canvas 2d context初始化失败');
|
|
19
|
+
return;
|
|
32
20
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
21
|
+
const img = new Image();
|
|
22
|
+
//浏览器在加载图像时要使用匿名身份验证,以允许跨域资源共享(CORS)。
|
|
23
|
+
img.crossOrigin = 'anonymous';
|
|
24
|
+
if (typeof element === 'string') {
|
|
25
|
+
img.src = element;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
img.src = element.src;
|
|
29
|
+
}
|
|
30
|
+
img.onload = () => {
|
|
31
|
+
//创建一个画布,赋予画布宽高为图片的原始宽高
|
|
32
|
+
if (typeof element === 'string') {
|
|
33
|
+
canvas.width = img.width;
|
|
34
|
+
canvas.height = img.height;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
canvas.width = element.naturalWidth;
|
|
38
|
+
canvas.height = element.naturalHeight;
|
|
39
|
+
}
|
|
40
|
+
//防止有缓存,绘制之前先清除画布
|
|
41
|
+
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
42
|
+
ctx.drawImage(img, 0, 0);
|
|
43
|
+
//将canvas转为blob
|
|
44
|
+
canvas.toBlob((blob) => {
|
|
45
|
+
if (blob === null) {
|
|
46
|
+
reject('canvas to blob失败');
|
|
50
47
|
return;
|
|
51
48
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
img.onload = function () {
|
|
62
|
-
//创建一个画布,赋予画布宽高为图片的原始宽高
|
|
63
|
-
if (typeof element === 'string') {
|
|
64
|
-
canvas.width = img.width;
|
|
65
|
-
canvas.height = img.height;
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
canvas.width = element.naturalWidth;
|
|
69
|
-
canvas.height = element.naturalHeight;
|
|
70
|
-
}
|
|
71
|
-
//防止有缓存,绘制之前先清除画布
|
|
72
|
-
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
73
|
-
ctx.drawImage(img, 0, 0);
|
|
74
|
-
//将canvas转为blob
|
|
75
|
-
canvas.toBlob(function (blob) {
|
|
76
|
-
var _a;
|
|
77
|
-
if (blob === null) {
|
|
78
|
-
reject('canvas to blob失败');
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
navigator.clipboard
|
|
82
|
-
.write([
|
|
83
|
-
new ClipboardItem((_a = {},
|
|
84
|
-
_a[blob.type] = blob,
|
|
85
|
-
_a)),
|
|
86
|
-
])
|
|
87
|
-
.then(resolve, reject);
|
|
88
|
-
});
|
|
89
|
-
};
|
|
90
|
-
})];
|
|
49
|
+
navigator.clipboard
|
|
50
|
+
.write([
|
|
51
|
+
new ClipboardItem({
|
|
52
|
+
[blob.type]: blob,
|
|
53
|
+
}),
|
|
54
|
+
])
|
|
55
|
+
.then(resolve, reject);
|
|
56
|
+
});
|
|
57
|
+
};
|
|
91
58
|
});
|
|
92
59
|
});
|
|
93
60
|
}
|
|
94
|
-
exports.writeImage = writeImage;
|
package/dist/date.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getRecentYears = exports.rangeOfYears = void 0;
|
|
4
1
|
/**
|
|
5
2
|
* Generates an array of numbers representing a range of years between the start year and the end year.
|
|
6
3
|
*
|
|
@@ -8,33 +5,27 @@ exports.getRecentYears = exports.rangeOfYears = void 0;
|
|
|
8
5
|
* @param {number} end - the ending year of the range (defaults to the current year)
|
|
9
6
|
* @return {number[]} an array of numbers representing the range of years
|
|
10
7
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
};
|
|
17
|
-
exports.rangeOfYears = rangeOfYears;
|
|
18
|
-
function getRecentYears(recentYears, type, suffix) {
|
|
19
|
-
if (suffix === void 0) { suffix = '年'; }
|
|
20
|
-
var thisYear = new Date().getFullYear();
|
|
8
|
+
export const rangeOfYears = (start, end = new Date().getFullYear()) => Array(end - start + 1)
|
|
9
|
+
.fill(start)
|
|
10
|
+
.map((year, index) => year + index);
|
|
11
|
+
export function getRecentYears(recentYears, type, suffix = '年') {
|
|
12
|
+
const thisYear = new Date().getFullYear();
|
|
21
13
|
if (type === 'number[]') {
|
|
22
|
-
|
|
23
|
-
for (
|
|
14
|
+
const result = [];
|
|
15
|
+
for (let i = 0; i < recentYears; i++) {
|
|
24
16
|
result.push(thisYear - i);
|
|
25
17
|
}
|
|
26
18
|
return result;
|
|
27
19
|
}
|
|
28
20
|
if (type === 'object[]') {
|
|
29
|
-
|
|
30
|
-
for (
|
|
21
|
+
const result = [];
|
|
22
|
+
for (let i = 0; i < recentYears; i++) {
|
|
31
23
|
result.push({
|
|
32
24
|
value: thisYear - i,
|
|
33
|
-
label:
|
|
25
|
+
label: `${thisYear - i}${suffix}`,
|
|
34
26
|
});
|
|
35
27
|
}
|
|
36
28
|
return result;
|
|
37
29
|
}
|
|
38
30
|
throw new Error('type must be "number[]" or "object[]"');
|
|
39
31
|
}
|
|
40
|
-
exports.getRecentYears = getRecentYears;
|
package/dist/dom.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.strip = exports.scrollToTop = void 0;
|
|
4
1
|
/**
|
|
5
2
|
* 元素滚动条滚动到顶部
|
|
6
3
|
*/
|
|
7
|
-
function scrollToTop(element) {
|
|
4
|
+
export function scrollToTop(element) {
|
|
8
5
|
if (element) {
|
|
9
6
|
if (element.scrollTop === 0) {
|
|
10
7
|
return;
|
|
@@ -18,15 +15,13 @@ function scrollToTop(element) {
|
|
|
18
15
|
}
|
|
19
16
|
}
|
|
20
17
|
}
|
|
21
|
-
exports.scrollToTop = scrollToTop;
|
|
22
18
|
/**
|
|
23
19
|
* Strips HTML tags from a given string and returns the plain text content.
|
|
24
20
|
*
|
|
25
21
|
* @param {string} html - The HTML string to strip tags from.
|
|
26
22
|
* @return {string} The plain text content of the HTML string.
|
|
27
23
|
*/
|
|
28
|
-
function strip(html) {
|
|
29
|
-
|
|
24
|
+
export function strip(html) {
|
|
25
|
+
let doc = new DOMParser().parseFromString(html !== null && html !== void 0 ? html : '', 'text/html');
|
|
30
26
|
return doc.body.textContent || '';
|
|
31
27
|
}
|
|
32
|
-
exports.strip = strip;
|
package/dist/file.d.ts
CHANGED
|
@@ -36,4 +36,14 @@ export declare function isImageExists(src: string, img?: HTMLImageElement): Prom
|
|
|
36
36
|
export declare function getFilenameFromContentDispositionHeader(header: {
|
|
37
37
|
['content-disposition']: string;
|
|
38
38
|
}): string;
|
|
39
|
+
declare const HyperLinkTargets: readonly ["_self", "_black", "_parent", "_top"];
|
|
40
|
+
export declare type HyperLinkTarget = (typeof HyperLinkTargets)[number];
|
|
41
|
+
/**
|
|
42
|
+
* 文件下载
|
|
43
|
+
* @param source 文件地址或blob对象
|
|
44
|
+
* @param fileName 文件名
|
|
45
|
+
* @param isPreview 是否
|
|
46
|
+
*/
|
|
47
|
+
export declare function download(source: Blob, fileName?: string): void;
|
|
48
|
+
export declare function download(source: string, fileName?: string, target?: HyperLinkTarget): void;
|
|
39
49
|
export {};
|
package/dist/file.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
2
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
3
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -8,48 +7,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
8
|
});
|
|
10
9
|
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (_) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.getFilenameFromContentDispositionHeader = exports.isImageExists = exports.validateImageSize = exports.toImage = void 0;
|
|
40
10
|
/**
|
|
41
11
|
* 转换BlobPart或者文件地址为图片对象
|
|
42
12
|
* @param file 传入文件 或者 url
|
|
43
13
|
* @returns 返回 一个图片详情对象
|
|
44
14
|
*/
|
|
45
|
-
|
|
46
|
-
return new Promise(
|
|
47
|
-
|
|
15
|
+
export const toImage = (file, options) => {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
const image = new Image();
|
|
48
18
|
if (typeof file === 'string') {
|
|
49
19
|
image.src = file;
|
|
50
20
|
}
|
|
51
21
|
else {
|
|
52
|
-
|
|
22
|
+
const blob = URL.createObjectURL(new Blob([file], options));
|
|
53
23
|
image.src = blob;
|
|
54
24
|
}
|
|
55
25
|
// 如果有缓存,读缓存
|
|
@@ -68,57 +38,64 @@ var toImage = function (file, options) {
|
|
|
68
38
|
}
|
|
69
39
|
});
|
|
70
40
|
};
|
|
71
|
-
exports.toImage = toImage;
|
|
72
41
|
/**
|
|
73
42
|
* 图片宽,高校验
|
|
74
43
|
* @param file 传入文件 或者 url
|
|
75
44
|
* @param limitSize 限制宽度, 高度
|
|
76
45
|
* @returns isOK: 是否超出宽高; width, height: 图片的宽高
|
|
77
46
|
*/
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return
|
|
81
|
-
|
|
82
|
-
case 0: return [4 /*yield*/, exports.toImage(file, options)];
|
|
83
|
-
case 1:
|
|
84
|
-
image = _a.sent();
|
|
85
|
-
return [2 /*return*/, { isOk: image.width <= limitSize.width && image.height <= limitSize.height, width: image.width, height: image.height }];
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
}); };
|
|
89
|
-
exports.validateImageSize = validateImageSize;
|
|
47
|
+
export const validateImageSize = (file, limitSize, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
48
|
+
const image = yield toImage(file, options);
|
|
49
|
+
return { isOk: image.width <= limitSize.width && image.height <= limitSize.height, width: image.width, height: image.height };
|
|
50
|
+
});
|
|
90
51
|
/**
|
|
91
52
|
* 检测图片地址是否可用
|
|
92
53
|
* @param src 图片地址
|
|
93
54
|
* @param img HTMLImageElement
|
|
94
55
|
* @returns Promise<boolean>
|
|
95
56
|
*/
|
|
96
|
-
function isImageExists(src, img) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
img.onload = function () { return resolve(true); };
|
|
105
|
-
img.onerror = function () { return resolve(false); };
|
|
106
|
-
})];
|
|
57
|
+
export function isImageExists(src, img = new Image()) {
|
|
58
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
if (!src)
|
|
60
|
+
return false;
|
|
61
|
+
return new Promise((resolve) => {
|
|
62
|
+
img.src = src;
|
|
63
|
+
img.onload = () => resolve(true);
|
|
64
|
+
img.onerror = () => resolve(false);
|
|
107
65
|
});
|
|
108
66
|
});
|
|
109
67
|
}
|
|
110
|
-
exports.isImageExists = isImageExists;
|
|
111
68
|
/**
|
|
112
69
|
* 从Content-Disposition中获取文件名
|
|
113
70
|
* @param header 包含Content-Disposition, 值为'attachment;filename=%E5%A4%A7%E8%A1%8C%E6%8C%87%E5%AF%BC2024-06-27-2024-06-28.xlsx'
|
|
114
71
|
* @returns string
|
|
115
72
|
*
|
|
116
73
|
*/
|
|
117
|
-
function getFilenameFromContentDispositionHeader(header) {
|
|
118
|
-
|
|
74
|
+
export function getFilenameFromContentDispositionHeader(header) {
|
|
75
|
+
const contentDisposition = header['content-disposition'];
|
|
119
76
|
if (!contentDisposition)
|
|
120
77
|
return '';
|
|
121
|
-
|
|
78
|
+
const filename = contentDisposition.split('filename=')[1].split(';')[0];
|
|
122
79
|
return decodeURIComponent(filename);
|
|
123
80
|
}
|
|
124
|
-
|
|
81
|
+
const HyperLinkTargets = ['_self', '_black', '_parent', '_top'];
|
|
82
|
+
export function download(source, fileName = '', target) {
|
|
83
|
+
const link = document.createElement('a');
|
|
84
|
+
if (typeof source === 'string') {
|
|
85
|
+
if (typeof target === 'string' && HyperLinkTargets.includes(target)) {
|
|
86
|
+
link.target = target;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
link.download = fileName;
|
|
90
|
+
}
|
|
91
|
+
link.href = source;
|
|
92
|
+
}
|
|
93
|
+
if (source instanceof Blob) {
|
|
94
|
+
const url = window.URL.createObjectURL(source);
|
|
95
|
+
link.href = url;
|
|
96
|
+
link.download = fileName;
|
|
97
|
+
}
|
|
98
|
+
document.body.appendChild(link);
|
|
99
|
+
link.click();
|
|
100
|
+
document.body.removeChild(link);
|
|
101
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,30 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
-
}) : function(o, v) {
|
|
12
|
-
o["default"] = v;
|
|
13
|
-
});
|
|
14
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
-
if (mod && mod.__esModule) return mod;
|
|
16
|
-
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
-
__setModuleDefault(result, mod);
|
|
19
|
-
return result;
|
|
20
|
-
};
|
|
21
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.support = exports.file = exports.algorithm = exports.types = exports.date = exports.dom = exports.react = exports.clipboard = void 0;
|
|
23
|
-
exports.clipboard = __importStar(require("./clipboard"));
|
|
24
|
-
exports.react = __importStar(require("./react"));
|
|
25
|
-
exports.dom = __importStar(require("./dom"));
|
|
26
|
-
exports.date = __importStar(require("./date"));
|
|
27
|
-
exports.types = __importStar(require("./types"));
|
|
28
|
-
exports.algorithm = __importStar(require("./algorithm"));
|
|
29
|
-
exports.file = __importStar(require("./file"));
|
|
30
|
-
exports.support = __importStar(require("./support"));
|
|
1
|
+
export * as clipboard from './clipboard';
|
|
2
|
+
export * as react from './react';
|
|
3
|
+
export * as dom from './dom';
|
|
4
|
+
export * as date from './date';
|
|
5
|
+
export * as types from './types';
|
|
6
|
+
export * as algorithm from './algorithm';
|
|
7
|
+
export * as file from './file';
|
|
8
|
+
export * as support from './support';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* react component 的增强类
|
|
4
|
+
*/
|
|
5
|
+
export declare class EnhancedComponent<P, S> extends React.Component<P, S> {
|
|
6
|
+
/**
|
|
7
|
+
* setState 方法的同步版本
|
|
8
|
+
* @param state
|
|
9
|
+
* @returns Promise
|
|
10
|
+
*/
|
|
11
|
+
protected setStateAsync<K extends keyof S>(state: ((prevState: Readonly<S>, props: Readonly<P>) => Pick<S, K> | S | null) | (Pick<S, K> | S | null)): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* react component 的增强类
|
|
4
|
+
*/
|
|
5
|
+
export class EnhancedComponent extends React.Component {
|
|
6
|
+
/**
|
|
7
|
+
* setState 方法的同步版本
|
|
8
|
+
* @param state
|
|
9
|
+
* @returns Promise
|
|
10
|
+
*/
|
|
11
|
+
setStateAsync(state) {
|
|
12
|
+
return new Promise((resolve) => {
|
|
13
|
+
this.setState(state, resolve);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
package/dist/react/index.d.ts
CHANGED
package/dist/react/index.js
CHANGED
|
@@ -1,17 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}));
|
|
9
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
10
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
|
-
};
|
|
12
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
__exportStar(require("./useDisableContextMenu"), exports);
|
|
14
|
-
__exportStar(require("./useStateCallback"), exports);
|
|
15
|
-
__exportStar(require("./renderToString"), exports);
|
|
16
|
-
__exportStar(require("./useIsMounted"), exports);
|
|
17
|
-
__exportStar(require("./useCopyToClipboard"), exports);
|
|
1
|
+
export * from './useDisableContextMenu';
|
|
2
|
+
export * from './useStateCallback';
|
|
3
|
+
export * from './renderToString';
|
|
4
|
+
export * from './useIsMounted';
|
|
5
|
+
export * from './useCopyToClipboard';
|
|
6
|
+
export * from './enhancedComponent';
|
|
7
|
+
export * from './useDeepCompareRef';
|
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.cleanup = exports.render = void 0;
|
|
7
|
-
var react_dom_1 = __importDefault(require("react-dom"));
|
|
8
|
-
var container;
|
|
9
|
-
var render = function (element) {
|
|
10
|
-
return new Promise(function (resolve, reject) {
|
|
1
|
+
import ReactDOM from 'react-dom';
|
|
2
|
+
let container;
|
|
3
|
+
export const render = (element) => {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
11
5
|
if (document === undefined) {
|
|
12
6
|
return reject('只支持浏览器环境');
|
|
13
7
|
}
|
|
@@ -15,7 +9,7 @@ var render = function (element) {
|
|
|
15
9
|
container.id = 'template-container';
|
|
16
10
|
container.style.cssText = 'position: absolute; left: -9999px;';
|
|
17
11
|
document.body.appendChild(container);
|
|
18
|
-
|
|
12
|
+
ReactDOM.render(element, container, () => {
|
|
19
13
|
if (container) {
|
|
20
14
|
resolve(container.innerHTML);
|
|
21
15
|
}
|
|
@@ -25,14 +19,12 @@ var render = function (element) {
|
|
|
25
19
|
});
|
|
26
20
|
});
|
|
27
21
|
};
|
|
28
|
-
|
|
29
|
-
var cleanup = function () {
|
|
22
|
+
export const cleanup = () => {
|
|
30
23
|
if (container === null)
|
|
31
24
|
return;
|
|
32
|
-
|
|
25
|
+
const isUnmounted = ReactDOM.unmountComponentAtNode(container);
|
|
33
26
|
if (isUnmounted) {
|
|
34
27
|
document.body.removeChild(container);
|
|
35
28
|
container = null;
|
|
36
29
|
}
|
|
37
30
|
};
|
|
38
|
-
exports.cleanup = cleanup;
|
|
@@ -1,32 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
var isMounted = useIsMounted_1.useIsMounted();
|
|
9
|
-
var _c = react_1.useState(false), isCopied = _c[0], setIsCopied = _c[1];
|
|
10
|
-
var copyToClipboard = react_1.useCallback(function (value) {
|
|
1
|
+
import { useCallback, useState } from 'react';
|
|
2
|
+
import { useIsMounted } from './useIsMounted';
|
|
3
|
+
export function useCopyToClipboard(props) {
|
|
4
|
+
const { timeout = 2000, onCopy, onError } = props !== null && props !== void 0 ? props : {};
|
|
5
|
+
const isMounted = useIsMounted();
|
|
6
|
+
const [isCopied, setIsCopied] = useState(false);
|
|
7
|
+
const copyToClipboard = useCallback((value) => {
|
|
11
8
|
var _a;
|
|
12
9
|
if (!isMounted())
|
|
13
10
|
return;
|
|
14
11
|
if (typeof window === 'undefined' || !((_a = navigator.clipboard) === null || _a === void 0 ? void 0 : _a.writeText)) {
|
|
15
|
-
|
|
12
|
+
const error = new Error(`Cannot copy to clipboard, navigator.clipboard.writeText is not defined`);
|
|
16
13
|
if (process.env.NODE_ENV === 'development')
|
|
17
14
|
console.error(error);
|
|
18
15
|
onError === null || onError === void 0 ? void 0 : onError(error);
|
|
19
16
|
return;
|
|
20
17
|
}
|
|
21
18
|
if (typeof value !== 'string') {
|
|
22
|
-
|
|
19
|
+
const error = new Error(`Cannot copy typeof ${typeof value} to clipboard, must be a string`);
|
|
23
20
|
if (process.env.NODE_ENV === 'development')
|
|
24
21
|
console.error(error);
|
|
25
22
|
onError === null || onError === void 0 ? void 0 : onError(error);
|
|
26
23
|
return;
|
|
27
24
|
}
|
|
28
25
|
if (value === '') {
|
|
29
|
-
|
|
26
|
+
const error = new Error(`Cannot copy empty string to clipboard.`);
|
|
30
27
|
if (process.env.NODE_ENV === 'development')
|
|
31
28
|
console.error(error);
|
|
32
29
|
onError === null || onError === void 0 ? void 0 : onError(error);
|
|
@@ -34,15 +31,14 @@ function useCopyToClipboard(props) {
|
|
|
34
31
|
}
|
|
35
32
|
navigator.clipboard
|
|
36
33
|
.writeText(value)
|
|
37
|
-
.then(
|
|
34
|
+
.then(() => {
|
|
38
35
|
setIsCopied(true);
|
|
39
36
|
onCopy === null || onCopy === void 0 ? void 0 : onCopy(value);
|
|
40
|
-
setTimeout(
|
|
37
|
+
setTimeout(() => {
|
|
41
38
|
setIsCopied(false);
|
|
42
39
|
}, timeout);
|
|
43
40
|
})
|
|
44
|
-
.catch(
|
|
41
|
+
.catch((error) => onError === null || onError === void 0 ? void 0 : onError(error));
|
|
45
42
|
}, [onCopy, onError, timeout]);
|
|
46
|
-
return { isCopied
|
|
43
|
+
return { isCopied, copyToClipboard };
|
|
47
44
|
}
|
|
48
|
-
exports.useCopyToClipboard = useCopyToClipboard;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useRef } from 'react';
|
|
2
|
+
import isEqual from 'react-fast-compare';
|
|
3
|
+
export const useDeepCompareRef = (deps) => {
|
|
4
|
+
const ref = useRef();
|
|
5
|
+
const signalRef = useRef(0);
|
|
6
|
+
if (deps === undefined || !isEqual(deps, ref.current)) {
|
|
7
|
+
ref.current = deps;
|
|
8
|
+
signalRef.current += 1;
|
|
9
|
+
}
|
|
10
|
+
return signalRef;
|
|
11
|
+
};
|
|
@@ -1,29 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.useDisableContextMenu = void 0;
|
|
4
|
-
var react_1 = require("react");
|
|
5
|
-
var defaultContextMenuTarget = function () { return document; };
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
const defaultContextMenuTarget = () => document;
|
|
6
3
|
/**
|
|
7
4
|
* 在HTML元素上禁用右键菜单
|
|
8
5
|
* @param target 默认为 () => document
|
|
9
6
|
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
var targetFn = react_1.useRef(target);
|
|
7
|
+
export const useDisableContextMenu = (target = defaultContextMenuTarget) => {
|
|
8
|
+
const targetFn = useRef(target);
|
|
13
9
|
targetFn.current = target;
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
const el = targetFn.current();
|
|
16
12
|
if (!el)
|
|
17
13
|
return;
|
|
18
|
-
|
|
14
|
+
const onContextMenu = (e) => {
|
|
19
15
|
e.preventDefault();
|
|
20
16
|
};
|
|
21
17
|
el.addEventListener('contextmenu', onContextMenu);
|
|
22
|
-
return
|
|
18
|
+
return () => {
|
|
23
19
|
if (!el)
|
|
24
20
|
return;
|
|
25
21
|
el.removeEventListener('contextmenu', onContextMenu);
|
|
26
22
|
};
|
|
27
23
|
}, []);
|
|
28
24
|
};
|
|
29
|
-
exports.useDisableContextMenu = useDisableContextMenu;
|
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useIsMounted = void 0;
|
|
4
|
-
var react_1 = require("react");
|
|
1
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
5
2
|
/** 用于判断组件是否挂载 */
|
|
6
|
-
function useIsMounted() {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
export function useIsMounted() {
|
|
4
|
+
const mountedRef = useRef(false);
|
|
5
|
+
const get = useCallback(() => mountedRef.current, []);
|
|
6
|
+
useEffect(() => {
|
|
10
7
|
mountedRef.current = true;
|
|
11
|
-
return
|
|
8
|
+
return () => {
|
|
12
9
|
mountedRef.current = false;
|
|
13
10
|
};
|
|
14
11
|
}, []);
|
|
15
12
|
return get;
|
|
16
13
|
}
|
|
17
|
-
exports.useIsMounted = useIsMounted;
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useStateCallback = void 0;
|
|
4
|
-
var react_1 = require("react");
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
5
2
|
/** 等价与类组件 setState(updater[, callback]) */
|
|
6
|
-
function useStateCallback(initialState) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
export function useStateCallback(initialState) {
|
|
4
|
+
const [state, setState] = useState(initialState);
|
|
5
|
+
const cbRef = useRef(undefined);
|
|
6
|
+
const setStateCallback = useCallback((state, cb) => {
|
|
10
7
|
cbRef.current = cb;
|
|
11
8
|
setState(state);
|
|
12
9
|
}, []);
|
|
13
|
-
|
|
10
|
+
useEffect(() => {
|
|
14
11
|
if (cbRef.current) {
|
|
15
12
|
cbRef.current(state);
|
|
16
13
|
cbRef.current = undefined;
|
|
@@ -18,4 +15,3 @@ function useStateCallback(initialState) {
|
|
|
18
15
|
}, [state]);
|
|
19
16
|
return [state, setStateCallback];
|
|
20
17
|
}
|
|
21
|
-
exports.useStateCallback = useStateCallback;
|
package/dist/support.js
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isSharedWorker = exports.isWebSocket = exports.isBrowserEnv = void 0;
|
|
4
1
|
/**
|
|
5
2
|
* 是否是浏览器环境
|
|
6
3
|
*/
|
|
7
|
-
|
|
8
|
-
exports.isBrowserEnv = isBrowserEnv;
|
|
4
|
+
export const isBrowserEnv = () => typeof window !== 'undefined';
|
|
9
5
|
/**
|
|
10
6
|
* 是否支持WebSocket
|
|
11
7
|
*/
|
|
12
|
-
|
|
13
|
-
exports.isWebSocket = isWebSocket;
|
|
8
|
+
export const isWebSocket = () => typeof WebSocket !== 'undefined';
|
|
14
9
|
/**
|
|
15
10
|
* 是否支持SharedWorker
|
|
16
11
|
*/
|
|
17
|
-
|
|
18
|
-
exports.isSharedWorker = isSharedWorker;
|
|
12
|
+
export const isSharedWorker = () => typeof SharedWorker !== 'undefined';
|
package/dist/timer.d.ts
ADDED
package/dist/timer.js
ADDED
package/dist/types.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@d-matrix/utils",
|
|
3
|
-
"
|
|
3
|
+
"sideEffects": false,
|
|
4
|
+
"version": "1.9.0",
|
|
4
5
|
"description": "A dozen of utils for Front-End Development",
|
|
5
6
|
"main": "dist/index.js",
|
|
6
7
|
"scripts": {
|
|
@@ -11,7 +12,8 @@
|
|
|
11
12
|
"cy:component": "cypress run --component --spec",
|
|
12
13
|
"cy:component:all": "cypress run --component",
|
|
13
14
|
"test:tsd": "tsd",
|
|
14
|
-
"postversion": "git push && git push --tags"
|
|
15
|
+
"postversion": "git push && git push --tags",
|
|
16
|
+
"cnpm:sync": "cnpm sync %npm_package_name%"
|
|
15
17
|
},
|
|
16
18
|
"engines": {
|
|
17
19
|
"node": ">=16.20.0"
|
|
@@ -42,9 +44,13 @@
|
|
|
42
44
|
},
|
|
43
45
|
"devDependencies": {
|
|
44
46
|
"@vitejs/plugin-react": "^4.2.1",
|
|
47
|
+
"cnpm": "^9.4.0",
|
|
45
48
|
"cypress": "^13.6.6",
|
|
46
49
|
"expect-type": "^0.19.0",
|
|
47
50
|
"rimraf": "^5.0.5",
|
|
48
51
|
"vite": "^4.5.2"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"react-fast-compare": "^3.2.2"
|
|
49
55
|
}
|
|
50
56
|
}
|
package/readme.md
CHANGED
|
@@ -15,6 +15,7 @@ A dozen of utils for Front-End Development
|
|
|
15
15
|
- [algorithm](#algorithm)
|
|
16
16
|
- [file](#file)
|
|
17
17
|
- [support](#support)
|
|
18
|
+
- [timer](#timer)
|
|
18
19
|
|
|
19
20
|
### clipboard
|
|
20
21
|
|
|
@@ -88,6 +89,37 @@ const Test = () => {
|
|
|
88
89
|
|
|
89
90
|
复制文本到剪切板, 用法见[测试](./tests/react.cy.tsx)
|
|
90
91
|
|
|
92
|
+
- `EnhancedComponent.prototype.setStateAsync(state)`
|
|
93
|
+
|
|
94
|
+
setState 方法的同步版本
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import { react } from '@d-matrix/utils';
|
|
98
|
+
|
|
99
|
+
class TestComponent extends EnhancedComponent<unknown, { pageIndex: number }> {
|
|
100
|
+
state = {
|
|
101
|
+
pageIndex: 1,
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
async onClick() {
|
|
105
|
+
await this.setStateAsync({ pageIndex: 2 });
|
|
106
|
+
console.log(this.state.pageIndex); // 2
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
render() {
|
|
110
|
+
return (
|
|
111
|
+
<button data-cy="test-button" onClick={() => this.onClick()}>
|
|
112
|
+
click
|
|
113
|
+
</button>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
- `useDeepCompareRef(deps: DependencyList): React.MutableRefObject<number>`
|
|
120
|
+
|
|
121
|
+
深比较`deps`。返回`ref`,`ref.current`是一个自增数字,每次`deps`变化,`ref.current`加`1`。用法见[测试](./tests/react.cy.tsx)
|
|
122
|
+
|
|
91
123
|
### dom
|
|
92
124
|
|
|
93
125
|
- `scrollToTop(element: Element | null | undefined): void`
|
|
@@ -203,6 +235,14 @@ const filename = file.getFilenameFromContentDispositionHeader(header);
|
|
|
203
235
|
// '大行指导2024-06-27-2024-06-28.xlsx'
|
|
204
236
|
```
|
|
205
237
|
|
|
238
|
+
- `download(source: string | Blob, fileName = '', target?: HyperLinkTarget): void`
|
|
239
|
+
|
|
240
|
+
文件下载,`source`是文件地址或`blob`对象。
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
type HyperLinkTarget = "_self" | "_black" | "_parent" | "_top"
|
|
244
|
+
```
|
|
245
|
+
|
|
206
246
|
## support
|
|
207
247
|
|
|
208
248
|
- `isBrowserEnv(): boolean`
|
|
@@ -217,6 +257,17 @@ const filename = file.getFilenameFromContentDispositionHeader(header);
|
|
|
217
257
|
|
|
218
258
|
是否支持SharedWorker
|
|
219
259
|
|
|
260
|
+
## timer
|
|
261
|
+
|
|
262
|
+
- `sleep(ms?: number): Promise<unknown>`
|
|
263
|
+
|
|
264
|
+
使用`setTimeout`与`Promise`实现,暂停执行`ms`毫秒
|
|
265
|
+
|
|
266
|
+
```
|
|
267
|
+
await sleep(3000); // 暂停3秒
|
|
268
|
+
console.log('continue'); // 继续执行
|
|
269
|
+
```
|
|
270
|
+
|
|
220
271
|
## 测试
|
|
221
272
|
|
|
222
273
|
运行全部组件测试
|