tv-console 1.0.0 → 1.0.2
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/index.esm.js +396 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +401 -1
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +408 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/index.umd.min.js +2 -0
- package/dist/index.umd.min.js.map +1 -0
- package/package.json +7 -5
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
(function (global, factory) {
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.TVConsole = {}));
|
|
5
|
+
})(this, (function (exports) { 'use strict';
|
|
6
|
+
|
|
7
|
+
const DEFAULT_CONFIG = {
|
|
8
|
+
enabled: true,
|
|
9
|
+
maxEntries: 100,
|
|
10
|
+
position: 'top-right',
|
|
11
|
+
width: '400px',
|
|
12
|
+
height: '300px',
|
|
13
|
+
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
|
14
|
+
textColor: '#ffffff',
|
|
15
|
+
fontSize: '14px',
|
|
16
|
+
opacity: 0.9,
|
|
17
|
+
showTimestamp: true,
|
|
18
|
+
className: 'tv-console',
|
|
19
|
+
zIndex: 9999,
|
|
20
|
+
showLogLevel: true,
|
|
21
|
+
logLevels: ['log', 'info', 'warn', 'error', 'debug'],
|
|
22
|
+
formatter: (entry) => {
|
|
23
|
+
const timestamp = entry.timestamp.toLocaleTimeString();
|
|
24
|
+
const level = `[${entry.level.toUpperCase()}]` ;
|
|
25
|
+
const prefix = `[${timestamp}]` ;
|
|
26
|
+
return `${prefix} ${level} ${entry.message}`.trim();
|
|
27
|
+
},
|
|
28
|
+
focusKey: '12345',
|
|
29
|
+
unfocusKey: 'Escape',
|
|
30
|
+
onFocus: () => { },
|
|
31
|
+
onUnfocus: () => { },
|
|
32
|
+
enableKeyboardNav: true,
|
|
33
|
+
showFocusIndicator: true
|
|
34
|
+
};
|
|
35
|
+
class TVConsole {
|
|
36
|
+
constructor(config = {}) {
|
|
37
|
+
Object.defineProperty(this, "config", {
|
|
38
|
+
enumerable: true,
|
|
39
|
+
configurable: true,
|
|
40
|
+
writable: true,
|
|
41
|
+
value: void 0
|
|
42
|
+
});
|
|
43
|
+
Object.defineProperty(this, "logs", {
|
|
44
|
+
enumerable: true,
|
|
45
|
+
configurable: true,
|
|
46
|
+
writable: true,
|
|
47
|
+
value: []
|
|
48
|
+
});
|
|
49
|
+
Object.defineProperty(this, "container", {
|
|
50
|
+
enumerable: true,
|
|
51
|
+
configurable: true,
|
|
52
|
+
writable: true,
|
|
53
|
+
value: null
|
|
54
|
+
});
|
|
55
|
+
Object.defineProperty(this, "isVisible", {
|
|
56
|
+
enumerable: true,
|
|
57
|
+
configurable: true,
|
|
58
|
+
writable: true,
|
|
59
|
+
value: false
|
|
60
|
+
});
|
|
61
|
+
Object.defineProperty(this, "originalConsole", {
|
|
62
|
+
enumerable: true,
|
|
63
|
+
configurable: true,
|
|
64
|
+
writable: true,
|
|
65
|
+
value: void 0
|
|
66
|
+
});
|
|
67
|
+
Object.defineProperty(this, "_isFocused", {
|
|
68
|
+
enumerable: true,
|
|
69
|
+
configurable: true,
|
|
70
|
+
writable: true,
|
|
71
|
+
value: false
|
|
72
|
+
});
|
|
73
|
+
Object.defineProperty(this, "keyBuffer", {
|
|
74
|
+
enumerable: true,
|
|
75
|
+
configurable: true,
|
|
76
|
+
writable: true,
|
|
77
|
+
value: ''
|
|
78
|
+
});
|
|
79
|
+
Object.defineProperty(this, "keyBufferTimeout", {
|
|
80
|
+
enumerable: true,
|
|
81
|
+
configurable: true,
|
|
82
|
+
writable: true,
|
|
83
|
+
value: null
|
|
84
|
+
});
|
|
85
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
86
|
+
this.originalConsole = console;
|
|
87
|
+
this.initialize();
|
|
88
|
+
}
|
|
89
|
+
initialize() {
|
|
90
|
+
if (!this.config.enabled)
|
|
91
|
+
return;
|
|
92
|
+
this.createContainer();
|
|
93
|
+
this.interceptConsole();
|
|
94
|
+
this.setupKeyboardListeners();
|
|
95
|
+
this.render();
|
|
96
|
+
}
|
|
97
|
+
createContainer() {
|
|
98
|
+
this.container = document.createElement('div');
|
|
99
|
+
this.container.className = this.config.className;
|
|
100
|
+
this.container.tabIndex = this.config.enableKeyboardNav ? 0 : -1;
|
|
101
|
+
this.container.style.cssText = `
|
|
102
|
+
position: fixed;
|
|
103
|
+
${this.getPositionStyles()}
|
|
104
|
+
width: ${this.config.width};
|
|
105
|
+
height: ${this.config.height};
|
|
106
|
+
background-color: ${this.config.backgroundColor};
|
|
107
|
+
color: ${this.config.textColor};
|
|
108
|
+
font-family: 'Courier New', monospace;
|
|
109
|
+
font-size: ${this.config.fontSize};
|
|
110
|
+
padding: 10px;
|
|
111
|
+
border-radius: 5px;
|
|
112
|
+
overflow-y: auto;
|
|
113
|
+
z-index: ${this.config.zIndex};
|
|
114
|
+
opacity: ${this.config.opacity};
|
|
115
|
+
display: none;
|
|
116
|
+
word-wrap: break-word;
|
|
117
|
+
white-space: pre-wrap;
|
|
118
|
+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
|
|
119
|
+
outline: none;
|
|
120
|
+
`;
|
|
121
|
+
document.body.appendChild(this.container);
|
|
122
|
+
}
|
|
123
|
+
getPositionStyles() {
|
|
124
|
+
switch (this.config.position) {
|
|
125
|
+
case 'top-left':
|
|
126
|
+
return 'top: 10px; left: 10px;';
|
|
127
|
+
case 'top-right':
|
|
128
|
+
return 'top: 10px; right: 10px;';
|
|
129
|
+
case 'bottom-left':
|
|
130
|
+
return 'bottom: 10px; left: 10px;';
|
|
131
|
+
case 'bottom-right':
|
|
132
|
+
return 'bottom: 10px; right: 10px;';
|
|
133
|
+
default:
|
|
134
|
+
return 'top: 10px; right: 10px;';
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
interceptConsole() {
|
|
138
|
+
const methods = ['log', 'info', 'warn', 'error', 'debug'];
|
|
139
|
+
methods.forEach(method => {
|
|
140
|
+
const original = this.originalConsole[method];
|
|
141
|
+
this.originalConsole[method] = (...args) => {
|
|
142
|
+
// Call original console method
|
|
143
|
+
original.apply(this.originalConsole, args);
|
|
144
|
+
// Add to TV console
|
|
145
|
+
this.addLog(method, ...args);
|
|
146
|
+
};
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
addLog(level, ...args) {
|
|
150
|
+
if (!this.config.enabled || !this.config.logLevels.includes(level)) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const message = args.map(arg => this.formatArgument(arg)).join(' ');
|
|
154
|
+
const entry = {
|
|
155
|
+
id: Date.now().toString() + Math.random().toString(36).substr(2, 9),
|
|
156
|
+
level,
|
|
157
|
+
message,
|
|
158
|
+
timestamp: new Date(),
|
|
159
|
+
data: args,
|
|
160
|
+
stack: level === 'error' ? new Error().stack : undefined
|
|
161
|
+
};
|
|
162
|
+
this.logs.push(entry);
|
|
163
|
+
// Keep only the latest entries
|
|
164
|
+
if (this.logs.length > this.config.maxEntries) {
|
|
165
|
+
this.logs = this.logs.slice(-this.config.maxEntries);
|
|
166
|
+
}
|
|
167
|
+
this.render();
|
|
168
|
+
}
|
|
169
|
+
formatArgument(arg) {
|
|
170
|
+
if (arg === null)
|
|
171
|
+
return 'null';
|
|
172
|
+
if (arg === undefined)
|
|
173
|
+
return 'undefined';
|
|
174
|
+
// Handle Error objects specifically
|
|
175
|
+
if (arg instanceof Error) {
|
|
176
|
+
return `Error: ${arg.message}\nStack: ${arg.stack || 'No stack trace available'}`;
|
|
177
|
+
}
|
|
178
|
+
// Handle other objects
|
|
179
|
+
if (typeof arg === 'object') {
|
|
180
|
+
try {
|
|
181
|
+
// Try JSON.stringify first
|
|
182
|
+
return JSON.stringify(arg, null, 2);
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
// If JSON.stringify fails, try to get a meaningful string representation
|
|
186
|
+
if (arg.toString && arg.toString !== Object.prototype.toString) {
|
|
187
|
+
return arg.toString();
|
|
188
|
+
}
|
|
189
|
+
// For objects that don't have a custom toString, show their keys
|
|
190
|
+
const keys = Object.keys(arg);
|
|
191
|
+
if (keys.length > 0) {
|
|
192
|
+
return `[Object with keys: ${keys.join(', ')}]`;
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
return '[Empty Object]';
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// Handle functions
|
|
200
|
+
if (typeof arg === 'function') {
|
|
201
|
+
return `[Function: ${arg.name || 'anonymous'}]`;
|
|
202
|
+
}
|
|
203
|
+
// Handle other primitive types
|
|
204
|
+
return String(arg);
|
|
205
|
+
}
|
|
206
|
+
render() {
|
|
207
|
+
if (!this.container)
|
|
208
|
+
return;
|
|
209
|
+
const filteredLogs = this.logs.filter(log => this.config.logLevels.includes(log.level));
|
|
210
|
+
const formattedLogs = filteredLogs.map(log => {
|
|
211
|
+
const formatted = this.config.formatter(log);
|
|
212
|
+
const levelClass = `tv-console-${log.level}`;
|
|
213
|
+
return `<div class="${levelClass}">${this.escapeHtml(formatted)}</div>`;
|
|
214
|
+
});
|
|
215
|
+
this.container.innerHTML = formattedLogs.join('');
|
|
216
|
+
// Auto-scroll to the bottom to show the most recent logs
|
|
217
|
+
this.container.scrollTop = this.container.scrollHeight;
|
|
218
|
+
}
|
|
219
|
+
escapeHtml(text) {
|
|
220
|
+
const div = document.createElement('div');
|
|
221
|
+
div.textContent = text;
|
|
222
|
+
return div.innerHTML;
|
|
223
|
+
}
|
|
224
|
+
setupKeyboardListeners() {
|
|
225
|
+
document.addEventListener('keydown', (event) => {
|
|
226
|
+
this.handleKeyDown(event);
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
handleKeyDown(event) {
|
|
230
|
+
// Handle focus key combination
|
|
231
|
+
if (this.config.focusKey) {
|
|
232
|
+
this.keyBuffer += event.key;
|
|
233
|
+
// Clear buffer after 2 seconds of inactivity
|
|
234
|
+
if (this.keyBufferTimeout) {
|
|
235
|
+
clearTimeout(this.keyBufferTimeout);
|
|
236
|
+
}
|
|
237
|
+
this.keyBufferTimeout = window.setTimeout(() => {
|
|
238
|
+
this.keyBuffer = '';
|
|
239
|
+
}, 2000);
|
|
240
|
+
// Check if key combination matches
|
|
241
|
+
if (this.keyBuffer.includes(this.config.focusKey)) {
|
|
242
|
+
this.focus();
|
|
243
|
+
this.keyBuffer = '';
|
|
244
|
+
event.preventDefault();
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// Handle unfocus key
|
|
249
|
+
if (this.config.unfocusKey && event.key === this.config.unfocusKey && this._isFocused) {
|
|
250
|
+
this.unfocus();
|
|
251
|
+
event.preventDefault();
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
// Handle keyboard navigation when focused
|
|
255
|
+
if (this._isFocused && this.config.enableKeyboardNav && this.container) {
|
|
256
|
+
switch (event.key) {
|
|
257
|
+
case 'ArrowUp':
|
|
258
|
+
this.container.scrollTop -= 20;
|
|
259
|
+
event.preventDefault();
|
|
260
|
+
break;
|
|
261
|
+
case 'ArrowDown':
|
|
262
|
+
this.container.scrollTop += 20;
|
|
263
|
+
event.preventDefault();
|
|
264
|
+
break;
|
|
265
|
+
case 'PageUp':
|
|
266
|
+
this.container.scrollTop -= this.container.clientHeight;
|
|
267
|
+
event.preventDefault();
|
|
268
|
+
break;
|
|
269
|
+
case 'PageDown':
|
|
270
|
+
this.container.scrollTop += this.container.clientHeight;
|
|
271
|
+
event.preventDefault();
|
|
272
|
+
break;
|
|
273
|
+
case 'Home':
|
|
274
|
+
this.container.scrollTop = 0;
|
|
275
|
+
event.preventDefault();
|
|
276
|
+
break;
|
|
277
|
+
case 'End':
|
|
278
|
+
this.container.scrollTop = this.container.scrollHeight;
|
|
279
|
+
event.preventDefault();
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
// Public API methods
|
|
285
|
+
log(...args) {
|
|
286
|
+
this.addLog('log', ...args);
|
|
287
|
+
}
|
|
288
|
+
info(...args) {
|
|
289
|
+
this.addLog('info', ...args);
|
|
290
|
+
}
|
|
291
|
+
warn(...args) {
|
|
292
|
+
this.addLog('warn', ...args);
|
|
293
|
+
}
|
|
294
|
+
error(...args) {
|
|
295
|
+
this.addLog('error', ...args);
|
|
296
|
+
}
|
|
297
|
+
debug(...args) {
|
|
298
|
+
this.addLog('debug', ...args);
|
|
299
|
+
}
|
|
300
|
+
clear() {
|
|
301
|
+
this.logs = [];
|
|
302
|
+
this.render();
|
|
303
|
+
}
|
|
304
|
+
show() {
|
|
305
|
+
if (this.container) {
|
|
306
|
+
this.container.style.display = 'block';
|
|
307
|
+
this.isVisible = true;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
hide() {
|
|
311
|
+
if (this.container) {
|
|
312
|
+
this.container.style.display = 'none';
|
|
313
|
+
this.isVisible = false;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
toggle() {
|
|
317
|
+
if (this.isVisible) {
|
|
318
|
+
this.hide();
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
this.show();
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
focus() {
|
|
325
|
+
if (!this.container || this._isFocused)
|
|
326
|
+
return;
|
|
327
|
+
this._isFocused = true;
|
|
328
|
+
this.container.focus();
|
|
329
|
+
if (this.config.showFocusIndicator) {
|
|
330
|
+
this.container.style.border = '2px solid #00ff00';
|
|
331
|
+
this.container.style.boxShadow = '0 0 10px rgba(0, 255, 0, 0.5)';
|
|
332
|
+
}
|
|
333
|
+
// Call onFocus callback if provided
|
|
334
|
+
if (this.config.onFocus) {
|
|
335
|
+
this.config.onFocus();
|
|
336
|
+
}
|
|
337
|
+
console.log('TV Console focused - Use arrow keys to scroll, Escape to unfocus');
|
|
338
|
+
}
|
|
339
|
+
unfocus() {
|
|
340
|
+
if (!this.container || !this._isFocused)
|
|
341
|
+
return;
|
|
342
|
+
this._isFocused = false;
|
|
343
|
+
this.container.blur();
|
|
344
|
+
if (this.config.showFocusIndicator) {
|
|
345
|
+
this.container.style.border = '';
|
|
346
|
+
this.container.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.3)';
|
|
347
|
+
}
|
|
348
|
+
// Call onUnfocus callback if provided
|
|
349
|
+
if (this.config.onUnfocus) {
|
|
350
|
+
this.config.onUnfocus();
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
isFocused() {
|
|
354
|
+
return this._isFocused;
|
|
355
|
+
}
|
|
356
|
+
destroy() {
|
|
357
|
+
if (this.container) {
|
|
358
|
+
document.body.removeChild(this.container);
|
|
359
|
+
this.container = null;
|
|
360
|
+
}
|
|
361
|
+
// Restore original console methods
|
|
362
|
+
Object.assign(console, this.originalConsole);
|
|
363
|
+
}
|
|
364
|
+
getLogs() {
|
|
365
|
+
return [...this.logs];
|
|
366
|
+
}
|
|
367
|
+
setConfig(config) {
|
|
368
|
+
this.config = { ...this.config, ...config };
|
|
369
|
+
if (this.container) {
|
|
370
|
+
this.container.style.cssText = `
|
|
371
|
+
position: fixed;
|
|
372
|
+
${this.getPositionStyles()}
|
|
373
|
+
width: ${this.config.width};
|
|
374
|
+
height: ${this.config.height};
|
|
375
|
+
background-color: ${this.config.backgroundColor};
|
|
376
|
+
color: ${this.config.textColor};
|
|
377
|
+
font-family: 'Courier New', monospace;
|
|
378
|
+
font-size: ${this.config.fontSize};
|
|
379
|
+
padding: 10px;
|
|
380
|
+
border-radius: 5px;
|
|
381
|
+
overflow-y: auto;
|
|
382
|
+
z-index: ${this.config.zIndex};
|
|
383
|
+
opacity: ${this.config.opacity};
|
|
384
|
+
display: ${this.isVisible ? 'block' : 'none'};
|
|
385
|
+
word-wrap: break-word;
|
|
386
|
+
white-space: pre-wrap;
|
|
387
|
+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
|
|
388
|
+
outline: none;
|
|
389
|
+
`;
|
|
390
|
+
this.container.tabIndex = this.config.enableKeyboardNav ? 0 : -1;
|
|
391
|
+
}
|
|
392
|
+
this.render();
|
|
393
|
+
}
|
|
394
|
+
exportLogs() {
|
|
395
|
+
return this.logs.map(log => {
|
|
396
|
+
const timestamp = log.timestamp.toISOString();
|
|
397
|
+
return `[${timestamp}] [${log.level.toUpperCase()}] ${log.message}`;
|
|
398
|
+
}).join('\n');
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
exports.TVConsole = TVConsole;
|
|
403
|
+
exports.default = TVConsole;
|
|
404
|
+
|
|
405
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
406
|
+
|
|
407
|
+
}));
|
|
408
|
+
//# sourceMappingURL=index.umd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../src/tv-console.ts"],"sourcesContent":["import type { TVConsoleConfig, LogLevel, LogEntry, TVConsoleInstance } from './types';\n\nconst DEFAULT_CONFIG: Required<TVConsoleConfig> = {\n enabled: true,\n maxEntries: 100,\n position: 'top-right',\n width: '400px',\n height: '300px',\n backgroundColor: 'rgba(0, 0, 0, 0.8)',\n textColor: '#ffffff',\n fontSize: '14px',\n opacity: 0.9,\n showTimestamp: true,\n className: 'tv-console',\n zIndex: 9999,\n showLogLevel: true,\n logLevels: ['log', 'info', 'warn', 'error', 'debug'],\n formatter: (entry: LogEntry) => {\n const timestamp = entry.timestamp.toLocaleTimeString();\n const level = DEFAULT_CONFIG.showLogLevel ? `[${entry.level.toUpperCase()}]` : '';\n const prefix = DEFAULT_CONFIG.showTimestamp ? `[${timestamp}]` : '';\n return `${prefix} ${level} ${entry.message}`.trim();\n },\n focusKey: '12345',\n unfocusKey: 'Escape',\n onFocus: () => {},\n onUnfocus: () => {},\n enableKeyboardNav: true,\n showFocusIndicator: true\n};\n\nexport class TVConsole implements TVConsoleInstance {\n private config: Required<TVConsoleConfig>;\n private logs: LogEntry[] = [];\n private container: HTMLDivElement | null = null;\n private isVisible = false;\n private originalConsole: Console;\n private _isFocused = false;\n private keyBuffer = '';\n private keyBufferTimeout: number | null = null;\n\n constructor(config: TVConsoleConfig = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.originalConsole = console;\n this.initialize();\n }\n\n private initialize(): void {\n if (!this.config.enabled) return;\n\n this.createContainer();\n this.interceptConsole();\n this.setupKeyboardListeners();\n this.render();\n }\n\n private createContainer(): void {\n this.container = document.createElement('div');\n this.container.className = this.config.className;\n this.container.tabIndex = this.config.enableKeyboardNav ? 0 : -1;\n this.container.style.cssText = `\n position: fixed;\n ${this.getPositionStyles()}\n width: ${this.config.width};\n height: ${this.config.height};\n background-color: ${this.config.backgroundColor};\n color: ${this.config.textColor};\n font-family: 'Courier New', monospace;\n font-size: ${this.config.fontSize};\n padding: 10px;\n border-radius: 5px;\n overflow-y: auto;\n z-index: ${this.config.zIndex};\n opacity: ${this.config.opacity};\n display: none;\n word-wrap: break-word;\n white-space: pre-wrap;\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);\n outline: none;\n `;\n\n document.body.appendChild(this.container);\n }\n\n private getPositionStyles(): string {\n switch (this.config.position) {\n case 'top-left':\n return 'top: 10px; left: 10px;';\n case 'top-right':\n return 'top: 10px; right: 10px;';\n case 'bottom-left':\n return 'bottom: 10px; left: 10px;';\n case 'bottom-right':\n return 'bottom: 10px; right: 10px;';\n default:\n return 'top: 10px; right: 10px;';\n }\n }\n\n private interceptConsole(): void {\n const methods: LogLevel[] = ['log', 'info', 'warn', 'error', 'debug'];\n \n methods.forEach(method => {\n const original = this.originalConsole[method];\n this.originalConsole[method] = (...args: any[]) => {\n // Call original console method\n original.apply(this.originalConsole, args);\n \n // Add to TV console\n this.addLog(method, ...args);\n };\n });\n }\n\n private addLog(level: LogLevel, ...args: any[]): void {\n if (!this.config.enabled || !this.config.logLevels.includes(level)) {\n return;\n }\n\n const message = args.map(arg => this.formatArgument(arg)).join(' ');\n const entry: LogEntry = {\n id: Date.now().toString() + Math.random().toString(36).substr(2, 9),\n level,\n message,\n timestamp: new Date(),\n data: args,\n stack: level === 'error' ? new Error().stack : undefined\n };\n\n this.logs.push(entry);\n\n // Keep only the latest entries\n if (this.logs.length > this.config.maxEntries) {\n this.logs = this.logs.slice(-this.config.maxEntries);\n }\n\n this.render();\n }\n\n private formatArgument(arg: any): string {\n if (arg === null) return 'null';\n if (arg === undefined) return 'undefined';\n \n // Handle Error objects specifically\n if (arg instanceof Error) {\n return `Error: ${arg.message}\\nStack: ${arg.stack || 'No stack trace available'}`;\n }\n \n // Handle other objects\n if (typeof arg === 'object') {\n try {\n // Try JSON.stringify first\n return JSON.stringify(arg, null, 2);\n } catch {\n // If JSON.stringify fails, try to get a meaningful string representation\n if (arg.toString && arg.toString !== Object.prototype.toString) {\n return arg.toString();\n }\n \n // For objects that don't have a custom toString, show their keys\n const keys = Object.keys(arg);\n if (keys.length > 0) {\n return `[Object with keys: ${keys.join(', ')}]`;\n } else {\n return '[Empty Object]';\n }\n }\n }\n \n // Handle functions\n if (typeof arg === 'function') {\n return `[Function: ${arg.name || 'anonymous'}]`;\n }\n \n // Handle other primitive types\n return String(arg);\n }\n\n private render(): void {\n if (!this.container) return;\n\n const filteredLogs = this.logs.filter(log => \n this.config.logLevels.includes(log.level)\n );\n\n const formattedLogs = filteredLogs.map(log => {\n const formatted = this.config.formatter(log);\n const levelClass = `tv-console-${log.level}`;\n return `<div class=\"${levelClass}\">${this.escapeHtml(formatted)}</div>`;\n });\n\n this.container.innerHTML = formattedLogs.join('');\n \n // Auto-scroll to the bottom to show the most recent logs\n this.container.scrollTop = this.container.scrollHeight;\n }\n\n private escapeHtml(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n }\n\n private setupKeyboardListeners(): void {\n document.addEventListener('keydown', (event) => {\n this.handleKeyDown(event);\n });\n }\n\n private handleKeyDown(event: KeyboardEvent): void {\n // Handle focus key combination\n if (this.config.focusKey) {\n this.keyBuffer += event.key;\n \n // Clear buffer after 2 seconds of inactivity\n if (this.keyBufferTimeout) {\n clearTimeout(this.keyBufferTimeout);\n }\n this.keyBufferTimeout = window.setTimeout(() => {\n this.keyBuffer = '';\n }, 2000);\n\n // Check if key combination matches\n if (this.keyBuffer.includes(this.config.focusKey)) {\n this.focus();\n this.keyBuffer = '';\n event.preventDefault();\n return;\n }\n }\n\n // Handle unfocus key\n if (this.config.unfocusKey && event.key === this.config.unfocusKey && this._isFocused) {\n this.unfocus();\n event.preventDefault();\n return;\n }\n\n // Handle keyboard navigation when focused\n if (this._isFocused && this.config.enableKeyboardNav && this.container) {\n switch (event.key) {\n case 'ArrowUp':\n this.container.scrollTop -= 20;\n event.preventDefault();\n break;\n case 'ArrowDown':\n this.container.scrollTop += 20;\n event.preventDefault();\n break;\n case 'PageUp':\n this.container.scrollTop -= this.container.clientHeight;\n event.preventDefault();\n break;\n case 'PageDown':\n this.container.scrollTop += this.container.clientHeight;\n event.preventDefault();\n break;\n case 'Home':\n this.container.scrollTop = 0;\n event.preventDefault();\n break;\n case 'End':\n this.container.scrollTop = this.container.scrollHeight;\n event.preventDefault();\n break;\n }\n }\n }\n\n // Public API methods\n log(...args: any[]): void {\n this.addLog('log', ...args);\n }\n\n info(...args: any[]): void {\n this.addLog('info', ...args);\n }\n\n warn(...args: any[]): void {\n this.addLog('warn', ...args);\n }\n\n error(...args: any[]): void {\n this.addLog('error', ...args);\n }\n\n debug(...args: any[]): void {\n this.addLog('debug', ...args);\n }\n\n clear(): void {\n this.logs = [];\n this.render();\n }\n\n show(): void {\n if (this.container) {\n this.container.style.display = 'block';\n this.isVisible = true;\n }\n }\n\n hide(): void {\n if (this.container) {\n this.container.style.display = 'none';\n this.isVisible = false;\n }\n }\n\n toggle(): void {\n if (this.isVisible) {\n this.hide();\n } else {\n this.show();\n }\n }\n\n focus(): void {\n if (!this.container || this._isFocused) return;\n \n this._isFocused = true;\n this.container.focus();\n \n if (this.config.showFocusIndicator) {\n this.container.style.border = '2px solid #00ff00';\n this.container.style.boxShadow = '0 0 10px rgba(0, 255, 0, 0.5)';\n }\n \n // Call onFocus callback if provided\n if (this.config.onFocus) {\n this.config.onFocus();\n }\n \n console.log('TV Console focused - Use arrow keys to scroll, Escape to unfocus');\n }\n\n unfocus(): void {\n if (!this.container || !this._isFocused) return;\n \n this._isFocused = false;\n this.container.blur();\n \n if (this.config.showFocusIndicator) {\n this.container.style.border = '';\n this.container.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.3)';\n }\n \n // Call onUnfocus callback if provided\n if (this.config.onUnfocus) {\n this.config.onUnfocus();\n }\n }\n\n isFocused(): boolean {\n return this._isFocused;\n }\n\n destroy(): void {\n if (this.container) {\n document.body.removeChild(this.container);\n this.container = null;\n }\n \n // Restore original console methods\n Object.assign(console, this.originalConsole);\n }\n\n getLogs(): LogEntry[] {\n return [...this.logs];\n }\n\n setConfig(config: Partial<TVConsoleConfig>): void {\n this.config = { ...this.config, ...config };\n \n if (this.container) {\n this.container.style.cssText = `\n position: fixed;\n ${this.getPositionStyles()}\n width: ${this.config.width};\n height: ${this.config.height};\n background-color: ${this.config.backgroundColor};\n color: ${this.config.textColor};\n font-family: 'Courier New', monospace;\n font-size: ${this.config.fontSize};\n padding: 10px;\n border-radius: 5px;\n overflow-y: auto;\n z-index: ${this.config.zIndex};\n opacity: ${this.config.opacity};\n display: ${this.isVisible ? 'block' : 'none'};\n word-wrap: break-word;\n white-space: pre-wrap;\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);\n outline: none;\n `;\n this.container.tabIndex = this.config.enableKeyboardNav ? 0 : -1;\n }\n \n this.render();\n }\n\n exportLogs(): string {\n return this.logs.map(log => {\n const timestamp = log.timestamp.toISOString();\n return `[${timestamp}] [${log.level.toUpperCase()}] ${log.message}`;\n }).join('\\n');\n }\n} "],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).TVConsole={})}(this,function(e){"use strict";const t={enabled:!0,maxEntries:100,position:"top-right",width:"400px",height:"300px",backgroundColor:"rgba(0, 0, 0, 0.8)",textColor:"#ffffff",fontSize:"14px",opacity:.9,showTimestamp:!0,className:"tv-console",zIndex:9999,showLogLevel:!0,logLevels:["log","info","warn","error","debug"],formatter:e=>`${`[${e.timestamp.toLocaleTimeString()}]`} ${`[${e.level.toUpperCase()}]`} ${e.message}`.trim(),focusKey:"12345",unfocusKey:"Escape",onFocus:()=>{},onUnfocus:()=>{},enableKeyboardNav:!0,showFocusIndicator:!0};class i{constructor(e={}){Object.defineProperty(this,"config",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"logs",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"container",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"isVisible",{enumerable:!0,configurable:!0,writable:!0,value:!1}),Object.defineProperty(this,"originalConsole",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_isFocused",{enumerable:!0,configurable:!0,writable:!0,value:!1}),Object.defineProperty(this,"keyBuffer",{enumerable:!0,configurable:!0,writable:!0,value:""}),Object.defineProperty(this,"keyBufferTimeout",{enumerable:!0,configurable:!0,writable:!0,value:null}),this.config={...t,...e},this.originalConsole=console,this.initialize()}initialize(){this.config.enabled&&(this.createContainer(),this.interceptConsole(),this.setupKeyboardListeners(),this.render())}createContainer(){this.container=document.createElement("div"),this.container.className=this.config.className,this.container.tabIndex=this.config.enableKeyboardNav?0:-1,this.container.style.cssText=`\n position: fixed;\n ${this.getPositionStyles()}\n width: ${this.config.width};\n height: ${this.config.height};\n background-color: ${this.config.backgroundColor};\n color: ${this.config.textColor};\n font-family: 'Courier New', monospace;\n font-size: ${this.config.fontSize};\n padding: 10px;\n border-radius: 5px;\n overflow-y: auto;\n z-index: ${this.config.zIndex};\n opacity: ${this.config.opacity};\n display: none;\n word-wrap: break-word;\n white-space: pre-wrap;\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);\n outline: none;\n `,document.body.appendChild(this.container)}getPositionStyles(){switch(this.config.position){case"top-left":return"top: 10px; left: 10px;";case"top-right":default:return"top: 10px; right: 10px;";case"bottom-left":return"bottom: 10px; left: 10px;";case"bottom-right":return"bottom: 10px; right: 10px;"}}interceptConsole(){["log","info","warn","error","debug"].forEach(e=>{const t=this.originalConsole[e];this.originalConsole[e]=(...i)=>{t.apply(this.originalConsole,i),this.addLog(e,...i)}})}addLog(e,...t){if(!this.config.enabled||!this.config.logLevels.includes(e))return;const i=t.map(e=>this.formatArgument(e)).join(" "),o={id:Date.now().toString()+Math.random().toString(36).substr(2,9),level:e,message:i,timestamp:new Date,data:t,stack:"error"===e?(new Error).stack:void 0};this.logs.push(o),this.logs.length>this.config.maxEntries&&(this.logs=this.logs.slice(-this.config.maxEntries)),this.render()}formatArgument(e){if(null===e)return"null";if(void 0===e)return"undefined";if(e instanceof Error)return`Error: ${e.message}\nStack: ${e.stack||"No stack trace available"}`;if("object"==typeof e)try{return JSON.stringify(e,null,2)}catch{if(e.toString&&e.toString!==Object.prototype.toString)return e.toString();const t=Object.keys(e);return t.length>0?`[Object with keys: ${t.join(", ")}]`:"[Empty Object]"}return"function"==typeof e?`[Function: ${e.name||"anonymous"}]`:String(e)}render(){if(!this.container)return;const e=this.logs.filter(e=>this.config.logLevels.includes(e.level)).map(e=>{const t=this.config.formatter(e);return`<div class="${`tv-console-${e.level}`}">${this.escapeHtml(t)}</div>`});this.container.innerHTML=e.join(""),this.container.scrollTop=this.container.scrollHeight}escapeHtml(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}setupKeyboardListeners(){document.addEventListener("keydown",e=>{this.handleKeyDown(e)})}handleKeyDown(e){if(this.config.focusKey&&(this.keyBuffer+=e.key,this.keyBufferTimeout&&clearTimeout(this.keyBufferTimeout),this.keyBufferTimeout=window.setTimeout(()=>{this.keyBuffer=""},2e3),this.keyBuffer.includes(this.config.focusKey)))return this.focus(),this.keyBuffer="",void e.preventDefault();if(this.config.unfocusKey&&e.key===this.config.unfocusKey&&this._isFocused)return this.unfocus(),void e.preventDefault();if(this._isFocused&&this.config.enableKeyboardNav&&this.container)switch(e.key){case"ArrowUp":this.container.scrollTop-=20,e.preventDefault();break;case"ArrowDown":this.container.scrollTop+=20,e.preventDefault();break;case"PageUp":this.container.scrollTop-=this.container.clientHeight,e.preventDefault();break;case"PageDown":this.container.scrollTop+=this.container.clientHeight,e.preventDefault();break;case"Home":this.container.scrollTop=0,e.preventDefault();break;case"End":this.container.scrollTop=this.container.scrollHeight,e.preventDefault()}}log(...e){this.addLog("log",...e)}info(...e){this.addLog("info",...e)}warn(...e){this.addLog("warn",...e)}error(...e){this.addLog("error",...e)}debug(...e){this.addLog("debug",...e)}clear(){this.logs=[],this.render()}show(){this.container&&(this.container.style.display="block",this.isVisible=!0)}hide(){this.container&&(this.container.style.display="none",this.isVisible=!1)}toggle(){this.isVisible?this.hide():this.show()}focus(){this.container&&!this._isFocused&&(this._isFocused=!0,this.container.focus(),this.config.showFocusIndicator&&(this.container.style.border="2px solid #00ff00",this.container.style.boxShadow="0 0 10px rgba(0, 255, 0, 0.5)"),this.config.onFocus&&this.config.onFocus(),console.log("TV Console focused - Use arrow keys to scroll, Escape to unfocus"))}unfocus(){this.container&&this._isFocused&&(this._isFocused=!1,this.container.blur(),this.config.showFocusIndicator&&(this.container.style.border="",this.container.style.boxShadow="0 2px 10px rgba(0, 0, 0, 0.3)"),this.config.onUnfocus&&this.config.onUnfocus())}isFocused(){return this._isFocused}destroy(){this.container&&(document.body.removeChild(this.container),this.container=null),Object.assign(console,this.originalConsole)}getLogs(){return[...this.logs]}setConfig(e){this.config={...this.config,...e},this.container&&(this.container.style.cssText=`\n position: fixed;\n ${this.getPositionStyles()}\n width: ${this.config.width};\n height: ${this.config.height};\n background-color: ${this.config.backgroundColor};\n color: ${this.config.textColor};\n font-family: 'Courier New', monospace;\n font-size: ${this.config.fontSize};\n padding: 10px;\n border-radius: 5px;\n overflow-y: auto;\n z-index: ${this.config.zIndex};\n opacity: ${this.config.opacity};\n display: ${this.isVisible?"block":"none"};\n word-wrap: break-word;\n white-space: pre-wrap;\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);\n outline: none;\n `,this.container.tabIndex=this.config.enableKeyboardNav?0:-1),this.render()}exportLogs(){return this.logs.map(e=>`[${e.timestamp.toISOString()}] [${e.level.toUpperCase()}] ${e.message}`).join("\n")}}e.TVConsole=i,e.default=i,Object.defineProperty(e,"__esModule",{value:!0})});
|
|
2
|
+
//# sourceMappingURL=index.umd.min.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.umd.min.js","sources":["../src/tv-console.ts"],"sourcesContent":["import type { TVConsoleConfig, LogLevel, LogEntry, TVConsoleInstance } from './types';\n\nconst DEFAULT_CONFIG: Required<TVConsoleConfig> = {\n enabled: true,\n maxEntries: 100,\n position: 'top-right',\n width: '400px',\n height: '300px',\n backgroundColor: 'rgba(0, 0, 0, 0.8)',\n textColor: '#ffffff',\n fontSize: '14px',\n opacity: 0.9,\n showTimestamp: true,\n className: 'tv-console',\n zIndex: 9999,\n showLogLevel: true,\n logLevels: ['log', 'info', 'warn', 'error', 'debug'],\n formatter: (entry: LogEntry) => {\n const timestamp = entry.timestamp.toLocaleTimeString();\n const level = DEFAULT_CONFIG.showLogLevel ? `[${entry.level.toUpperCase()}]` : '';\n const prefix = DEFAULT_CONFIG.showTimestamp ? `[${timestamp}]` : '';\n return `${prefix} ${level} ${entry.message}`.trim();\n },\n focusKey: '12345',\n unfocusKey: 'Escape',\n onFocus: () => {},\n onUnfocus: () => {},\n enableKeyboardNav: true,\n showFocusIndicator: true\n};\n\nexport class TVConsole implements TVConsoleInstance {\n private config: Required<TVConsoleConfig>;\n private logs: LogEntry[] = [];\n private container: HTMLDivElement | null = null;\n private isVisible = false;\n private originalConsole: Console;\n private _isFocused = false;\n private keyBuffer = '';\n private keyBufferTimeout: number | null = null;\n\n constructor(config: TVConsoleConfig = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.originalConsole = console;\n this.initialize();\n }\n\n private initialize(): void {\n if (!this.config.enabled) return;\n\n this.createContainer();\n this.interceptConsole();\n this.setupKeyboardListeners();\n this.render();\n }\n\n private createContainer(): void {\n this.container = document.createElement('div');\n this.container.className = this.config.className;\n this.container.tabIndex = this.config.enableKeyboardNav ? 0 : -1;\n this.container.style.cssText = `\n position: fixed;\n ${this.getPositionStyles()}\n width: ${this.config.width};\n height: ${this.config.height};\n background-color: ${this.config.backgroundColor};\n color: ${this.config.textColor};\n font-family: 'Courier New', monospace;\n font-size: ${this.config.fontSize};\n padding: 10px;\n border-radius: 5px;\n overflow-y: auto;\n z-index: ${this.config.zIndex};\n opacity: ${this.config.opacity};\n display: none;\n word-wrap: break-word;\n white-space: pre-wrap;\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);\n outline: none;\n `;\n\n document.body.appendChild(this.container);\n }\n\n private getPositionStyles(): string {\n switch (this.config.position) {\n case 'top-left':\n return 'top: 10px; left: 10px;';\n case 'top-right':\n return 'top: 10px; right: 10px;';\n case 'bottom-left':\n return 'bottom: 10px; left: 10px;';\n case 'bottom-right':\n return 'bottom: 10px; right: 10px;';\n default:\n return 'top: 10px; right: 10px;';\n }\n }\n\n private interceptConsole(): void {\n const methods: LogLevel[] = ['log', 'info', 'warn', 'error', 'debug'];\n \n methods.forEach(method => {\n const original = this.originalConsole[method];\n this.originalConsole[method] = (...args: any[]) => {\n // Call original console method\n original.apply(this.originalConsole, args);\n \n // Add to TV console\n this.addLog(method, ...args);\n };\n });\n }\n\n private addLog(level: LogLevel, ...args: any[]): void {\n if (!this.config.enabled || !this.config.logLevels.includes(level)) {\n return;\n }\n\n const message = args.map(arg => this.formatArgument(arg)).join(' ');\n const entry: LogEntry = {\n id: Date.now().toString() + Math.random().toString(36).substr(2, 9),\n level,\n message,\n timestamp: new Date(),\n data: args,\n stack: level === 'error' ? new Error().stack : undefined\n };\n\n this.logs.push(entry);\n\n // Keep only the latest entries\n if (this.logs.length > this.config.maxEntries) {\n this.logs = this.logs.slice(-this.config.maxEntries);\n }\n\n this.render();\n }\n\n private formatArgument(arg: any): string {\n if (arg === null) return 'null';\n if (arg === undefined) return 'undefined';\n \n // Handle Error objects specifically\n if (arg instanceof Error) {\n return `Error: ${arg.message}\\nStack: ${arg.stack || 'No stack trace available'}`;\n }\n \n // Handle other objects\n if (typeof arg === 'object') {\n try {\n // Try JSON.stringify first\n return JSON.stringify(arg, null, 2);\n } catch {\n // If JSON.stringify fails, try to get a meaningful string representation\n if (arg.toString && arg.toString !== Object.prototype.toString) {\n return arg.toString();\n }\n \n // For objects that don't have a custom toString, show their keys\n const keys = Object.keys(arg);\n if (keys.length > 0) {\n return `[Object with keys: ${keys.join(', ')}]`;\n } else {\n return '[Empty Object]';\n }\n }\n }\n \n // Handle functions\n if (typeof arg === 'function') {\n return `[Function: ${arg.name || 'anonymous'}]`;\n }\n \n // Handle other primitive types\n return String(arg);\n }\n\n private render(): void {\n if (!this.container) return;\n\n const filteredLogs = this.logs.filter(log => \n this.config.logLevels.includes(log.level)\n );\n\n const formattedLogs = filteredLogs.map(log => {\n const formatted = this.config.formatter(log);\n const levelClass = `tv-console-${log.level}`;\n return `<div class=\"${levelClass}\">${this.escapeHtml(formatted)}</div>`;\n });\n\n this.container.innerHTML = formattedLogs.join('');\n \n // Auto-scroll to the bottom to show the most recent logs\n this.container.scrollTop = this.container.scrollHeight;\n }\n\n private escapeHtml(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n }\n\n private setupKeyboardListeners(): void {\n document.addEventListener('keydown', (event) => {\n this.handleKeyDown(event);\n });\n }\n\n private handleKeyDown(event: KeyboardEvent): void {\n // Handle focus key combination\n if (this.config.focusKey) {\n this.keyBuffer += event.key;\n \n // Clear buffer after 2 seconds of inactivity\n if (this.keyBufferTimeout) {\n clearTimeout(this.keyBufferTimeout);\n }\n this.keyBufferTimeout = window.setTimeout(() => {\n this.keyBuffer = '';\n }, 2000);\n\n // Check if key combination matches\n if (this.keyBuffer.includes(this.config.focusKey)) {\n this.focus();\n this.keyBuffer = '';\n event.preventDefault();\n return;\n }\n }\n\n // Handle unfocus key\n if (this.config.unfocusKey && event.key === this.config.unfocusKey && this._isFocused) {\n this.unfocus();\n event.preventDefault();\n return;\n }\n\n // Handle keyboard navigation when focused\n if (this._isFocused && this.config.enableKeyboardNav && this.container) {\n switch (event.key) {\n case 'ArrowUp':\n this.container.scrollTop -= 20;\n event.preventDefault();\n break;\n case 'ArrowDown':\n this.container.scrollTop += 20;\n event.preventDefault();\n break;\n case 'PageUp':\n this.container.scrollTop -= this.container.clientHeight;\n event.preventDefault();\n break;\n case 'PageDown':\n this.container.scrollTop += this.container.clientHeight;\n event.preventDefault();\n break;\n case 'Home':\n this.container.scrollTop = 0;\n event.preventDefault();\n break;\n case 'End':\n this.container.scrollTop = this.container.scrollHeight;\n event.preventDefault();\n break;\n }\n }\n }\n\n // Public API methods\n log(...args: any[]): void {\n this.addLog('log', ...args);\n }\n\n info(...args: any[]): void {\n this.addLog('info', ...args);\n }\n\n warn(...args: any[]): void {\n this.addLog('warn', ...args);\n }\n\n error(...args: any[]): void {\n this.addLog('error', ...args);\n }\n\n debug(...args: any[]): void {\n this.addLog('debug', ...args);\n }\n\n clear(): void {\n this.logs = [];\n this.render();\n }\n\n show(): void {\n if (this.container) {\n this.container.style.display = 'block';\n this.isVisible = true;\n }\n }\n\n hide(): void {\n if (this.container) {\n this.container.style.display = 'none';\n this.isVisible = false;\n }\n }\n\n toggle(): void {\n if (this.isVisible) {\n this.hide();\n } else {\n this.show();\n }\n }\n\n focus(): void {\n if (!this.container || this._isFocused) return;\n \n this._isFocused = true;\n this.container.focus();\n \n if (this.config.showFocusIndicator) {\n this.container.style.border = '2px solid #00ff00';\n this.container.style.boxShadow = '0 0 10px rgba(0, 255, 0, 0.5)';\n }\n \n // Call onFocus callback if provided\n if (this.config.onFocus) {\n this.config.onFocus();\n }\n \n console.log('TV Console focused - Use arrow keys to scroll, Escape to unfocus');\n }\n\n unfocus(): void {\n if (!this.container || !this._isFocused) return;\n \n this._isFocused = false;\n this.container.blur();\n \n if (this.config.showFocusIndicator) {\n this.container.style.border = '';\n this.container.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.3)';\n }\n \n // Call onUnfocus callback if provided\n if (this.config.onUnfocus) {\n this.config.onUnfocus();\n }\n }\n\n isFocused(): boolean {\n return this._isFocused;\n }\n\n destroy(): void {\n if (this.container) {\n document.body.removeChild(this.container);\n this.container = null;\n }\n \n // Restore original console methods\n Object.assign(console, this.originalConsole);\n }\n\n getLogs(): LogEntry[] {\n return [...this.logs];\n }\n\n setConfig(config: Partial<TVConsoleConfig>): void {\n this.config = { ...this.config, ...config };\n \n if (this.container) {\n this.container.style.cssText = `\n position: fixed;\n ${this.getPositionStyles()}\n width: ${this.config.width};\n height: ${this.config.height};\n background-color: ${this.config.backgroundColor};\n color: ${this.config.textColor};\n font-family: 'Courier New', monospace;\n font-size: ${this.config.fontSize};\n padding: 10px;\n border-radius: 5px;\n overflow-y: auto;\n z-index: ${this.config.zIndex};\n opacity: ${this.config.opacity};\n display: ${this.isVisible ? 'block' : 'none'};\n word-wrap: break-word;\n white-space: pre-wrap;\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);\n outline: none;\n `;\n this.container.tabIndex = this.config.enableKeyboardNav ? 0 : -1;\n }\n \n this.render();\n }\n\n exportLogs(): string {\n return this.logs.map(log => {\n const timestamp = log.timestamp.toISOString();\n return `[${timestamp}] [${log.level.toUpperCase()}] ${log.message}`;\n }).join('\\n');\n }\n} "],"names":["DEFAULT_CONFIG","enabled","maxEntries","position","width","height","backgroundColor","textColor","fontSize","opacity","showTimestamp","className","zIndex","showLogLevel","logLevels","formatter","entry","timestamp","toLocaleTimeString","level","toUpperCase","message","trim","focusKey","unfocusKey","onFocus","onUnfocus","enableKeyboardNav","showFocusIndicator","TVConsole","constructor","config","Object","defineProperty","this","originalConsole","console","initialize","createContainer","interceptConsole","setupKeyboardListeners","render","container","document","createElement","tabIndex","style","cssText","getPositionStyles","body","appendChild","forEach","method","original","args","apply","addLog","includes","map","arg","formatArgument","join","id","Date","now","toString","Math","random","substr","data","stack","Error","undefined","logs","push","length","slice","JSON","stringify","prototype","keys","name","String","formattedLogs","filter","log","formatted","escapeHtml","innerHTML","scrollTop","scrollHeight","text","div","textContent","addEventListener","event","handleKeyDown","keyBuffer","key","keyBufferTimeout","clearTimeout","window","setTimeout","focus","preventDefault","_isFocused","unfocus","clientHeight","info","warn","error","debug","clear","show","display","isVisible","hide","toggle","border","boxShadow","blur","isFocused","destroy","removeChild","assign","getLogs","setConfig","exportLogs","toISOString"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tv-console",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "A console replacement for TV apps where browser console is not accessible",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
+
"unpkg": "dist/index.umd.min.js",
|
|
9
|
+
"jsdelivr": "dist/index.umd.min.js",
|
|
8
10
|
"exports": {
|
|
9
11
|
".": {
|
|
10
12
|
"import": "./dist/index.esm.js",
|
|
@@ -33,7 +35,7 @@
|
|
|
33
35
|
"logging",
|
|
34
36
|
"typescript"
|
|
35
37
|
],
|
|
36
|
-
"author": "
|
|
38
|
+
"author": "Andrew Hardy",
|
|
37
39
|
"license": "MIT",
|
|
38
40
|
"devDependencies": {
|
|
39
41
|
"@rollup/plugin-commonjs": "^25.0.0",
|
|
@@ -54,12 +56,12 @@
|
|
|
54
56
|
},
|
|
55
57
|
"repository": {
|
|
56
58
|
"type": "git",
|
|
57
|
-
"url": "https://github.com/
|
|
59
|
+
"url": "https://github.com/ahardy42/tv-console.git"
|
|
58
60
|
},
|
|
59
61
|
"bugs": {
|
|
60
|
-
"url": "https://github.com/
|
|
62
|
+
"url": "https://github.com/ahardy42/tv-console/issues"
|
|
61
63
|
},
|
|
62
|
-
"homepage": "https://github.com/
|
|
64
|
+
"homepage": "https://github.com/ahardy42/tv-console#readme",
|
|
63
65
|
"dependencies": {
|
|
64
66
|
"tslib": "^2.8.1"
|
|
65
67
|
}
|