@amit_mandal/smart-logger-devtools 1.0.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.
@@ -0,0 +1,321 @@
1
+ .smart-logger-floating-button {
2
+ position: fixed;
3
+ bottom: 20px;
4
+ right: 20px;
5
+ width: 60px;
6
+ height: 60px;
7
+ border-radius: 50%;
8
+ background:
9
+ linear-gradient(
10
+ 135deg,
11
+ #667eea 0%,
12
+ #764ba2 100%);
13
+ border: none;
14
+ color: white;
15
+ font-size: 24px;
16
+ cursor: pointer;
17
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
18
+ display: flex;
19
+ align-items: center;
20
+ justify-content: center;
21
+ transition: all 0.3s ease;
22
+ z-index: 9998;
23
+ font-weight: bold;
24
+ }
25
+ .smart-logger-floating-button:hover,
26
+ .smart-logger-floating-button.hovered {
27
+ transform: scale(1.1);
28
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
29
+ }
30
+ .smart-logger-floating-button:active {
31
+ transform: scale(0.95);
32
+ }
33
+ .smart-logger-button-icon {
34
+ position: absolute;
35
+ font-size: 28px;
36
+ }
37
+ .smart-logger-button-count {
38
+ position: absolute;
39
+ bottom: 0;
40
+ right: 0;
41
+ background: #ff4757;
42
+ color: white;
43
+ border-radius: 50%;
44
+ width: 24px;
45
+ height: 24px;
46
+ display: flex;
47
+ align-items: center;
48
+ justify-content: center;
49
+ font-size: 12px;
50
+ font-weight: bold;
51
+ border: 2px solid white;
52
+ }
53
+ .smart-logger-modal-overlay {
54
+ position: fixed;
55
+ top: 0;
56
+ left: 0;
57
+ right: 0;
58
+ bottom: 0;
59
+ background: rgba(0, 0, 0, 0.5);
60
+ display: flex;
61
+ align-items: center;
62
+ justify-content: center;
63
+ z-index: 9999;
64
+ animation: fadeIn 0.3s ease;
65
+ }
66
+ @keyframes fadeIn {
67
+ from {
68
+ opacity: 0;
69
+ }
70
+ to {
71
+ opacity: 1;
72
+ }
73
+ }
74
+ .smart-logger-modal {
75
+ background: white;
76
+ border-radius: 12px;
77
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
78
+ width: 90%;
79
+ max-width: 900px;
80
+ height: 80vh;
81
+ max-height: 600px;
82
+ display: flex;
83
+ flex-direction: column;
84
+ animation: slideUp 0.3s ease;
85
+ font-family:
86
+ -apple-system,
87
+ BlinkMacSystemFont,
88
+ "Segoe UI",
89
+ Roboto,
90
+ "Helvetica Neue",
91
+ Arial,
92
+ sans-serif;
93
+ }
94
+ @keyframes slideUp {
95
+ from {
96
+ transform: translateY(20px);
97
+ opacity: 0;
98
+ }
99
+ to {
100
+ transform: translateY(0);
101
+ opacity: 1;
102
+ }
103
+ }
104
+ .smart-logger-modal-header {
105
+ display: flex;
106
+ justify-content: space-between;
107
+ align-items: center;
108
+ padding: 20px;
109
+ border-bottom: 1px solid #e0e0e0;
110
+ background:
111
+ linear-gradient(
112
+ 135deg,
113
+ #667eea 0%,
114
+ #764ba2 100%);
115
+ color: white;
116
+ border-radius: 12px 12px 0 0;
117
+ }
118
+ .smart-logger-modal-header h2 {
119
+ margin: 0;
120
+ font-size: 20px;
121
+ font-weight: 600;
122
+ }
123
+ .smart-logger-close-button {
124
+ background: transparent;
125
+ border: none;
126
+ color: white;
127
+ font-size: 24px;
128
+ cursor: pointer;
129
+ padding: 0;
130
+ width: 32px;
131
+ height: 32px;
132
+ display: flex;
133
+ align-items: center;
134
+ justify-content: center;
135
+ transition: transform 0.2s ease;
136
+ }
137
+ .smart-logger-close-button:hover {
138
+ transform: scale(1.2);
139
+ }
140
+ .smart-logger-modal-controls {
141
+ display: flex;
142
+ gap: 10px;
143
+ padding: 15px 20px;
144
+ border-bottom: 1px solid #e0e0e0;
145
+ background: #f9f9f9;
146
+ flex-wrap: wrap;
147
+ }
148
+ .smart-logger-search-input,
149
+ .smart-logger-filter-select {
150
+ padding: 8px 12px;
151
+ border: 1px solid #d0d0d0;
152
+ border-radius: 6px;
153
+ font-size: 14px;
154
+ font-family: inherit;
155
+ transition: border-color 0.2s ease;
156
+ }
157
+ .smart-logger-search-input {
158
+ flex: 1;
159
+ min-width: 200px;
160
+ }
161
+ .smart-logger-search-input:focus,
162
+ .smart-logger-filter-select:focus {
163
+ outline: none;
164
+ border-color: #667eea;
165
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
166
+ }
167
+ .smart-logger-filter-select {
168
+ min-width: 120px;
169
+ }
170
+ .smart-logger-clear-button {
171
+ padding: 8px 16px;
172
+ background: #ff4757;
173
+ color: white;
174
+ border: none;
175
+ border-radius: 6px;
176
+ cursor: pointer;
177
+ font-size: 14px;
178
+ font-weight: 500;
179
+ transition: background 0.2s ease;
180
+ }
181
+ .smart-logger-clear-button:hover {
182
+ background: #ff3838;
183
+ }
184
+ .smart-logger-modal-content {
185
+ flex: 1;
186
+ overflow-y: auto;
187
+ padding: 0;
188
+ }
189
+ .smart-logger-log-list {
190
+ list-style: none;
191
+ margin: 0;
192
+ padding: 0;
193
+ }
194
+ .smart-logger-log-item {
195
+ padding: 12px 20px;
196
+ border-bottom: 1px solid #f0f0f0;
197
+ transition: background-color 0.2s ease;
198
+ }
199
+ .smart-logger-log-item:hover {
200
+ background-color: #f9f9f9;
201
+ }
202
+ .smart-logger-log-item.error {
203
+ background-color: #fff5f5;
204
+ }
205
+ .smart-logger-log-item.warn {
206
+ background-color: #fffbf0;
207
+ }
208
+ .smart-logger-log-item.info {
209
+ background-color: #f0f7ff;
210
+ }
211
+ .smart-logger-log-header {
212
+ display: flex;
213
+ gap: 10px;
214
+ align-items: center;
215
+ margin-bottom: 6px;
216
+ }
217
+ .smart-logger-log-level {
218
+ font-weight: 600;
219
+ font-size: 12px;
220
+ text-transform: uppercase;
221
+ letter-spacing: 0.5px;
222
+ }
223
+ .smart-logger-log-timestamp {
224
+ font-size: 12px;
225
+ color: #999;
226
+ font-family:
227
+ "Monaco",
228
+ "Courier New",
229
+ monospace;
230
+ }
231
+ .smart-logger-log-message {
232
+ font-size: 14px;
233
+ color: #333;
234
+ word-break: break-word;
235
+ font-family:
236
+ "Monaco",
237
+ "Courier New",
238
+ monospace;
239
+ }
240
+ .smart-logger-log-details {
241
+ margin-top: 8px;
242
+ font-size: 12px;
243
+ }
244
+ .smart-logger-log-details summary {
245
+ cursor: pointer;
246
+ color: #667eea;
247
+ font-weight: 500;
248
+ padding: 4px 0;
249
+ user-select: none;
250
+ }
251
+ .smart-logger-log-details summary:hover {
252
+ text-decoration: underline;
253
+ }
254
+ .smart-logger-log-args {
255
+ background: #f5f5f5;
256
+ padding: 10px;
257
+ border-radius: 4px;
258
+ overflow-x: auto;
259
+ font-size: 12px;
260
+ margin: 8px 0 0 0;
261
+ border: 1px solid #e0e0e0;
262
+ max-height: 200px;
263
+ overflow-y: auto;
264
+ }
265
+ .smart-logger-empty-state {
266
+ display: flex;
267
+ align-items: center;
268
+ justify-content: center;
269
+ height: 100%;
270
+ color: #999;
271
+ font-size: 16px;
272
+ }
273
+ .smart-logger-modal-footer {
274
+ padding: 12px 20px;
275
+ border-top: 1px solid #e0e0e0;
276
+ background: #f9f9f9;
277
+ display: flex;
278
+ justify-content: space-between;
279
+ align-items: center;
280
+ border-radius: 0 0 12px 12px;
281
+ }
282
+ .smart-logger-log-count {
283
+ font-size: 12px;
284
+ color: #666;
285
+ font-weight: 500;
286
+ }
287
+ @media (max-width: 768px) {
288
+ .smart-logger-modal {
289
+ width: 95%;
290
+ max-height: 90vh;
291
+ }
292
+ .smart-logger-modal-controls {
293
+ flex-direction: column;
294
+ }
295
+ .smart-logger-search-input,
296
+ .smart-logger-filter-select,
297
+ .smart-logger-clear-button {
298
+ width: 100%;
299
+ }
300
+ .smart-logger-floating-button {
301
+ bottom: 10px;
302
+ right: 10px;
303
+ width: 50px;
304
+ height: 50px;
305
+ }
306
+ }
307
+ .text-red-500 {
308
+ color: #ff4757;
309
+ }
310
+ .text-yellow-500 {
311
+ color: #ffa502;
312
+ }
313
+ .text-blue-500 {
314
+ color: #0984e3;
315
+ }
316
+ .text-purple-500 {
317
+ color: #a29bfe;
318
+ }
319
+ .text-gray-700 {
320
+ color: #2d3436;
321
+ }
package/src/types.ts ADDED
@@ -0,0 +1,22 @@
1
+ export type LogLevel = "log" | "warn" | "error" | "info" | "debug";
2
+
3
+ export interface SmartLoggerConfig {
4
+ enabled?: boolean;
5
+ showTimestamp?: boolean;
6
+ showComponentName?: boolean;
7
+ maxHistory?: number;
8
+ level?: LogLevel[];
9
+ }
10
+
11
+ export interface LogEntry {
12
+ id: string;
13
+ timestamp: string;
14
+ level: LogLevel;
15
+ message: string;
16
+ args: any[];
17
+ }
18
+
19
+ export interface EventEmitter {
20
+ on(event: string, listener: Function): () => void;
21
+ emit(event: string, ...args: any[]): void;
22
+ }
@@ -0,0 +1,24 @@
1
+ import React, { useState } from "react";
2
+ import "../styles/index.css";
3
+
4
+ interface FloatingButtonProps {
5
+ onClick: () => void;
6
+ logCount: number;
7
+ }
8
+
9
+ export const FloatingButton: React.FC<FloatingButtonProps> = ({ onClick, logCount }) => {
10
+ const [isHovered, setIsHovered] = useState(false);
11
+
12
+ return (
13
+ <button
14
+ onClick={onClick}
15
+ onMouseEnter={() => setIsHovered(true)}
16
+ onMouseLeave={() => setIsHovered(false)}
17
+ className={`smart-logger-floating-button ${isHovered ? "hovered" : ""}`}
18
+ title="Open SmartLogger DevTools"
19
+ >
20
+ <span className="smart-logger-button-icon">📋</span>
21
+ <span className="smart-logger-button-count">{logCount}</span>
22
+ </button>
23
+ );
24
+ };
@@ -0,0 +1,97 @@
1
+ import React, { useState } from "react";
2
+ import type { LogEntry, LogLevel } from "../types";
3
+ import { getLogLevelColor } from "../utils/formatters";
4
+ import "../styles/index.css";
5
+
6
+ interface LogModalProps {
7
+ isOpen: boolean;
8
+ onClose: () => void;
9
+ logs: LogEntry[];
10
+ onClearLogs: () => void;
11
+ }
12
+ export const LogModal: React.FC<LogModalProps> = ({ isOpen, onClose, logs, onClearLogs }) => {
13
+ const [selectedLevel, setSelectedLevel] = useState<LogLevel | "all">("all");
14
+ const [searchQuery, setSearchQuery] = useState("");
15
+
16
+ const filteredLogs = logs.filter((log) => {
17
+ const levelMatch = selectedLevel === "all" || log.level === selectedLevel;
18
+ const searchMatch = log.message.toLowerCase().includes(searchQuery.toLowerCase());
19
+ return levelMatch && searchMatch;
20
+ });
21
+
22
+ if (!isOpen) return null;
23
+
24
+ return (
25
+ <div className="smart-logger-modal-overlay" onClick={onClose}>
26
+ <div className="smart-logger-modal" onClick={(e) => e.stopPropagation()}>
27
+ <div className="smart-logger-modal-header">
28
+ <h2>SmartLogger DevTools</h2>
29
+ <button className="smart-logger-close-button" onClick={onClose}>
30
+ ✕
31
+ </button>
32
+ </div>
33
+
34
+ <div className="smart-logger-modal-controls">
35
+ <input
36
+ type="text"
37
+ placeholder="Search logs..."
38
+ value={searchQuery}
39
+ onChange={(e) => setSearchQuery(e.target.value)}
40
+ className="smart-logger-search-input"
41
+ />
42
+
43
+ <select
44
+ value={selectedLevel}
45
+ onChange={(e) => setSelectedLevel(e.target.value as LogLevel | "all")}
46
+ className="smart-logger-filter-select"
47
+ >
48
+ <option value="all">All Levels</option>
49
+ <option value="log">Log</option>
50
+ <option value="info">Info</option>
51
+ <option value="warn">Warn</option>
52
+ <option value="error">Error</option>
53
+ <option value="debug">Debug</option>
54
+ </select>
55
+
56
+ <button className="smart-logger-clear-button" onClick={onClearLogs}>
57
+ Clear Logs
58
+ </button>
59
+ </div>
60
+
61
+ <div className="smart-logger-modal-content">
62
+ {filteredLogs.length === 0 ? (
63
+ <div className="smart-logger-empty-state">
64
+ <p>No logs to display</p>
65
+ </div>
66
+ ) : (
67
+ <ul className="smart-logger-log-list">
68
+ {filteredLogs.map((log) => (
69
+ <li key={log.id} className={`smart-logger-log-item ${log.level}`}>
70
+ <div className="smart-logger-log-header">
71
+ <span className={`smart-logger-log-level ${getLogLevelColor(log.level)}`}>
72
+ [{log.level.toUpperCase()}]
73
+ </span>
74
+ <span className="smart-logger-log-timestamp">{log.timestamp}</span>
75
+ </div>
76
+ <div className="smart-logger-log-message">{log.message}</div>
77
+ {log.args && log.args.length > 0 && (
78
+ <details className="smart-logger-log-details">
79
+ <summary>View Arguments</summary>
80
+ <pre className="smart-logger-log-args">
81
+ {JSON.stringify(log.args, null, 2)}
82
+ </pre>
83
+ </details>
84
+ )}
85
+ </li>
86
+ ))}
87
+ </ul>
88
+ )}
89
+ </div>
90
+
91
+ <div className="smart-logger-modal-footer">
92
+ <span className="smart-logger-log-count">Total: {filteredLogs.length} logs</span>
93
+ </div>
94
+ </div>
95
+ </div>
96
+ );
97
+ };
@@ -0,0 +1,29 @@
1
+ import type { LogEntry } from "../types";
2
+ export const formatLogMessage = (log: LogEntry): string => {
3
+ let message = `${log.timestamp} [${log.level.toUpperCase()}] ${log.message}`;
4
+ if (log.args && log.args.length > 0) {
5
+ message += ` ${log.args.map(arg => {
6
+ if (typeof arg === 'object' && arg !== null) {
7
+ return JSON.stringify(arg);
8
+ }
9
+ return String(arg);
10
+ }).join(' ')}`;
11
+ }
12
+ return message;
13
+ };
14
+
15
+ export const getLogLevelColor = (level: LogEntry["level"]) => {
16
+ switch (level) {
17
+ case "error":
18
+ return "text-red-500";
19
+ case "warn":
20
+ return "text-yellow-500";
21
+ case "info":
22
+ return "text-blue-500";
23
+ case "debug":
24
+ return "text-purple-500";
25
+ case "log":
26
+ default:
27
+ return "text-gray-700";
28
+ }
29
+ };