react-mention-input 1.1.28 → 1.1.30
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/ShowMessageCard.js +4 -4
- package/dist/useProtectedImage.d.ts +1 -0
- package/dist/useProtectedImage.js +91 -33
- package/package.json +2 -2
- package/src/ShowMessageCard.tsx +5 -5
- package/src/useProtectedImage.ts +95 -29
- package/demo.tsx +0 -167
- package/dist/src/MentionInput.d.ts +0 -38
- package/dist/src/MentionInput.js +0 -376
- package/dist/src/ShowMessageCard.d.ts +0 -41
- package/dist/src/ShowMessageCard.js +0 -72
- package/dist/src/index.d.ts +0 -2
- package/dist/src/index.js +0 -2
- package/index.html +0 -12
- package/main.tsx +0 -9
- package/tsconfig.json +0 -28
- package/vite.config.ts +0 -10
package/dist/ShowMessageCard.js
CHANGED
|
@@ -18,7 +18,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
18
18
|
}
|
|
19
19
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
20
20
|
};
|
|
21
|
-
import React, { useState } from "react";
|
|
21
|
+
import React, { useState, memo } from "react";
|
|
22
22
|
import "./ShowMessageCard.css";
|
|
23
23
|
import { useProtectedImage } from "./useProtectedImage";
|
|
24
24
|
export var ShowMessageCard = function (_a) {
|
|
@@ -50,8 +50,8 @@ export var ShowMessageCard = function (_a) {
|
|
|
50
50
|
.join("");
|
|
51
51
|
return initials;
|
|
52
52
|
};
|
|
53
|
-
// Component to render protected images
|
|
54
|
-
var ProtectedImage = function (_a) {
|
|
53
|
+
// Component to render protected images - memoized to prevent recreation on every render
|
|
54
|
+
var ProtectedImage = memo(function (_a) {
|
|
55
55
|
var url = _a.url, alt = _a.alt, className = _a.className, style = _a.style, containerClassName = _a.containerClassName, containerStyle = _a.containerStyle, onError = _a.onError, _b = _a.renderInContainer, renderInContainer = _b === void 0 ? true : _b;
|
|
56
56
|
var displayUrl = useProtectedImage({
|
|
57
57
|
url: url,
|
|
@@ -66,7 +66,7 @@ export var ShowMessageCard = function (_a) {
|
|
|
66
66
|
return (React.createElement("div", { className: containerClassName, style: containerStyle }, imgElement));
|
|
67
67
|
}
|
|
68
68
|
return imgElement;
|
|
69
|
-
};
|
|
69
|
+
});
|
|
70
70
|
// Helper function to extract hashtags and mentions from text
|
|
71
71
|
var extractTagsAndMentions = function (text) {
|
|
72
72
|
// First extract from HTML with spans
|
|
@@ -7,6 +7,7 @@ interface UseProtectedImageOptions {
|
|
|
7
7
|
* Custom hook to handle protected image URLs that require authentication tokens in headers.
|
|
8
8
|
* For protected URLs, it fetches the image with auth headers and converts it to a blob URL.
|
|
9
9
|
* For non-protected URLs, it returns the URL as-is.
|
|
10
|
+
* Uses a module-level cache to prevent blinking on re-renders.
|
|
10
11
|
*/
|
|
11
12
|
export declare const useProtectedImage: ({ url, isProtected, getAuthHeaders, }: UseProtectedImageOptions) => string | null;
|
|
12
13
|
export {};
|
|
@@ -46,41 +46,86 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
48
|
import { useState, useEffect, useRef } from 'react';
|
|
49
|
+
// Module-level cache to persist blob URLs across component re-renders
|
|
50
|
+
var blobUrlCache = new Map();
|
|
51
|
+
var fetchingUrls = new Set();
|
|
49
52
|
/**
|
|
50
53
|
* Custom hook to handle protected image URLs that require authentication tokens in headers.
|
|
51
54
|
* For protected URLs, it fetches the image with auth headers and converts it to a blob URL.
|
|
52
55
|
* For non-protected URLs, it returns the URL as-is.
|
|
56
|
+
* Uses a module-level cache to prevent blinking on re-renders.
|
|
53
57
|
*/
|
|
54
58
|
export var useProtectedImage = function (_a) {
|
|
55
59
|
var url = _a.url, isProtected = _a.isProtected, getAuthHeaders = _a.getAuthHeaders;
|
|
56
|
-
var _b = useState(
|
|
57
|
-
|
|
60
|
+
var _b = useState(function () {
|
|
61
|
+
// Initialize from cache if available
|
|
62
|
+
return url ? blobUrlCache.get(url) || null : null;
|
|
63
|
+
}), blobUrl = _b[0], setBlobUrl = _b[1];
|
|
64
|
+
var previousUrlRef = useRef(null);
|
|
65
|
+
var isProtectedRef = useRef(isProtected);
|
|
66
|
+
var getAuthHeadersRef = useRef(getAuthHeaders);
|
|
67
|
+
var mountedRef = useRef(true);
|
|
68
|
+
// Update refs when props change (but don't trigger re-fetch)
|
|
58
69
|
useEffect(function () {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
70
|
+
isProtectedRef.current = isProtected;
|
|
71
|
+
getAuthHeadersRef.current = getAuthHeaders;
|
|
72
|
+
}, [isProtected, getAuthHeaders]);
|
|
73
|
+
useEffect(function () {
|
|
74
|
+
mountedRef.current = true;
|
|
75
|
+
return function () {
|
|
76
|
+
mountedRef.current = false;
|
|
77
|
+
};
|
|
78
|
+
}, []);
|
|
79
|
+
useEffect(function () {
|
|
80
|
+
// Always check cache first and restore if needed (synchronous)
|
|
81
|
+
if (url && blobUrlCache.has(url) && !blobUrl) {
|
|
82
|
+
var cachedBlobUrl = blobUrlCache.get(url);
|
|
83
|
+
setBlobUrl(cachedBlobUrl);
|
|
63
84
|
}
|
|
64
|
-
|
|
85
|
+
// If URL hasn't changed, keep using cached blob URL
|
|
86
|
+
if (url === previousUrlRef.current) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
var oldUrl = previousUrlRef.current;
|
|
90
|
+
previousUrlRef.current = url;
|
|
65
91
|
if (!url) {
|
|
92
|
+
setBlobUrl(null);
|
|
66
93
|
return;
|
|
67
94
|
}
|
|
68
95
|
// Check if URL is protected
|
|
69
|
-
var shouldUseAuth = typeof
|
|
70
|
-
?
|
|
71
|
-
:
|
|
72
|
-
// If not protected,
|
|
73
|
-
if (!shouldUseAuth || !
|
|
96
|
+
var shouldUseAuth = typeof isProtectedRef.current === 'boolean'
|
|
97
|
+
? isProtectedRef.current
|
|
98
|
+
: isProtectedRef.current ? isProtectedRef.current(url) : false;
|
|
99
|
+
// If not protected, use original URL
|
|
100
|
+
if (!shouldUseAuth || !getAuthHeadersRef.current) {
|
|
101
|
+
// Clear any cached blob URL for this URL
|
|
102
|
+
if (blobUrlCache.has(url)) {
|
|
103
|
+
var cachedBlobUrl = blobUrlCache.get(url);
|
|
104
|
+
URL.revokeObjectURL(cachedBlobUrl);
|
|
105
|
+
blobUrlCache.delete(url);
|
|
106
|
+
}
|
|
107
|
+
setBlobUrl(null);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
// Check cache first - if we have a cached blob URL, use it immediately
|
|
111
|
+
if (blobUrlCache.has(url)) {
|
|
112
|
+
var cachedBlobUrl = blobUrlCache.get(url);
|
|
113
|
+
setBlobUrl(cachedBlobUrl);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
// If already fetching this URL, don't fetch again
|
|
117
|
+
if (fetchingUrls.has(url)) {
|
|
74
118
|
return;
|
|
75
119
|
}
|
|
76
120
|
// Fetch protected image with auth headers
|
|
121
|
+
fetchingUrls.add(url);
|
|
77
122
|
var fetchProtectedImage = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
78
123
|
var headers, response, blob, newBlobUrl, error_1;
|
|
79
124
|
return __generator(this, function (_a) {
|
|
80
125
|
switch (_a.label) {
|
|
81
126
|
case 0:
|
|
82
|
-
_a.trys.push([0, 4, ,
|
|
83
|
-
return [4 /*yield*/, Promise.resolve(
|
|
127
|
+
_a.trys.push([0, 4, 5, 6]);
|
|
128
|
+
return [4 /*yield*/, Promise.resolve(getAuthHeadersRef.current())];
|
|
84
129
|
case 1:
|
|
85
130
|
headers = _a.sent();
|
|
86
131
|
return [4 /*yield*/, fetch(url, {
|
|
@@ -96,34 +141,47 @@ export var useProtectedImage = function (_a) {
|
|
|
96
141
|
case 3:
|
|
97
142
|
blob = _a.sent();
|
|
98
143
|
newBlobUrl = URL.createObjectURL(blob);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
144
|
+
// Only update if URL hasn't changed during fetch and component is still mounted
|
|
145
|
+
if (previousUrlRef.current === url && mountedRef.current) {
|
|
146
|
+
// Cache the blob URL
|
|
147
|
+
blobUrlCache.set(url, newBlobUrl);
|
|
148
|
+
setBlobUrl(newBlobUrl);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
// URL changed during fetch or component unmounted, revoke this blob URL
|
|
152
|
+
URL.revokeObjectURL(newBlobUrl);
|
|
153
|
+
}
|
|
154
|
+
return [3 /*break*/, 6];
|
|
102
155
|
case 4:
|
|
103
156
|
error_1 = _a.sent();
|
|
104
157
|
console.error('Error fetching protected image:', error_1);
|
|
105
|
-
// On error,
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
158
|
+
// On error, only clear if URL hasn't changed and component is mounted
|
|
159
|
+
if (previousUrlRef.current === url && mountedRef.current) {
|
|
160
|
+
setBlobUrl(null);
|
|
161
|
+
}
|
|
162
|
+
return [3 /*break*/, 6];
|
|
163
|
+
case 5:
|
|
164
|
+
fetchingUrls.delete(url);
|
|
165
|
+
return [7 /*endfinally*/];
|
|
166
|
+
case 6: return [2 /*return*/];
|
|
109
167
|
}
|
|
110
168
|
});
|
|
111
169
|
}); };
|
|
112
170
|
fetchProtectedImage();
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
URL.revokeObjectURL(blobUrlRef.current);
|
|
117
|
-
blobUrlRef.current = null;
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
}, [url, isProtected, getAuthHeaders]);
|
|
171
|
+
}, [url]); // Only depend on url
|
|
172
|
+
// Cleanup: Don't revoke blob URLs on unmount - keep them in cache for reuse
|
|
173
|
+
// They will be cleaned up when the URL changes or when the cache is cleared
|
|
121
174
|
// Return blob URL if available, otherwise return original URL (or null)
|
|
122
175
|
if (!url) {
|
|
123
176
|
return null;
|
|
124
177
|
}
|
|
125
|
-
var isUrlProtected = typeof
|
|
126
|
-
?
|
|
127
|
-
:
|
|
128
|
-
return
|
|
178
|
+
var isUrlProtected = typeof isProtectedRef.current === 'boolean'
|
|
179
|
+
? isProtectedRef.current
|
|
180
|
+
: isProtectedRef.current ? isProtectedRef.current(url) : false;
|
|
181
|
+
// For protected URLs, return cached blob URL or current blobUrl state
|
|
182
|
+
// For non-protected URLs, return the original URL
|
|
183
|
+
if (isUrlProtected) {
|
|
184
|
+
return blobUrl || blobUrlCache.get(url) || null;
|
|
185
|
+
}
|
|
186
|
+
return url;
|
|
129
187
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-mention-input",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.30",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"scripts": {
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"description": "A React component for input with @mention functionality.",
|
|
26
26
|
"repository": {
|
|
27
27
|
"type": "git",
|
|
28
|
-
"url": "https://github.com/yourusername/react-mention-input.git"
|
|
28
|
+
"url": "git+https://github.com/yourusername/react-mention-input.git"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/node": "^22.9.0",
|
package/src/ShowMessageCard.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { CSSProperties, useState, ReactNode } from "react";
|
|
1
|
+
import React, { CSSProperties, useState, ReactNode, useMemo, memo } from "react";
|
|
2
2
|
import "./ShowMessageCard.css";
|
|
3
3
|
import { useProtectedImage } from "./useProtectedImage";
|
|
4
4
|
|
|
@@ -112,8 +112,8 @@ export const ShowMessageCard: React.FC<ShowMessageCardProps> = ({
|
|
|
112
112
|
return initials;
|
|
113
113
|
};
|
|
114
114
|
|
|
115
|
-
// Component to render protected images
|
|
116
|
-
const ProtectedImage
|
|
115
|
+
// Component to render protected images - memoized to prevent recreation on every render
|
|
116
|
+
const ProtectedImage = memo<{
|
|
117
117
|
url: string;
|
|
118
118
|
alt: string;
|
|
119
119
|
className?: string;
|
|
@@ -122,7 +122,7 @@ export const ShowMessageCard: React.FC<ShowMessageCardProps> = ({
|
|
|
122
122
|
containerStyle?: CSSProperties;
|
|
123
123
|
onError?: () => void;
|
|
124
124
|
renderInContainer?: boolean;
|
|
125
|
-
}>
|
|
125
|
+
}>(({ url, alt, className, style, containerClassName, containerStyle, onError, renderInContainer = true }) => {
|
|
126
126
|
const displayUrl = useProtectedImage({
|
|
127
127
|
url,
|
|
128
128
|
isProtected: isProtectedUrl,
|
|
@@ -152,7 +152,7 @@ export const ShowMessageCard: React.FC<ShowMessageCardProps> = ({
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
return imgElement;
|
|
155
|
-
};
|
|
155
|
+
});
|
|
156
156
|
|
|
157
157
|
// Helper function to extract hashtags and mentions from text
|
|
158
158
|
const extractTagsAndMentions = (text: string) => {
|
package/src/useProtectedImage.ts
CHANGED
|
@@ -6,45 +6,97 @@ interface UseProtectedImageOptions {
|
|
|
6
6
|
getAuthHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
// Module-level cache to persist blob URLs across component re-renders
|
|
10
|
+
const blobUrlCache = new Map<string, string>();
|
|
11
|
+
const fetchingUrls = new Set<string>();
|
|
12
|
+
|
|
9
13
|
/**
|
|
10
14
|
* Custom hook to handle protected image URLs that require authentication tokens in headers.
|
|
11
15
|
* For protected URLs, it fetches the image with auth headers and converts it to a blob URL.
|
|
12
16
|
* For non-protected URLs, it returns the URL as-is.
|
|
17
|
+
* Uses a module-level cache to prevent blinking on re-renders.
|
|
13
18
|
*/
|
|
14
19
|
export const useProtectedImage = ({
|
|
15
20
|
url,
|
|
16
21
|
isProtected,
|
|
17
22
|
getAuthHeaders,
|
|
18
23
|
}: UseProtectedImageOptions): string | null => {
|
|
19
|
-
const [blobUrl, setBlobUrl] = useState<string | null>(
|
|
20
|
-
|
|
24
|
+
const [blobUrl, setBlobUrl] = useState<string | null>(() => {
|
|
25
|
+
// Initialize from cache if available
|
|
26
|
+
return url ? blobUrlCache.get(url) || null : null;
|
|
27
|
+
});
|
|
28
|
+
const previousUrlRef = useRef<string | null>(null);
|
|
29
|
+
const isProtectedRef = useRef(isProtected);
|
|
30
|
+
const getAuthHeadersRef = useRef(getAuthHeaders);
|
|
31
|
+
const mountedRef = useRef(true);
|
|
32
|
+
|
|
33
|
+
// Update refs when props change (but don't trigger re-fetch)
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
isProtectedRef.current = isProtected;
|
|
36
|
+
getAuthHeadersRef.current = getAuthHeaders;
|
|
37
|
+
}, [isProtected, getAuthHeaders]);
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
mountedRef.current = true;
|
|
41
|
+
return () => {
|
|
42
|
+
mountedRef.current = false;
|
|
43
|
+
};
|
|
44
|
+
}, []);
|
|
21
45
|
|
|
22
46
|
useEffect(() => {
|
|
23
|
-
//
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
|
|
47
|
+
// Always check cache first and restore if needed (synchronous)
|
|
48
|
+
if (url && blobUrlCache.has(url) && !blobUrl) {
|
|
49
|
+
const cachedBlobUrl = blobUrlCache.get(url)!;
|
|
50
|
+
setBlobUrl(cachedBlobUrl);
|
|
27
51
|
}
|
|
28
|
-
|
|
52
|
+
|
|
53
|
+
// If URL hasn't changed, keep using cached blob URL
|
|
54
|
+
if (url === previousUrlRef.current) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const oldUrl = previousUrlRef.current;
|
|
59
|
+
previousUrlRef.current = url;
|
|
29
60
|
|
|
30
61
|
if (!url) {
|
|
62
|
+
setBlobUrl(null);
|
|
31
63
|
return;
|
|
32
64
|
}
|
|
33
65
|
|
|
34
66
|
// Check if URL is protected
|
|
35
|
-
const shouldUseAuth = typeof
|
|
36
|
-
?
|
|
37
|
-
:
|
|
67
|
+
const shouldUseAuth = typeof isProtectedRef.current === 'boolean'
|
|
68
|
+
? isProtectedRef.current
|
|
69
|
+
: isProtectedRef.current ? isProtectedRef.current(url) : false;
|
|
70
|
+
|
|
71
|
+
// If not protected, use original URL
|
|
72
|
+
if (!shouldUseAuth || !getAuthHeadersRef.current) {
|
|
73
|
+
// Clear any cached blob URL for this URL
|
|
74
|
+
if (blobUrlCache.has(url)) {
|
|
75
|
+
const cachedBlobUrl = blobUrlCache.get(url)!;
|
|
76
|
+
URL.revokeObjectURL(cachedBlobUrl);
|
|
77
|
+
blobUrlCache.delete(url);
|
|
78
|
+
}
|
|
79
|
+
setBlobUrl(null);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
38
82
|
|
|
39
|
-
//
|
|
40
|
-
if (
|
|
83
|
+
// Check cache first - if we have a cached blob URL, use it immediately
|
|
84
|
+
if (blobUrlCache.has(url)) {
|
|
85
|
+
const cachedBlobUrl = blobUrlCache.get(url)!;
|
|
86
|
+
setBlobUrl(cachedBlobUrl);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// If already fetching this URL, don't fetch again
|
|
91
|
+
if (fetchingUrls.has(url)) {
|
|
41
92
|
return;
|
|
42
93
|
}
|
|
43
94
|
|
|
44
95
|
// Fetch protected image with auth headers
|
|
96
|
+
fetchingUrls.add(url);
|
|
45
97
|
const fetchProtectedImage = async () => {
|
|
46
98
|
try {
|
|
47
|
-
const headers = await Promise.resolve(
|
|
99
|
+
const headers = await Promise.resolve(getAuthHeadersRef.current!());
|
|
48
100
|
const response = await fetch(url, {
|
|
49
101
|
method: 'GET',
|
|
50
102
|
headers: {
|
|
@@ -58,34 +110,48 @@ export const useProtectedImage = ({
|
|
|
58
110
|
|
|
59
111
|
const blob = await response.blob();
|
|
60
112
|
const newBlobUrl = URL.createObjectURL(blob);
|
|
61
|
-
|
|
62
|
-
|
|
113
|
+
|
|
114
|
+
// Only update if URL hasn't changed during fetch and component is still mounted
|
|
115
|
+
if (previousUrlRef.current === url && mountedRef.current) {
|
|
116
|
+
// Cache the blob URL
|
|
117
|
+
blobUrlCache.set(url, newBlobUrl);
|
|
118
|
+
setBlobUrl(newBlobUrl);
|
|
119
|
+
} else {
|
|
120
|
+
// URL changed during fetch or component unmounted, revoke this blob URL
|
|
121
|
+
URL.revokeObjectURL(newBlobUrl);
|
|
122
|
+
}
|
|
63
123
|
} catch (error) {
|
|
64
124
|
console.error('Error fetching protected image:', error);
|
|
65
|
-
// On error,
|
|
66
|
-
|
|
125
|
+
// On error, only clear if URL hasn't changed and component is mounted
|
|
126
|
+
if (previousUrlRef.current === url && mountedRef.current) {
|
|
127
|
+
setBlobUrl(null);
|
|
128
|
+
}
|
|
129
|
+
} finally {
|
|
130
|
+
fetchingUrls.delete(url);
|
|
67
131
|
}
|
|
68
132
|
};
|
|
69
133
|
|
|
70
134
|
fetchProtectedImage();
|
|
135
|
+
}, [url]); // Only depend on url
|
|
71
136
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (blobUrlRef.current) {
|
|
75
|
-
URL.revokeObjectURL(blobUrlRef.current);
|
|
76
|
-
blobUrlRef.current = null;
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
}, [url, isProtected, getAuthHeaders]);
|
|
137
|
+
// Cleanup: Don't revoke blob URLs on unmount - keep them in cache for reuse
|
|
138
|
+
// They will be cleaned up when the URL changes or when the cache is cleared
|
|
80
139
|
|
|
81
140
|
// Return blob URL if available, otherwise return original URL (or null)
|
|
82
141
|
if (!url) {
|
|
83
142
|
return null;
|
|
84
143
|
}
|
|
85
144
|
|
|
86
|
-
const isUrlProtected = typeof
|
|
87
|
-
?
|
|
88
|
-
:
|
|
89
|
-
|
|
145
|
+
const isUrlProtected = typeof isProtectedRef.current === 'boolean'
|
|
146
|
+
? isProtectedRef.current
|
|
147
|
+
: isProtectedRef.current ? isProtectedRef.current(url) : false;
|
|
148
|
+
|
|
149
|
+
// For protected URLs, return cached blob URL or current blobUrl state
|
|
150
|
+
// For non-protected URLs, return the original URL
|
|
151
|
+
if (isUrlProtected) {
|
|
152
|
+
return blobUrl || blobUrlCache.get(url) || null;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return url;
|
|
90
156
|
};
|
|
91
157
|
|
package/demo.tsx
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
2
|
-
import { MentionInput, ShowMessageCard } from './src';
|
|
3
|
-
|
|
4
|
-
const Demo: React.FC = () => {
|
|
5
|
-
const [messages, setMessages] = useState<any[]>([
|
|
6
|
-
{
|
|
7
|
-
id: 1,
|
|
8
|
-
name: 'John Doe',
|
|
9
|
-
date: '14/07/2025 04:15 PM',
|
|
10
|
-
comment: 'Updated the status to Draft. Need <span class="mention-highlight">@team-leads</span> review before proceeding. <span class="hashtag-highlight">#urgent</span> <span class="hashtag-highlight">#review</span>',
|
|
11
|
-
objectName: '26may_item001',
|
|
12
|
-
revision: 'A',
|
|
13
|
-
object_type_icon: '📄',
|
|
14
|
-
relatedObject: 'test_jeet_july2334 (A)',
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
id: 2,
|
|
18
|
-
name: 'Mike Johnson',
|
|
19
|
-
date: '14/07/2025 04:15 PM',
|
|
20
|
-
comment: 'Revision A completed successfully. Ready for next phase. <span class="hashtag-highlight">#milestone</span>',
|
|
21
|
-
objectName: '26may_item001',
|
|
22
|
-
revision: 'A',
|
|
23
|
-
object_type_icon: '📋',
|
|
24
|
-
relatedObject: 'test_jeet_july2334 (A)',
|
|
25
|
-
}
|
|
26
|
-
]);
|
|
27
|
-
|
|
28
|
-
// Sample users for mentions
|
|
29
|
-
const users = [
|
|
30
|
-
{ id: 1, name: 'John Doe' },
|
|
31
|
-
{ id: 2, name: 'Jane Smith' },
|
|
32
|
-
{ id: 3, name: 'Mike Johnson' },
|
|
33
|
-
{ id: 4, name: 'Sarah Wilson' },
|
|
34
|
-
];
|
|
35
|
-
|
|
36
|
-
const handleSendMessage = (messageData: {
|
|
37
|
-
messageText: string;
|
|
38
|
-
messageHTML: string;
|
|
39
|
-
userSelectListWithIds: { id: number; name: string }[];
|
|
40
|
-
userSelectListName: string[];
|
|
41
|
-
tags: string[];
|
|
42
|
-
images?: File[];
|
|
43
|
-
imageUrl?: string | null;
|
|
44
|
-
}) => {
|
|
45
|
-
console.log('Message Data:', messageData);
|
|
46
|
-
console.log('Extracted Tags:', messageData.tags);
|
|
47
|
-
|
|
48
|
-
// Create a new message for display
|
|
49
|
-
const newMessage = {
|
|
50
|
-
id: Date.now(),
|
|
51
|
-
name: 'You',
|
|
52
|
-
date: new Date().toLocaleTimeString(),
|
|
53
|
-
comment: messageData.messageHTML,
|
|
54
|
-
imageUrl: messageData.imageUrl,
|
|
55
|
-
tags: messageData.tags,
|
|
56
|
-
mentions: messageData.userSelectListName,
|
|
57
|
-
objectName: 'new_item001', // You can customize this or make it dynamic
|
|
58
|
-
revision: 'A', // You can customize this or make it dynamic
|
|
59
|
-
object_type_icon: '✨', // You can customize this or make it dynamic
|
|
60
|
-
relatedObject: 'test_jeet_july2334 (A)', // You can customize this or make it dynamic
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
setMessages([...messages, newMessage]);
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
return (
|
|
67
|
-
<div style={{ maxWidth: '600px', margin: '20px auto', padding: '20px' }}>
|
|
68
|
-
<h1>React Mention Input with Hashtag Support</h1>
|
|
69
|
-
|
|
70
|
-
<div style={{ marginBottom: '20px' }}>
|
|
71
|
-
<h3>Features:</h3>
|
|
72
|
-
<ul>
|
|
73
|
-
<li>Type <strong>@</strong> to mention users (e.g., @John Doe)</li>
|
|
74
|
-
<li>Type <strong>#</strong> to create hashtags (e.g., #urgent #review #milestone)</li>
|
|
75
|
-
<li>Links are automatically detected and highlighted</li>
|
|
76
|
-
<li>Hashtags are extracted and returned in the tags array</li>
|
|
77
|
-
<li><strong>Custom Object Chip</strong> rendering with objectChipRender prop</li>
|
|
78
|
-
<li><strong>Object Type Icons</strong> for visual identification</li>
|
|
79
|
-
</ul>
|
|
80
|
-
</div>
|
|
81
|
-
|
|
82
|
-
<div style={{ marginBottom: '20px' }}>
|
|
83
|
-
<MentionInput
|
|
84
|
-
users={users}
|
|
85
|
-
placeholder="Type @ to mention and inform someone"
|
|
86
|
-
onSendMessage={handleSendMessage}
|
|
87
|
-
suggestionPosition="bottom"
|
|
88
|
-
/>
|
|
89
|
-
</div>
|
|
90
|
-
|
|
91
|
-
<div>
|
|
92
|
-
<h3>Messages (Default Object Chip):</h3>
|
|
93
|
-
<ShowMessageCard data={messages} />
|
|
94
|
-
</div>
|
|
95
|
-
|
|
96
|
-
<div style={{ marginTop: '30px' }}>
|
|
97
|
-
<h3>Messages (Custom Object Chip):</h3>
|
|
98
|
-
<ShowMessageCard
|
|
99
|
-
data={messages}
|
|
100
|
-
objectChipRender={({ objectName, revision, objectTypeIcon, item }) => (
|
|
101
|
-
<div style={{
|
|
102
|
-
backgroundColor: '#007bff',
|
|
103
|
-
color: 'white',
|
|
104
|
-
padding: '6px 12px',
|
|
105
|
-
borderRadius: '20px',
|
|
106
|
-
fontSize: '12px',
|
|
107
|
-
fontWeight: '600',
|
|
108
|
-
boxShadow: '0 2px 4px rgba(0,123,255,0.3)',
|
|
109
|
-
display: 'flex',
|
|
110
|
-
alignItems: 'center',
|
|
111
|
-
gap: '4px'
|
|
112
|
-
}}>
|
|
113
|
-
{objectTypeIcon && <span>{objectTypeIcon}</span>}
|
|
114
|
-
{objectName && <span>{objectName}</span>}
|
|
115
|
-
{revision && <span style={{ opacity: 0.8 }}> v{revision}</span>}
|
|
116
|
-
</div>
|
|
117
|
-
)}
|
|
118
|
-
/>
|
|
119
|
-
</div>
|
|
120
|
-
|
|
121
|
-
<div style={{ marginTop: '20px', padding: '15px', backgroundColor: '#f5f5f5', borderRadius: '8px' }}>
|
|
122
|
-
<h4>Example Usage:</h4>
|
|
123
|
-
<p>Try typing these examples:</p>
|
|
124
|
-
<ul>
|
|
125
|
-
<li>"Project update complete. Ready for @John Doe review #milestone #completed"</li>
|
|
126
|
-
<li>"Need urgent help with deployment @Jane Smith @Mike Johnson #urgent #deployment #help"</li>
|
|
127
|
-
<li>"Meeting scheduled for tomorrow #meeting #planning"</li>
|
|
128
|
-
</ul>
|
|
129
|
-
|
|
130
|
-
<h4 style={{ marginTop: '20px' }}>objectChipRender Example:</h4>
|
|
131
|
-
<pre style={{ backgroundColor: '#2d3748', color: '#e2e8f0', padding: '12px', borderRadius: '6px', fontSize: '12px', overflow: 'auto' }}>
|
|
132
|
-
{`<ShowMessageCard
|
|
133
|
-
data={messages}
|
|
134
|
-
objectChipRender={({ objectName, revision, objectTypeIcon, item }) => (
|
|
135
|
-
<div style={{
|
|
136
|
-
backgroundColor: '#007bff',
|
|
137
|
-
color: 'white',
|
|
138
|
-
padding: '6px 12px',
|
|
139
|
-
borderRadius: '20px',
|
|
140
|
-
display: 'flex',
|
|
141
|
-
alignItems: 'center',
|
|
142
|
-
gap: '4px'
|
|
143
|
-
}}>
|
|
144
|
-
{objectTypeIcon && <span>{objectTypeIcon}</span>}
|
|
145
|
-
{objectName} v{revision}
|
|
146
|
-
</div>
|
|
147
|
-
)}
|
|
148
|
-
/>`}
|
|
149
|
-
</pre>
|
|
150
|
-
|
|
151
|
-
<h4 style={{ marginTop: '20px' }}>Data Structure with Icon:</h4>
|
|
152
|
-
<pre style={{ backgroundColor: '#2d3748', color: '#e2e8f0', padding: '12px', borderRadius: '6px', fontSize: '12px', overflow: 'auto' }}>
|
|
153
|
-
{`const messageData = {
|
|
154
|
-
name: 'John Doe',
|
|
155
|
-
objectName: '26may_item001',
|
|
156
|
-
revision: 'A',
|
|
157
|
-
object_type_icon: '📄', // Document icon
|
|
158
|
-
relatedObject: 'test_jeet_july2334 (A)', // Related object
|
|
159
|
-
comment: 'Message content...'
|
|
160
|
-
};`}
|
|
161
|
-
</pre>
|
|
162
|
-
</div>
|
|
163
|
-
</div>
|
|
164
|
-
);
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
export default Demo;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import React, { ReactNode } from "react";
|
|
2
|
-
import "./MentionInput.css";
|
|
3
|
-
interface User {
|
|
4
|
-
id: number;
|
|
5
|
-
name: string;
|
|
6
|
-
}
|
|
7
|
-
interface MentionInputProps {
|
|
8
|
-
users: User[];
|
|
9
|
-
placeholder?: string;
|
|
10
|
-
containerClassName?: string;
|
|
11
|
-
inputContainerClassName?: string;
|
|
12
|
-
inputClassName?: string;
|
|
13
|
-
sendBtnClassName?: string;
|
|
14
|
-
suggestionListClassName?: string;
|
|
15
|
-
suggestionItemClassName?: string;
|
|
16
|
-
attachedImageContainerClassName?: string;
|
|
17
|
-
attachedImageContainerStyle?: React.CSSProperties;
|
|
18
|
-
imgClassName?: string;
|
|
19
|
-
imgStyle?: React.CSSProperties;
|
|
20
|
-
sendButtonIcon?: ReactNode;
|
|
21
|
-
attachmentButtonIcon?: ReactNode;
|
|
22
|
-
onSendMessage?: (obj: {
|
|
23
|
-
messageText: string;
|
|
24
|
-
messageHTML: string;
|
|
25
|
-
userSelectListWithIds: {
|
|
26
|
-
id: number;
|
|
27
|
-
name: string;
|
|
28
|
-
}[];
|
|
29
|
-
userSelectListName: string[];
|
|
30
|
-
tags: string[];
|
|
31
|
-
images?: File[];
|
|
32
|
-
imageUrl?: string | null;
|
|
33
|
-
}) => void;
|
|
34
|
-
suggestionPosition?: 'top' | 'bottom' | 'left' | 'right';
|
|
35
|
-
onImageUpload?: (file: File) => Promise<string>;
|
|
36
|
-
}
|
|
37
|
-
declare const MentionInput: React.FC<MentionInputProps>;
|
|
38
|
-
export default MentionInput;
|
package/dist/src/MentionInput.js
DELETED
|
@@ -1,376 +0,0 @@
|
|
|
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
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
11
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
12
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
13
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
14
|
-
function step(op) {
|
|
15
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
16
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
17
|
-
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;
|
|
18
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
19
|
-
switch (op[0]) {
|
|
20
|
-
case 0: case 1: t = op; break;
|
|
21
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
22
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
23
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
24
|
-
default:
|
|
25
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
26
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
27
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
28
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
29
|
-
if (t[2]) _.ops.pop();
|
|
30
|
-
_.trys.pop(); continue;
|
|
31
|
-
}
|
|
32
|
-
op = body.call(thisArg, _);
|
|
33
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
34
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
import React, { useState, useRef } from "react";
|
|
38
|
-
import ReactDOM from "react-dom";
|
|
39
|
-
import "./MentionInput.css";
|
|
40
|
-
var MentionInput = function (_a) {
|
|
41
|
-
var _b;
|
|
42
|
-
var users = _a.users, _c = _a.placeholder, placeholder = _c === void 0 ? "Type a message... (or drag & drop an image)" : _c, containerClassName = _a.containerClassName, inputContainerClassName = _a.inputContainerClassName, inputClassName = _a.inputClassName, sendBtnClassName = _a.sendBtnClassName, suggestionListClassName = _a.suggestionListClassName, suggestionItemClassName = _a.suggestionItemClassName, imgClassName = _a.imgClassName, imgStyle = _a.imgStyle, attachedImageContainerClassName = _a.attachedImageContainerClassName, attachedImageContainerStyle = _a.attachedImageContainerStyle, sendButtonIcon = _a.sendButtonIcon, attachmentButtonIcon = _a.attachmentButtonIcon, onSendMessage = _a.onSendMessage, _d = _a.suggestionPosition, suggestionPosition = _d === void 0 ? 'bottom' : _d, onImageUpload = _a.onImageUpload;
|
|
43
|
-
var _e = useState(""), inputValue = _e[0], setInputValue = _e[1]; // Plain text
|
|
44
|
-
var _f = useState([]), suggestions = _f[0], setSuggestions = _f[1];
|
|
45
|
-
var _g = useState(false), showSuggestions = _g[0], setShowSuggestions = _g[1];
|
|
46
|
-
var _h = useState(null), selectedImage = _h[0], setSelectedImage = _h[1];
|
|
47
|
-
var _j = useState(null), imageUrl = _j[0], setImageUrl = _j[1];
|
|
48
|
-
var _k = useState(false), isUploading = _k[0], setIsUploading = _k[1];
|
|
49
|
-
var _l = useState(false), isDraggingOver = _l[0], setIsDraggingOver = _l[1];
|
|
50
|
-
var inputRef = useRef(null);
|
|
51
|
-
var suggestionListRef = useRef(null);
|
|
52
|
-
var caretOffsetRef = useRef(0);
|
|
53
|
-
var userSelectListRef = useRef([]); // Only unique names
|
|
54
|
-
var userSelectListWithIdsRef = useRef([]); // Unique IDs with names
|
|
55
|
-
var tagsListRef = useRef([]); // Store hashtags
|
|
56
|
-
var fileInputRef = useRef(null);
|
|
57
|
-
var highlightMentionsAndLinks = function (text) {
|
|
58
|
-
// Regular expression for detecting links
|
|
59
|
-
var linkRegex = /(https?:\/\/[^\s]+)/g;
|
|
60
|
-
// Regular expression for detecting hashtags
|
|
61
|
-
var hashtagRegex = /#[\w]+/g;
|
|
62
|
-
// Highlight links
|
|
63
|
-
var highlightedText = text.replace(linkRegex, '<a href="$1" target="_blank" rel="noopener noreferrer" class="link-highlight">$1</a>');
|
|
64
|
-
// Highlight hashtags
|
|
65
|
-
highlightedText = highlightedText.replace(hashtagRegex, function (match) {
|
|
66
|
-
return "<span class=\"hashtag-highlight\">".concat(match, "</span>");
|
|
67
|
-
});
|
|
68
|
-
// Highlight mentions manually based on `userSelectListRef`
|
|
69
|
-
userSelectListRef === null || userSelectListRef === void 0 ? void 0 : userSelectListRef.current.forEach(function (userName) {
|
|
70
|
-
var mentionPattern = new RegExp("@".concat(userName, "(\\s|$)"), "g");
|
|
71
|
-
highlightedText = highlightedText.replace(mentionPattern, function (match) {
|
|
72
|
-
return "<span class=\"mention-highlight\">".concat(match.trim(), "</span> ");
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
return highlightedText;
|
|
76
|
-
};
|
|
77
|
-
var restoreCaretPosition = function (node, caretOffset) {
|
|
78
|
-
var range = document.createRange();
|
|
79
|
-
var sel = window.getSelection();
|
|
80
|
-
var charCount = 0;
|
|
81
|
-
var findCaret = function (currentNode) {
|
|
82
|
-
var _a;
|
|
83
|
-
for (var _i = 0, _b = Array.from(currentNode.childNodes); _i < _b.length; _i++) {
|
|
84
|
-
var child = _b[_i];
|
|
85
|
-
if (child.nodeType === Node.TEXT_NODE) {
|
|
86
|
-
var textLength = ((_a = child.textContent) === null || _a === void 0 ? void 0 : _a.length) || 0;
|
|
87
|
-
if (charCount + textLength >= caretOffset) {
|
|
88
|
-
range.setStart(child, caretOffset - charCount);
|
|
89
|
-
range.collapse(true);
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
charCount += textLength;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
else if (child.nodeType === Node.ELEMENT_NODE) {
|
|
97
|
-
if (findCaret(child))
|
|
98
|
-
return true;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return false;
|
|
102
|
-
};
|
|
103
|
-
findCaret(node);
|
|
104
|
-
if (sel) {
|
|
105
|
-
sel.removeAllRanges();
|
|
106
|
-
sel.addRange(range);
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
var handleInputChange = function () {
|
|
110
|
-
if (!inputRef.current)
|
|
111
|
-
return;
|
|
112
|
-
// Store current selection before modifications
|
|
113
|
-
var selection = window.getSelection();
|
|
114
|
-
var range = selection === null || selection === void 0 ? void 0 : selection.getRangeAt(0);
|
|
115
|
-
var newCaretOffset = 0;
|
|
116
|
-
if (range && inputRef.current.contains(range.startContainer)) {
|
|
117
|
-
var preCaretRange = range.cloneRange();
|
|
118
|
-
preCaretRange.selectNodeContents(inputRef.current);
|
|
119
|
-
preCaretRange.setEnd(range.startContainer, range.startOffset);
|
|
120
|
-
newCaretOffset = preCaretRange.toString().length;
|
|
121
|
-
}
|
|
122
|
-
caretOffsetRef.current = newCaretOffset;
|
|
123
|
-
var plainText = inputRef.current.innerText;
|
|
124
|
-
setInputValue(plainText);
|
|
125
|
-
// Process for mention suggestions
|
|
126
|
-
var mentionMatch = plainText.slice(0, newCaretOffset).match(/@(\S*)$/);
|
|
127
|
-
if (mentionMatch) {
|
|
128
|
-
var query_1 = mentionMatch[1].toLowerCase();
|
|
129
|
-
var filteredUsers = query_1 === "" ? users : users.filter(function (user) {
|
|
130
|
-
return user.name.toLowerCase().includes(query_1);
|
|
131
|
-
});
|
|
132
|
-
setSuggestions(filteredUsers);
|
|
133
|
-
setShowSuggestions(filteredUsers.length > 0);
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
setShowSuggestions(false);
|
|
137
|
-
}
|
|
138
|
-
// Extract and store hashtags
|
|
139
|
-
var hashtagMatches = plainText.match(/#[\w]+/g);
|
|
140
|
-
if (hashtagMatches) {
|
|
141
|
-
var uniqueTags = Array.from(new Set(hashtagMatches));
|
|
142
|
-
tagsListRef.current = uniqueTags;
|
|
143
|
-
}
|
|
144
|
-
else {
|
|
145
|
-
tagsListRef.current = [];
|
|
146
|
-
}
|
|
147
|
-
// Only apply highlighting if we have mentions, hashtags, or links to highlight
|
|
148
|
-
if (userSelectListRef.current.length > 0 || plainText.match(/(https?:\/\/[^\s]+)/g) || plainText.match(/#[\w]+/g)) {
|
|
149
|
-
var currentHTML = inputRef.current.innerHTML;
|
|
150
|
-
var htmlWithHighlights = highlightMentionsAndLinks(plainText);
|
|
151
|
-
// Only update if the highlighted HTML is different to avoid cursor jumping
|
|
152
|
-
if (currentHTML !== htmlWithHighlights) {
|
|
153
|
-
inputRef.current.innerHTML = htmlWithHighlights;
|
|
154
|
-
// Restore cursor position after changing innerHTML
|
|
155
|
-
restoreCaretPosition(inputRef.current, newCaretOffset);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
var renderSuggestions = function () {
|
|
160
|
-
if (!showSuggestions || !inputRef.current)
|
|
161
|
-
return null;
|
|
162
|
-
var getInitials = function (name) {
|
|
163
|
-
var nameParts = name.split(" ");
|
|
164
|
-
var initials = nameParts
|
|
165
|
-
.map(function (part) { var _a; return ((_a = part[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase()) || ""; })
|
|
166
|
-
.slice(0, 2)
|
|
167
|
-
.join("");
|
|
168
|
-
return initials;
|
|
169
|
-
};
|
|
170
|
-
var inputRect = inputRef.current.getBoundingClientRect();
|
|
171
|
-
var styles = {
|
|
172
|
-
position: 'absolute',
|
|
173
|
-
zIndex: 1000,
|
|
174
|
-
};
|
|
175
|
-
// Use suggestionPosition prop to adjust tooltip position
|
|
176
|
-
switch (suggestionPosition) {
|
|
177
|
-
case 'top':
|
|
178
|
-
styles.left = "".concat(inputRect.left, "px");
|
|
179
|
-
styles.top = "".concat(inputRect.top - 150, "px");
|
|
180
|
-
break;
|
|
181
|
-
case 'bottom':
|
|
182
|
-
styles.left = "".concat(inputRect.left, "px");
|
|
183
|
-
styles.top = "".concat(inputRect.bottom, "px");
|
|
184
|
-
break;
|
|
185
|
-
case 'left':
|
|
186
|
-
styles.left = "".concat(inputRect.left - 150, "px");
|
|
187
|
-
styles.top = "".concat(inputRect.top, "px");
|
|
188
|
-
break;
|
|
189
|
-
case 'right':
|
|
190
|
-
styles.left = "".concat(inputRect.right, "px");
|
|
191
|
-
styles.top = "".concat(inputRect.top, "px");
|
|
192
|
-
break;
|
|
193
|
-
default:
|
|
194
|
-
break;
|
|
195
|
-
}
|
|
196
|
-
return ReactDOM.createPortal(React.createElement("div", { className: "suggestion-container ".concat(suggestionListClassName || ''), style: styles },
|
|
197
|
-
React.createElement("ul", { className: "suggestion-list", ref: suggestionListRef }, suggestions.map(function (user) { return (React.createElement("li", { key: user.id, onClick: function () { return handleSuggestionClick(user); }, className: "suggestion-item ".concat(suggestionItemClassName || ''), role: "option", tabIndex: 0, "aria-selected": "false" },
|
|
198
|
-
React.createElement("div", { className: "user-icon" }, getInitials(user === null || user === void 0 ? void 0 : user.name)),
|
|
199
|
-
React.createElement("span", { className: "user-name" }, user.name))); }))), window.document.body);
|
|
200
|
-
};
|
|
201
|
-
var handleSuggestionClick = function (user) {
|
|
202
|
-
if (!inputRef.current)
|
|
203
|
-
return;
|
|
204
|
-
var plainText = inputValue;
|
|
205
|
-
var caretOffset = caretOffsetRef.current;
|
|
206
|
-
var mentionMatch = plainText.slice(0, caretOffset).match(/@(\S*)$/);
|
|
207
|
-
if (!userSelectListRef.current.includes(user.name)) {
|
|
208
|
-
userSelectListRef.current.push(user.name);
|
|
209
|
-
}
|
|
210
|
-
// Check if the ID is already stored
|
|
211
|
-
var isIdExists = userSelectListWithIdsRef.current.some(function (item) { return item.id === user.id; });
|
|
212
|
-
if (!isIdExists) {
|
|
213
|
-
userSelectListWithIdsRef.current.push(user);
|
|
214
|
-
}
|
|
215
|
-
if (!mentionMatch)
|
|
216
|
-
return;
|
|
217
|
-
var mentionIndex = plainText.slice(0, caretOffset).lastIndexOf("@");
|
|
218
|
-
// Append space after the mention
|
|
219
|
-
var newValue = plainText.substring(0, mentionIndex + 1) + user.name + " " + plainText.substring(caretOffset);
|
|
220
|
-
setInputValue(newValue);
|
|
221
|
-
inputRef.current.innerText = newValue;
|
|
222
|
-
// Highlight mentions and links with
|
|
223
|
-
var htmlWithHighlights = highlightMentionsAndLinks(newValue);
|
|
224
|
-
// Set highlighted content
|
|
225
|
-
inputRef.current.innerHTML = htmlWithHighlights;
|
|
226
|
-
setShowSuggestions(false);
|
|
227
|
-
// Adjust caret position after adding the mention and space
|
|
228
|
-
var mentionEnd = mentionIndex + user.name.length + 1;
|
|
229
|
-
restoreCaretPosition(inputRef.current, mentionEnd + 1); // +1 for the space
|
|
230
|
-
};
|
|
231
|
-
var handleImageSelect = function (event) { return __awaiter(void 0, void 0, void 0, function () {
|
|
232
|
-
var files, file;
|
|
233
|
-
return __generator(this, function (_a) {
|
|
234
|
-
switch (_a.label) {
|
|
235
|
-
case 0:
|
|
236
|
-
files = Array.from(event.target.files || []);
|
|
237
|
-
if (!(files.length > 0)) return [3 /*break*/, 2];
|
|
238
|
-
file = files[0];
|
|
239
|
-
if (!file.type.startsWith('image/')) return [3 /*break*/, 2];
|
|
240
|
-
return [4 /*yield*/, uploadImage(file)];
|
|
241
|
-
case 1:
|
|
242
|
-
_a.sent();
|
|
243
|
-
_a.label = 2;
|
|
244
|
-
case 2: return [2 /*return*/];
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
}); };
|
|
248
|
-
var handleDragOver = function (e) {
|
|
249
|
-
e.preventDefault();
|
|
250
|
-
e.stopPropagation();
|
|
251
|
-
// Only set dragging if files are being dragged
|
|
252
|
-
if (e.dataTransfer.types.includes('Files')) {
|
|
253
|
-
setIsDraggingOver(true);
|
|
254
|
-
}
|
|
255
|
-
};
|
|
256
|
-
var handleDragLeave = function (e) {
|
|
257
|
-
e.preventDefault();
|
|
258
|
-
e.stopPropagation();
|
|
259
|
-
// Check if we're leaving the container, not just moving between children
|
|
260
|
-
var rect = e.currentTarget.getBoundingClientRect();
|
|
261
|
-
var x = e.clientX;
|
|
262
|
-
var y = e.clientY;
|
|
263
|
-
if (x <= rect.left ||
|
|
264
|
-
x >= rect.right ||
|
|
265
|
-
y <= rect.top ||
|
|
266
|
-
y >= rect.bottom) {
|
|
267
|
-
setIsDraggingOver(false);
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
var handleDrop = function (e) { return __awaiter(void 0, void 0, void 0, function () {
|
|
271
|
-
var files, imageFiles;
|
|
272
|
-
return __generator(this, function (_a) {
|
|
273
|
-
switch (_a.label) {
|
|
274
|
-
case 0:
|
|
275
|
-
e.preventDefault();
|
|
276
|
-
e.stopPropagation();
|
|
277
|
-
setIsDraggingOver(false);
|
|
278
|
-
files = Array.from(e.dataTransfer.files);
|
|
279
|
-
if (!(files.length > 0)) return [3 /*break*/, 2];
|
|
280
|
-
imageFiles = files.filter(function (file) { return file.type.startsWith('image/'); });
|
|
281
|
-
if (!(imageFiles.length > 0)) return [3 /*break*/, 2];
|
|
282
|
-
return [4 /*yield*/, uploadImage(imageFiles[0])];
|
|
283
|
-
case 1:
|
|
284
|
-
_a.sent();
|
|
285
|
-
_a.label = 2;
|
|
286
|
-
case 2: return [2 /*return*/];
|
|
287
|
-
}
|
|
288
|
-
});
|
|
289
|
-
}); };
|
|
290
|
-
var uploadImage = function (file) { return __awaiter(void 0, void 0, void 0, function () {
|
|
291
|
-
var url, error_1;
|
|
292
|
-
return __generator(this, function (_a) {
|
|
293
|
-
switch (_a.label) {
|
|
294
|
-
case 0:
|
|
295
|
-
if (!onImageUpload) {
|
|
296
|
-
// If no upload function provided, store the file directly
|
|
297
|
-
setSelectedImage(file);
|
|
298
|
-
setImageUrl(URL.createObjectURL(file));
|
|
299
|
-
return [2 /*return*/];
|
|
300
|
-
}
|
|
301
|
-
_a.label = 1;
|
|
302
|
-
case 1:
|
|
303
|
-
_a.trys.push([1, 3, 4, 5]);
|
|
304
|
-
setIsUploading(true);
|
|
305
|
-
return [4 /*yield*/, onImageUpload(file)];
|
|
306
|
-
case 2:
|
|
307
|
-
url = _a.sent();
|
|
308
|
-
setSelectedImage(file);
|
|
309
|
-
setImageUrl(url);
|
|
310
|
-
return [3 /*break*/, 5];
|
|
311
|
-
case 3:
|
|
312
|
-
error_1 = _a.sent();
|
|
313
|
-
console.error('Error uploading image:', error_1);
|
|
314
|
-
return [3 /*break*/, 5];
|
|
315
|
-
case 4:
|
|
316
|
-
setIsUploading(false);
|
|
317
|
-
return [7 /*endfinally*/];
|
|
318
|
-
case 5: return [2 /*return*/];
|
|
319
|
-
}
|
|
320
|
-
});
|
|
321
|
-
}); };
|
|
322
|
-
var removeImage = function () {
|
|
323
|
-
setSelectedImage(null);
|
|
324
|
-
setImageUrl(null);
|
|
325
|
-
};
|
|
326
|
-
var handleSendMessage = function () {
|
|
327
|
-
if (inputRef.current) {
|
|
328
|
-
var messageText = inputRef.current.innerText.trim();
|
|
329
|
-
var messageHTML = inputRef.current.innerHTML.trim();
|
|
330
|
-
if ((messageText || selectedImage) && onSendMessage) {
|
|
331
|
-
onSendMessage({
|
|
332
|
-
messageText: messageText,
|
|
333
|
-
messageHTML: messageHTML,
|
|
334
|
-
userSelectListWithIds: userSelectListWithIdsRef.current,
|
|
335
|
-
userSelectListName: userSelectListRef.current,
|
|
336
|
-
tags: tagsListRef.current,
|
|
337
|
-
images: selectedImage ? [selectedImage] : [],
|
|
338
|
-
imageUrl: imageUrl
|
|
339
|
-
});
|
|
340
|
-
setInputValue("");
|
|
341
|
-
setShowSuggestions(false);
|
|
342
|
-
inputRef.current.innerText = "";
|
|
343
|
-
setSelectedImage(null);
|
|
344
|
-
setImageUrl(null);
|
|
345
|
-
userSelectListRef.current = [];
|
|
346
|
-
userSelectListWithIdsRef.current = [];
|
|
347
|
-
tagsListRef.current = [];
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
};
|
|
351
|
-
var handleKeyDown = function (event) {
|
|
352
|
-
if (event.key === "Enter" && !event.shiftKey) {
|
|
353
|
-
event.preventDefault(); // Prevent newline in content-editable
|
|
354
|
-
handleSendMessage(); // Trigger the same function as the Send button
|
|
355
|
-
}
|
|
356
|
-
};
|
|
357
|
-
return (React.createElement("div", { className: "mention-container ".concat(containerClassName || "") },
|
|
358
|
-
imageUrl && selectedImage && (React.createElement("div", { className: "image-preview-card ".concat(attachedImageContainerClassName || ""), style: attachedImageContainerStyle },
|
|
359
|
-
React.createElement("img", { src: imageUrl, alt: "Preview", className: imgClassName || "", style: imgStyle }),
|
|
360
|
-
React.createElement("button", { onClick: removeImage, className: "remove-image-btn", "aria-label": "Remove image" }, "\u00D7"))),
|
|
361
|
-
React.createElement("div", { className: "mention-input-container ".concat(inputContainerClassName || "", " ").concat(isDraggingOver ? 'dragging-over' : ''), onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDragEnd: function () { return setIsDraggingOver(false); }, onDrop: handleDrop },
|
|
362
|
-
isDraggingOver && (React.createElement("div", { className: "drag-overlay" },
|
|
363
|
-
React.createElement("div", { className: "drag-message" },
|
|
364
|
-
React.createElement("span", null, "Drop to upload")))),
|
|
365
|
-
React.createElement("button", { onClick: function () { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, className: "attachment-button", type: "button", "aria-label": "Attach image" },
|
|
366
|
-
React.createElement("span", { className: "attachment-icon" }, attachmentButtonIcon || "📷")),
|
|
367
|
-
React.createElement("div", { className: "mention-input-wrapper" },
|
|
368
|
-
(!inputValue || !inputRef.current || ((_b = inputRef.current) === null || _b === void 0 ? void 0 : _b.innerText.trim()) === "") && (React.createElement("span", { className: "placeholder" }, placeholder)),
|
|
369
|
-
React.createElement("div", { ref: inputRef, contentEditable: true, suppressContentEditableWarning: true, className: "mention-input ".concat(inputClassName || ""), onInput: handleInputChange, onKeyDown: handleKeyDown, onFocus: function () { return document.execCommand('styleWithCSS', false, 'false'); } })),
|
|
370
|
-
React.createElement("button", { onClick: handleSendMessage, className: "send-button ".concat(sendBtnClassName || ""), "aria-label": "Send message" }, sendButtonIcon || "➤"),
|
|
371
|
-
React.createElement("input", { type: "file", ref: fileInputRef, accept: "image/*", onChange: handleImageSelect, style: { display: 'none' } }),
|
|
372
|
-
isUploading && (React.createElement("div", { className: "upload-loading" },
|
|
373
|
-
React.createElement("span", null, "Uploading...")))),
|
|
374
|
-
renderSuggestions()));
|
|
375
|
-
};
|
|
376
|
-
export default MentionInput;
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import React, { CSSProperties, ReactNode } from "react";
|
|
2
|
-
import "./ShowMessageCard.css";
|
|
3
|
-
interface MessageCardProps {
|
|
4
|
-
[key: string]: any;
|
|
5
|
-
}
|
|
6
|
-
interface ShowMessageCardProps {
|
|
7
|
-
data: MessageCardProps[];
|
|
8
|
-
nameKey?: string;
|
|
9
|
-
dateKey?: string;
|
|
10
|
-
commentKey?: string;
|
|
11
|
-
imgSrcKey?: string;
|
|
12
|
-
imageUrlKey?: string;
|
|
13
|
-
objectNameKey?: string;
|
|
14
|
-
containerClassName?: string;
|
|
15
|
-
containerStyle?: CSSProperties;
|
|
16
|
-
cardClassName?: string;
|
|
17
|
-
cardStyle?: CSSProperties;
|
|
18
|
-
headerClassName?: string;
|
|
19
|
-
headerStyle?: CSSProperties;
|
|
20
|
-
imgClassName?: string;
|
|
21
|
-
imgStyle?: CSSProperties;
|
|
22
|
-
infoClassName?: string;
|
|
23
|
-
infoStyle?: CSSProperties;
|
|
24
|
-
nameClassName?: string;
|
|
25
|
-
nameStyle?: CSSProperties;
|
|
26
|
-
dateClassName?: string;
|
|
27
|
-
dateStyle?: CSSProperties;
|
|
28
|
-
bodyClassName?: string;
|
|
29
|
-
bodyStyle?: CSSProperties;
|
|
30
|
-
commentClassName?: string;
|
|
31
|
-
commentStyle?: CSSProperties;
|
|
32
|
-
attachedImageClassName?: string;
|
|
33
|
-
attachedImageStyle?: CSSProperties;
|
|
34
|
-
attachedImageContainerClassName?: string;
|
|
35
|
-
attachedImageContainerStyle?: CSSProperties;
|
|
36
|
-
objectNameClassName?: string;
|
|
37
|
-
objectNameStyle?: CSSProperties;
|
|
38
|
-
renderItem?: (element: MessageCardProps) => ReactNode;
|
|
39
|
-
}
|
|
40
|
-
export declare const ShowMessageCard: React.FC<ShowMessageCardProps>;
|
|
41
|
-
export {};
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
var __assign = (this && this.__assign) || function () {
|
|
2
|
-
__assign = Object.assign || function(t) {
|
|
3
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
-
s = arguments[i];
|
|
5
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
-
t[p] = s[p];
|
|
7
|
-
}
|
|
8
|
-
return t;
|
|
9
|
-
};
|
|
10
|
-
return __assign.apply(this, arguments);
|
|
11
|
-
};
|
|
12
|
-
import React, { useState } from "react";
|
|
13
|
-
import "./ShowMessageCard.css";
|
|
14
|
-
export var ShowMessageCard = function (_a) {
|
|
15
|
-
var data = _a.data, _b = _a.nameKey, nameKey = _b === void 0 ? "name" : _b, _c = _a.dateKey, dateKey = _c === void 0 ? "date" : _c, _d = _a.commentKey, commentKey = _d === void 0 ? "comment" : _d, _e = _a.imgSrcKey, imgSrcKey = _e === void 0 ? "imgSrc" : _e, _f = _a.imageUrlKey, imageUrlKey = _f === void 0 ? "imageUrl" : _f, // Default key for attached image
|
|
16
|
-
_g = _a.objectNameKey, // Default key for attached image
|
|
17
|
-
objectNameKey = _g === void 0 ? "objectName" : _g, // Default key for object identifier
|
|
18
|
-
containerClassName = _a.containerClassName, containerStyle = _a.containerStyle, cardClassName = _a.cardClassName, cardStyle = _a.cardStyle, headerClassName = _a.headerClassName, headerStyle = _a.headerStyle, imgClassName = _a.imgClassName, imgStyle = _a.imgStyle, infoClassName = _a.infoClassName, infoStyle = _a.infoStyle, nameClassName = _a.nameClassName, nameStyle = _a.nameStyle, dateClassName = _a.dateClassName, dateStyle = _a.dateStyle, bodyClassName = _a.bodyClassName, bodyStyle = _a.bodyStyle, commentClassName = _a.commentClassName, commentStyle = _a.commentStyle, attachedImageClassName = _a.attachedImageClassName, attachedImageStyle = _a.attachedImageStyle, attachedImageContainerClassName = _a.attachedImageContainerClassName, attachedImageContainerStyle = _a.attachedImageContainerStyle, objectNameClassName = _a.objectNameClassName, objectNameStyle = _a.objectNameStyle, renderItem = _a.renderItem;
|
|
19
|
-
console.log(data, "data==");
|
|
20
|
-
// State to manage initials for images that fail to load
|
|
21
|
-
var _h = useState({}), initialsState = _h[0], setInitialsState = _h[1];
|
|
22
|
-
// Handle image load failure
|
|
23
|
-
var handleImageError = function (id) {
|
|
24
|
-
setInitialsState(function (prevState) {
|
|
25
|
-
var _a;
|
|
26
|
-
return (__assign(__assign({}, prevState), (_a = {}, _a[id] = true, _a)));
|
|
27
|
-
});
|
|
28
|
-
};
|
|
29
|
-
// Helper function to generate initials from the name
|
|
30
|
-
var getInitials = function (name) {
|
|
31
|
-
var nameParts = name.split(" ");
|
|
32
|
-
var initials = nameParts
|
|
33
|
-
.map(function (part) { var _a; return ((_a = part[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase()) || ""; }) // Take the first letter of each part
|
|
34
|
-
.slice(0, 2) // Limit to 2 letters
|
|
35
|
-
.join("");
|
|
36
|
-
return initials;
|
|
37
|
-
};
|
|
38
|
-
// Helper function to extract hashtags and mentions from text
|
|
39
|
-
var extractTagsAndMentions = function (text) {
|
|
40
|
-
var plainText = text.replace(/<[^>]*>/g, ''); // Remove HTML tags to get plain text
|
|
41
|
-
var hashtags = plainText.match(/#[\w]+/g) || [];
|
|
42
|
-
var mentions = plainText.match(/@[\w\s-]+/g) || [];
|
|
43
|
-
return {
|
|
44
|
-
hashtags: Array.from(new Set(hashtags)), // Remove duplicates
|
|
45
|
-
mentions: Array.from(new Set(mentions.map(function (mention) { return mention.trim(); }))) // Remove duplicates and trim
|
|
46
|
-
};
|
|
47
|
-
};
|
|
48
|
-
return (React.createElement("div", { className: "message-card-container ".concat(containerClassName || ""), style: containerStyle }, data.map(function (item, index) {
|
|
49
|
-
if (renderItem !== undefined) {
|
|
50
|
-
// Use custom render function if provided
|
|
51
|
-
return (React.createElement(React.Fragment, { key: item.id || index }, renderItem(item)));
|
|
52
|
-
}
|
|
53
|
-
var showInitials = initialsState[item.id || index] || !item[imgSrcKey]; // Decide whether to show initials
|
|
54
|
-
// Extract tags and mentions from the comment
|
|
55
|
-
var _a = extractTagsAndMentions(item[commentKey] || ''), hashtags = _a.hashtags, mentions = _a.mentions;
|
|
56
|
-
return (React.createElement("div", { key: item.id || index, className: "message-card ".concat(cardClassName || ""), style: cardStyle },
|
|
57
|
-
React.createElement("div", { className: "message-card-header ".concat(headerClassName || ""), style: headerStyle },
|
|
58
|
-
React.createElement("div", { className: "message-card-header-left" },
|
|
59
|
-
showInitials ? (React.createElement("div", { className: "message-card-initials ".concat(imgClassName || ""), style: imgStyle }, getInitials(item[nameKey]))) : (React.createElement("img", { src: item[imgSrcKey], alt: item[nameKey], className: "message-card-img ".concat(imgClassName || ""), style: imgStyle, onError: function () { return handleImageError(item.id || index); } })),
|
|
60
|
-
React.createElement("div", { className: "message-card-info ".concat(infoClassName || ""), style: infoStyle },
|
|
61
|
-
React.createElement("h3", { className: "message-card-name ".concat(nameClassName || ""), style: nameStyle }, item[nameKey]),
|
|
62
|
-
React.createElement("p", { className: "message-card-date ".concat(dateClassName || ""), style: dateStyle }, item[dateKey]))),
|
|
63
|
-
item[objectNameKey] && (React.createElement("div", { className: "message-card-item-name ".concat(objectNameClassName || ""), style: objectNameStyle }, item[objectNameKey]))),
|
|
64
|
-
React.createElement("div", { className: "message-card-body ".concat(bodyClassName || ""), style: bodyStyle },
|
|
65
|
-
React.createElement("p", { className: "message-card-comment ".concat(commentClassName || ""), style: commentStyle, dangerouslySetInnerHTML: { __html: item[commentKey] } }),
|
|
66
|
-
(item === null || item === void 0 ? void 0 : item[imageUrlKey]) && (React.createElement("div", { className: "message-card-attached-image-container ".concat(attachedImageContainerClassName || ""), style: attachedImageContainerStyle },
|
|
67
|
-
React.createElement("img", { src: item[imageUrlKey], alt: "Attached", className: "message-card-attached-image ".concat(attachedImageClassName || ""), style: attachedImageStyle }))),
|
|
68
|
-
(hashtags.length > 0 || mentions.length > 0) && (React.createElement("div", { className: "message-card-tags" },
|
|
69
|
-
hashtags.map(function (tag, tagIndex) { return (React.createElement("span", { key: "hashtag-".concat(tagIndex), className: "tag-chip hashtag-chip" }, tag)); }),
|
|
70
|
-
mentions.map(function (mention, mentionIndex) { return (React.createElement("span", { key: "mention-".concat(mentionIndex), className: "tag-chip mention-chip" }, mention)); }))))));
|
|
71
|
-
})));
|
|
72
|
-
};
|
package/dist/src/index.d.ts
DELETED
package/dist/src/index.js
DELETED
package/index.html
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>React Mention Input Demo</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<div id="root"></div>
|
|
10
|
-
<script type="module" src="/main.tsx"></script>
|
|
11
|
-
</body>
|
|
12
|
-
</html>
|
package/main.tsx
DELETED
package/tsconfig.json
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES5",
|
|
4
|
-
"sourceMap": false,
|
|
5
|
-
"module": "ESNext",
|
|
6
|
-
"moduleResolution": "bundler",
|
|
7
|
-
"jsx": "react",
|
|
8
|
-
"lib": ["dom", "es6"],
|
|
9
|
-
"declaration": true,
|
|
10
|
-
"outDir": "./dist",
|
|
11
|
-
"strict": true,
|
|
12
|
-
"esModuleInterop": true,
|
|
13
|
-
"allowSyntheticDefaultImports": true,
|
|
14
|
-
"skipLibCheck": true
|
|
15
|
-
},
|
|
16
|
-
"include": [
|
|
17
|
-
"src/**/*"
|
|
18
|
-
],
|
|
19
|
-
"exclude": [
|
|
20
|
-
"node_modules",
|
|
21
|
-
"dist",
|
|
22
|
-
"demo.tsx",
|
|
23
|
-
"main.tsx",
|
|
24
|
-
"vite.config.ts",
|
|
25
|
-
"**/*.test.*",
|
|
26
|
-
"**/*.spec.*"
|
|
27
|
-
]
|
|
28
|
-
}
|