@design.estate/dees-catalog 3.35.1 → 3.37.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.
Files changed (29) hide show
  1. package/dist_bundle/bundle.js +1391 -247
  2. package/dist_ts_web/00_commitinfo_data.js +1 -1
  3. package/dist_ts_web/elements/00group-button/dees-button/dees-button.d.ts +6 -0
  4. package/dist_ts_web/elements/00group-button/dees-button/dees-button.demo.js +69 -29
  5. package/dist_ts_web/elements/00group-button/dees-button/dees-button.js +75 -6
  6. package/dist_ts_web/elements/00group-chart/dees-chart-log/dees-chart-log.d.ts +104 -6
  7. package/dist_ts_web/elements/00group-chart/dees-chart-log/dees-chart-log.demo.js +153 -54
  8. package/dist_ts_web/elements/00group-chart/dees-chart-log/dees-chart-log.js +716 -153
  9. package/dist_ts_web/elements/dees-statsgrid/dees-statsgrid.d.ts +22 -1
  10. package/dist_ts_web/elements/dees-statsgrid/dees-statsgrid.demo.js +130 -2
  11. package/dist_ts_web/elements/dees-statsgrid/dees-statsgrid.js +322 -1
  12. package/dist_ts_web/services/DeesServiceLibLoader.d.ts +34 -1
  13. package/dist_ts_web/services/DeesServiceLibLoader.js +27 -1
  14. package/dist_ts_web/services/index.d.ts +1 -1
  15. package/dist_ts_web/services/versions.d.ts +1 -0
  16. package/dist_ts_web/services/versions.js +2 -1
  17. package/dist_watch/bundle.js +1389 -245
  18. package/dist_watch/bundle.js.map +3 -3
  19. package/package.json +1 -1
  20. package/ts_web/00_commitinfo_data.ts +1 -1
  21. package/ts_web/elements/00group-button/dees-button/dees-button.demo.ts +68 -28
  22. package/ts_web/elements/00group-button/dees-button/dees-button.ts +78 -6
  23. package/ts_web/elements/00group-chart/dees-chart-log/dees-chart-log.demo.ts +163 -56
  24. package/ts_web/elements/00group-chart/dees-chart-log/dees-chart-log.ts +756 -161
  25. package/ts_web/elements/dees-statsgrid/dees-statsgrid.demo.ts +130 -2
  26. package/ts_web/elements/dees-statsgrid/dees-statsgrid.ts +352 -1
  27. package/ts_web/services/DeesServiceLibLoader.ts +50 -1
  28. package/ts_web/services/index.ts +1 -1
  29. package/ts_web/services/versions.ts +1 -0
@@ -32,10 +32,11 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
32
32
  }
33
33
  return useValue ? value : void 0;
34
34
  };
35
- import { DeesElement, css, cssManager, customElement, html, property, } from '@design.estate/dees-element';
35
+ import { DeesElement, css, cssManager, customElement, html, property, state, } from '@design.estate/dees-element';
36
36
  import * as domtools from '@design.estate/dees-domtools';
37
37
  import { demoFunc } from './dees-chart-log.demo.js';
38
38
  import { themeDefaultStyles } from '../../00theme.js';
39
+ import { DeesServiceLibLoader, CDN_BASE, CDN_VERSIONS } from '../../../services/index.js';
39
40
  let DeesChartLog = (() => {
40
41
  let _classDecorators = [customElement('dees-chart-log')];
41
42
  let _classDescriptor;
@@ -45,6 +46,9 @@ let DeesChartLog = (() => {
45
46
  let _label_decorators;
46
47
  let _label_initializers = [];
47
48
  let _label_extraInitializers = [];
49
+ let _mode_decorators;
50
+ let _mode_initializers = [];
51
+ let _mode_extraInitializers = [];
48
52
  let _logEntries_decorators;
49
53
  let _logEntries_initializers = [];
50
54
  let _logEntries_extraInitializers = [];
@@ -54,18 +58,50 @@ let DeesChartLog = (() => {
54
58
  let _maxEntries_decorators;
55
59
  let _maxEntries_initializers = [];
56
60
  let _maxEntries_extraInitializers = [];
61
+ let _highlightKeywords_decorators;
62
+ let _highlightKeywords_initializers = [];
63
+ let _highlightKeywords_extraInitializers = [];
64
+ let _showMetrics_decorators;
65
+ let _showMetrics_initializers = [];
66
+ let _showMetrics_extraInitializers = [];
67
+ let _searchQuery_decorators;
68
+ let _searchQuery_initializers = [];
69
+ let _searchQuery_extraInitializers = [];
70
+ let _filterMode_decorators;
71
+ let _filterMode_initializers = [];
72
+ let _filterMode_extraInitializers = [];
73
+ let _metrics_decorators;
74
+ let _metrics_initializers = [];
75
+ let _metrics_extraInitializers = [];
76
+ let _terminalReady_decorators;
77
+ let _terminalReady_initializers = [];
78
+ let _terminalReady_extraInitializers = [];
57
79
  var DeesChartLog = class extends _classSuper {
58
80
  static { _classThis = this; }
59
81
  static {
60
82
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
61
83
  _label_decorators = [property()];
84
+ _mode_decorators = [property({ type: String })];
62
85
  _logEntries_decorators = [property({ type: Array })];
63
86
  _autoScroll_decorators = [property({ type: Boolean })];
64
87
  _maxEntries_decorators = [property({ type: Number })];
88
+ _highlightKeywords_decorators = [property({ type: Array })];
89
+ _showMetrics_decorators = [property({ type: Boolean })];
90
+ _searchQuery_decorators = [state()];
91
+ _filterMode_decorators = [state()];
92
+ _metrics_decorators = [state()];
93
+ _terminalReady_decorators = [state()];
65
94
  __esDecorate(this, null, _label_decorators, { kind: "accessor", name: "label", static: false, private: false, access: { has: obj => "label" in obj, get: obj => obj.label, set: (obj, value) => { obj.label = value; } }, metadata: _metadata }, _label_initializers, _label_extraInitializers);
95
+ __esDecorate(this, null, _mode_decorators, { kind: "accessor", name: "mode", static: false, private: false, access: { has: obj => "mode" in obj, get: obj => obj.mode, set: (obj, value) => { obj.mode = value; } }, metadata: _metadata }, _mode_initializers, _mode_extraInitializers);
66
96
  __esDecorate(this, null, _logEntries_decorators, { kind: "accessor", name: "logEntries", static: false, private: false, access: { has: obj => "logEntries" in obj, get: obj => obj.logEntries, set: (obj, value) => { obj.logEntries = value; } }, metadata: _metadata }, _logEntries_initializers, _logEntries_extraInitializers);
67
97
  __esDecorate(this, null, _autoScroll_decorators, { kind: "accessor", name: "autoScroll", static: false, private: false, access: { has: obj => "autoScroll" in obj, get: obj => obj.autoScroll, set: (obj, value) => { obj.autoScroll = value; } }, metadata: _metadata }, _autoScroll_initializers, _autoScroll_extraInitializers);
68
98
  __esDecorate(this, null, _maxEntries_decorators, { kind: "accessor", name: "maxEntries", static: false, private: false, access: { has: obj => "maxEntries" in obj, get: obj => obj.maxEntries, set: (obj, value) => { obj.maxEntries = value; } }, metadata: _metadata }, _maxEntries_initializers, _maxEntries_extraInitializers);
99
+ __esDecorate(this, null, _highlightKeywords_decorators, { kind: "accessor", name: "highlightKeywords", static: false, private: false, access: { has: obj => "highlightKeywords" in obj, get: obj => obj.highlightKeywords, set: (obj, value) => { obj.highlightKeywords = value; } }, metadata: _metadata }, _highlightKeywords_initializers, _highlightKeywords_extraInitializers);
100
+ __esDecorate(this, null, _showMetrics_decorators, { kind: "accessor", name: "showMetrics", static: false, private: false, access: { has: obj => "showMetrics" in obj, get: obj => obj.showMetrics, set: (obj, value) => { obj.showMetrics = value; } }, metadata: _metadata }, _showMetrics_initializers, _showMetrics_extraInitializers);
101
+ __esDecorate(this, null, _searchQuery_decorators, { kind: "accessor", name: "searchQuery", static: false, private: false, access: { has: obj => "searchQuery" in obj, get: obj => obj.searchQuery, set: (obj, value) => { obj.searchQuery = value; } }, metadata: _metadata }, _searchQuery_initializers, _searchQuery_extraInitializers);
102
+ __esDecorate(this, null, _filterMode_decorators, { kind: "accessor", name: "filterMode", static: false, private: false, access: { has: obj => "filterMode" in obj, get: obj => obj.filterMode, set: (obj, value) => { obj.filterMode = value; } }, metadata: _metadata }, _filterMode_initializers, _filterMode_extraInitializers);
103
+ __esDecorate(this, null, _metrics_decorators, { kind: "accessor", name: "metrics", static: false, private: false, access: { has: obj => "metrics" in obj, get: obj => obj.metrics, set: (obj, value) => { obj.metrics = value; } }, metadata: _metadata }, _metrics_initializers, _metrics_extraInitializers);
104
+ __esDecorate(this, null, _terminalReady_decorators, { kind: "accessor", name: "terminalReady", static: false, private: false, access: { has: obj => "terminalReady" in obj, get: obj => obj.terminalReady, set: (obj, value) => { obj.terminalReady = value; } }, metadata: _metadata }, _terminalReady_initializers, _terminalReady_extraInitializers);
69
105
  __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
70
106
  DeesChartLog = _classThis = _classDescriptor.value;
71
107
  if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
@@ -75,31 +111,60 @@ let DeesChartLog = (() => {
75
111
  #label_accessor_storage = __runInitializers(this, _label_initializers, 'Server Logs');
76
112
  get label() { return this.#label_accessor_storage; }
77
113
  set label(value) { this.#label_accessor_storage = value; }
78
- #logEntries_accessor_storage = (__runInitializers(this, _label_extraInitializers), __runInitializers(this, _logEntries_initializers, []));
114
+ #mode_accessor_storage = (__runInitializers(this, _label_extraInitializers), __runInitializers(this, _mode_initializers, 'structured'));
115
+ get mode() { return this.#mode_accessor_storage; }
116
+ set mode(value) { this.#mode_accessor_storage = value; }
117
+ #logEntries_accessor_storage = (__runInitializers(this, _mode_extraInitializers), __runInitializers(this, _logEntries_initializers, []));
79
118
  get logEntries() { return this.#logEntries_accessor_storage; }
80
119
  set logEntries(value) { this.#logEntries_accessor_storage = value; }
81
120
  #autoScroll_accessor_storage = (__runInitializers(this, _logEntries_extraInitializers), __runInitializers(this, _autoScroll_initializers, true));
82
121
  get autoScroll() { return this.#autoScroll_accessor_storage; }
83
122
  set autoScroll(value) { this.#autoScroll_accessor_storage = value; }
84
- #maxEntries_accessor_storage = (__runInitializers(this, _autoScroll_extraInitializers), __runInitializers(this, _maxEntries_initializers, 1000));
123
+ #maxEntries_accessor_storage = (__runInitializers(this, _autoScroll_extraInitializers), __runInitializers(this, _maxEntries_initializers, 10000));
85
124
  get maxEntries() { return this.#maxEntries_accessor_storage; }
86
125
  set maxEntries(value) { this.#maxEntries_accessor_storage = value; }
87
- logContainer = __runInitializers(this, _maxEntries_extraInitializers);
88
- constructor() {
89
- super();
90
- domtools.elementBasic.setup();
91
- }
126
+ #highlightKeywords_accessor_storage = (__runInitializers(this, _maxEntries_extraInitializers), __runInitializers(this, _highlightKeywords_initializers, []));
127
+ get highlightKeywords() { return this.#highlightKeywords_accessor_storage; }
128
+ set highlightKeywords(value) { this.#highlightKeywords_accessor_storage = value; }
129
+ #showMetrics_accessor_storage = (__runInitializers(this, _highlightKeywords_extraInitializers), __runInitializers(this, _showMetrics_initializers, true));
130
+ get showMetrics() { return this.#showMetrics_accessor_storage; }
131
+ set showMetrics(value) { this.#showMetrics_accessor_storage = value; }
132
+ #searchQuery_accessor_storage = (__runInitializers(this, _showMetrics_extraInitializers), __runInitializers(this, _searchQuery_initializers, ''));
133
+ get searchQuery() { return this.#searchQuery_accessor_storage; }
134
+ set searchQuery(value) { this.#searchQuery_accessor_storage = value; }
135
+ #filterMode_accessor_storage = (__runInitializers(this, _searchQuery_extraInitializers), __runInitializers(this, _filterMode_initializers, false));
136
+ get filterMode() { return this.#filterMode_accessor_storage; }
137
+ set filterMode(value) { this.#filterMode_accessor_storage = value; }
138
+ #metrics_accessor_storage = (__runInitializers(this, _filterMode_extraInitializers), __runInitializers(this, _metrics_initializers, { debug: 0, info: 0, warn: 0, error: 0, success: 0, total: 0, rate: 0 }));
139
+ get metrics() { return this.#metrics_accessor_storage; }
140
+ set metrics(value) { this.#metrics_accessor_storage = value; }
141
+ #terminalReady_accessor_storage = (__runInitializers(this, _metrics_extraInitializers), __runInitializers(this, _terminalReady_initializers, false));
142
+ get terminalReady() { return this.#terminalReady_accessor_storage; }
143
+ set terminalReady(value) { this.#terminalReady_accessor_storage = value; }
144
+ // Buffer of all log entries for filter mode
145
+ logBuffer = (__runInitializers(this, _terminalReady_extraInitializers), []);
146
+ // Track trailing hidden entries count for live updates in filter mode
147
+ trailingHiddenCount = 0;
148
+ // xterm instances
149
+ terminal = null;
150
+ fitAddon = null;
151
+ searchAddon = null;
152
+ resizeObserver = null;
153
+ terminalThemeSubscription = null;
154
+ domtoolsInstance = null;
155
+ // Rate calculation
156
+ rateBuffer = [];
157
+ rateInterval = null;
92
158
  static styles = [
93
159
  themeDefaultStyles,
94
160
  cssManager.defaultStyles,
95
161
  css `
96
- /* TODO: Migrate hardcoded values to --dees-* CSS variables */
97
162
  :host {
98
- font-family: 'SF Mono', 'Monaco', 'Consolas', 'Liberation Mono', 'Courier New', monospace;
163
+ display: block;
164
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
99
165
  color: ${cssManager.bdTheme('hsl(0 0% 3.9%)', 'hsl(0 0% 98%)')};
100
- font-size: 12px;
101
- line-height: 1.5;
102
166
  }
167
+
103
168
  .mainbox {
104
169
  position: relative;
105
170
  width: 100%;
@@ -114,242 +179,740 @@ let DeesChartLog = (() => {
114
179
 
115
180
  .header {
116
181
  background: ${cssManager.bdTheme('hsl(0 0% 97%)', 'hsl(0 0% 7%)')};
117
- padding: 12px 16px;
182
+ padding: 8px 12px;
118
183
  border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
119
184
  display: flex;
120
- justify-content: space-between;
121
185
  align-items: center;
186
+ gap: 12px;
122
187
  flex-shrink: 0;
188
+ flex-wrap: wrap;
123
189
  }
124
190
 
125
191
  .title {
126
192
  font-weight: 500;
127
193
  font-size: 14px;
128
194
  color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 95%)')};
129
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
195
+ white-space: nowrap;
130
196
  }
131
197
 
132
- .controls {
198
+ .search-box {
133
199
  display: flex;
134
- gap: 8px;
200
+ align-items: center;
201
+ gap: 4px;
202
+ flex: 1;
203
+ min-width: 150px;
204
+ max-width: 300px;
135
205
  }
136
206
 
137
- .control-button {
138
- background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 14.9%)')};
139
- border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
140
- border-radius: 6px;
141
- padding: 6px 12px;
142
- color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
143
- cursor: pointer;
207
+ .search-box input {
208
+ flex: 1;
209
+ padding: 4px 8px;
144
210
  font-size: 12px;
145
- font-weight: 500;
146
- transition: all 0.15s;
147
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
148
- }
149
-
150
- .control-button:hover {
151
- background: ${cssManager.bdTheme('hsl(0 0% 95.1%)', 'hsl(0 0% 14.9%)')};
152
- border-color: ${cssManager.bdTheme('hsl(0 0% 79.8%)', 'hsl(0 0% 20.9%)')};
153
- color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 93.9%)')};
211
+ border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
212
+ border-radius: 4px;
213
+ background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 9%)')};
214
+ color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 95%)')};
215
+ outline: none;
154
216
  }
155
217
 
156
- .control-button.active {
157
- background: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 93.9%)')};
158
- color: ${cssManager.bdTheme('hsl(0 0% 98%)', 'hsl(0 0% 3.9%)')};
218
+ .search-box input:focus {
219
+ border-color: ${cssManager.bdTheme('hsl(222.2 47.4% 51.2%)', 'hsl(217.2 91.2% 59.8%)')};
159
220
  }
160
221
 
161
- .logContainer {
162
- flex: 1;
163
- overflow-y: auto;
164
- overflow-x: hidden;
165
- padding: 16px;
166
- font-size: 12px;
222
+ .search-box input::placeholder {
223
+ color: ${cssManager.bdTheme('hsl(0 0% 63.9%)', 'hsl(0 0% 45.1%)')};
167
224
  }
168
225
 
169
- .logEntry {
170
- margin-bottom: 4px;
226
+ .search-nav {
171
227
  display: flex;
172
- white-space: pre-wrap;
173
- word-break: break-all;
174
- font-variant-numeric: tabular-nums;
228
+ gap: 2px;
175
229
  }
176
230
 
177
- .timestamp {
178
- color: ${cssManager.bdTheme('hsl(0 0% 63.9%)', 'hsl(0 0% 45.1%)')};
179
- margin-right: 12px;
180
- flex-shrink: 0;
231
+ .search-nav button {
232
+ padding: 4px 6px;
233
+ font-size: 11px;
234
+ background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 14.9%)')};
235
+ border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
236
+ border-radius: 3px;
237
+ color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
238
+ cursor: pointer;
239
+ line-height: 1;
181
240
  }
182
241
 
183
- .level {
184
- margin-right: 8px;
185
- padding: 0 6px;
186
- border-radius: 3px;
187
- font-weight: 600;
188
- text-transform: uppercase;
189
- font-size: 10px;
190
- flex-shrink: 0;
242
+ .search-nav button:hover {
243
+ background: ${cssManager.bdTheme('hsl(0 0% 95.1%)', 'hsl(0 0% 20%)')};
244
+ color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 93.9%)')};
191
245
  }
192
246
 
193
- .level.debug {
247
+ .filter-toggle {
248
+ padding: 4px 8px;
249
+ font-size: 11px;
250
+ font-weight: 500;
251
+ background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 14.9%)')};
252
+ border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
253
+ border-radius: 4px;
194
254
  color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
195
- background: ${cssManager.bdTheme('hsl(0 0% 45.1% / 0.1)', 'hsl(0 0% 63.9% / 0.1)')};
255
+ cursor: pointer;
256
+ transition: all 0.15s;
257
+ white-space: nowrap;
196
258
  }
197
259
 
198
- .level.info {
199
- color: ${cssManager.bdTheme('hsl(222.2 47.4% 51.2%)', 'hsl(217.2 91.2% 59.8%)')};
200
- background: ${cssManager.bdTheme('hsl(222.2 47.4% 51.2% / 0.1)', 'hsl(217.2 91.2% 59.8% / 0.1)')};
260
+ .filter-toggle:hover {
261
+ background: ${cssManager.bdTheme('hsl(0 0% 95.1%)', 'hsl(0 0% 20%)')};
262
+ color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 93.9%)')};
201
263
  }
202
264
 
203
- .level.warn {
204
- color: ${cssManager.bdTheme('hsl(25 95% 53%)', 'hsl(25 95% 63%)')};
205
- background: ${cssManager.bdTheme('hsl(25 95% 53% / 0.1)', 'hsl(25 95% 63% / 0.1)')};
265
+ .filter-toggle.active {
266
+ background: ${cssManager.bdTheme('hsl(45 93% 47%)', 'hsl(45 93% 47%)')};
267
+ border-color: ${cssManager.bdTheme('hsl(45 93% 47%)', 'hsl(45 93% 47%)')};
268
+ color: hsl(0 0% 9%);
206
269
  }
207
270
 
208
- .level.error {
209
- color: ${cssManager.bdTheme('hsl(0 84.2% 60.2%)', 'hsl(0 72.2% 50.6%)')};
210
- background: ${cssManager.bdTheme('hsl(0 84.2% 60.2% / 0.1)', 'hsl(0 72.2% 50.6% / 0.1)')};
271
+ .controls {
272
+ display: flex;
273
+ gap: 6px;
274
+ margin-left: auto;
211
275
  }
212
276
 
213
- .level.success {
214
- color: ${cssManager.bdTheme('hsl(142.1 76.2% 36.3%)', 'hsl(142.1 70.6% 45.3%)')};
215
- background: ${cssManager.bdTheme('hsl(142.1 76.2% 36.3% / 0.1)', 'hsl(142.1 70.6% 45.3% / 0.1)')};
277
+ .control-button {
278
+ background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 14.9%)')};
279
+ border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
280
+ border-radius: 4px;
281
+ padding: 4px 10px;
282
+ color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
283
+ cursor: pointer;
284
+ font-size: 12px;
285
+ font-weight: 500;
286
+ transition: all 0.15s;
216
287
  }
217
288
 
218
- .source {
219
- color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
220
- margin-right: 8px;
221
- flex-shrink: 0;
289
+ .control-button:hover {
290
+ background: ${cssManager.bdTheme('hsl(0 0% 95.1%)', 'hsl(0 0% 20%)')};
291
+ border-color: ${cssManager.bdTheme('hsl(0 0% 79.8%)', 'hsl(0 0% 25%)')};
292
+ color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 93.9%)')};
222
293
  }
223
294
 
224
- .message {
225
- color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 90%)')};
295
+ .control-button.active {
296
+ background: ${cssManager.bdTheme('hsl(222.2 47.4% 51.2%)', 'hsl(217.2 91.2% 59.8%)')};
297
+ border-color: ${cssManager.bdTheme('hsl(222.2 47.4% 51.2%)', 'hsl(217.2 91.2% 59.8%)')};
298
+ color: white;
299
+ }
300
+
301
+ .terminal-container {
226
302
  flex: 1;
303
+ overflow: hidden;
304
+ padding: 8px;
305
+ background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 3.9%)')};
306
+ }
307
+
308
+ .terminal-container .xterm {
309
+ height: 100%;
227
310
  }
228
311
 
229
- .empty-state {
312
+ .loading-state {
230
313
  display: flex;
231
314
  align-items: center;
232
315
  justify-content: center;
233
316
  height: 100%;
234
317
  color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
235
318
  font-style: italic;
319
+ font-size: 13px;
320
+ }
321
+
322
+ .metrics-bar {
323
+ background: ${cssManager.bdTheme('hsl(0 0% 97%)', 'hsl(0 0% 7%)')};
324
+ border-top: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
325
+ padding: 6px 12px;
326
+ display: flex;
327
+ gap: 16px;
328
+ font-size: 11px;
329
+ font-weight: 500;
330
+ flex-shrink: 0;
236
331
  }
237
332
 
238
- /* Custom scrollbar */
239
- .logContainer::-webkit-scrollbar {
333
+ .metric {
334
+ display: flex;
335
+ align-items: center;
336
+ gap: 4px;
337
+ }
338
+
339
+ .metric::before {
340
+ content: '';
240
341
  width: 8px;
342
+ height: 8px;
343
+ border-radius: 50%;
241
344
  }
242
345
 
243
- .logContainer::-webkit-scrollbar-track {
244
- background: ${cssManager.bdTheme('hsl(0 0% 95%)', 'hsl(0 0% 10%)')};
346
+ .metric.error::before {
347
+ background: hsl(0 84.2% 60.2%);
245
348
  }
246
349
 
247
- .logContainer::-webkit-scrollbar-thumb {
248
- background: ${cssManager.bdTheme('hsl(0 0% 70%)', 'hsl(0 0% 30%)')};
249
- border-radius: 4px;
350
+ .metric.warn::before {
351
+ background: hsl(25 95% 53%);
352
+ }
353
+
354
+ .metric.info::before {
355
+ background: hsl(222.2 47.4% 51.2%);
356
+ }
357
+
358
+ .metric.success::before {
359
+ background: hsl(142.1 76.2% 36.3%);
360
+ }
361
+
362
+ .metric.debug::before {
363
+ background: hsl(0 0% 63.9%);
364
+ }
365
+
366
+ .metric.rate {
367
+ margin-left: auto;
368
+ color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
250
369
  }
251
370
 
252
- .logContainer::-webkit-scrollbar-thumb:hover {
253
- background: ${cssManager.bdTheme('hsl(0 0% 60%)', 'hsl(0 0% 40%)')};
371
+ .metric.rate::before {
372
+ display: none;
254
373
  }
255
374
  `,
256
375
  ];
376
+ constructor() {
377
+ super();
378
+ domtools.elementBasic.setup();
379
+ }
257
380
  render() {
258
381
  return html `
259
382
  <div class="mainbox">
260
383
  <div class="header">
261
384
  <div class="title">${this.label}</div>
385
+ <div class="search-box">
386
+ <input
387
+ type="text"
388
+ placeholder="Search logs..."
389
+ .value=${this.searchQuery}
390
+ @input=${(e) => this.handleSearchInput(e)}
391
+ @keydown=${(e) => this.handleSearchKeydown(e)}
392
+ />
393
+ <div class="search-nav">
394
+ <button @click=${() => this.searchPrevious()} title="Previous match">↑</button>
395
+ <button @click=${() => this.searchNext()} title="Next match">↓</button>
396
+ </div>
397
+ <button
398
+ class="filter-toggle ${this.filterMode ? 'active' : ''}"
399
+ @click=${() => this.toggleFilterMode()}
400
+ title="${this.filterMode ? 'Switch to highlight mode' : 'Switch to filter mode'}"
401
+ >
402
+ ${this.filterMode ? 'Filter' : 'Highlight'}
403
+ </button>
404
+ </div>
262
405
  <div class="controls">
263
- <button
406
+ <button
264
407
  class="control-button ${this.autoScroll ? 'active' : ''}"
265
- @click=${() => { this.autoScroll = !this.autoScroll; }}
408
+ @click=${() => this.toggleAutoScroll()}
266
409
  >
267
410
  Auto Scroll
268
411
  </button>
269
- <button
270
- class="control-button"
271
- @click=${() => { this.clearLogs(); }}
272
- >
412
+ <button class="control-button" @click=${() => this.clearLogs()}>
273
413
  Clear
274
414
  </button>
275
415
  </div>
276
416
  </div>
277
- <div class="logContainer">
278
- ${this.logEntries.length === 0
279
- ? html `<div class="empty-state">No logs to display</div>`
280
- : this.logEntries.map(entry => this.renderLogEntry(entry))}
417
+
418
+ <div class="terminal-container">
419
+ ${!this.terminalReady
420
+ ? html `<div class="loading-state">Loading terminal...</div>`
421
+ : ''}
281
422
  </div>
423
+
424
+ ${this.showMetrics
425
+ ? html `
426
+ <div class="metrics-bar">
427
+ <span class="metric error">errors: ${this.metrics.error}</span>
428
+ <span class="metric warn">warns: ${this.metrics.warn}</span>
429
+ <span class="metric info">info: ${this.metrics.info}</span>
430
+ <span class="metric success">success: ${this.metrics.success}</span>
431
+ <span class="metric debug">debug: ${this.metrics.debug}</span>
432
+ <span class="metric rate">${this.metrics.rate.toFixed(1)} logs/sec</span>
433
+ </div>
434
+ `
435
+ : ''}
282
436
  </div>
283
437
  `;
284
438
  }
285
- renderLogEntry(entry) {
286
- const timestamp = new Date(entry.timestamp).toLocaleTimeString('en-US', {
439
+ async firstUpdated() {
440
+ this.domtoolsInstance = await this.domtoolsPromise;
441
+ await this.initializeTerminal();
442
+ // Process any initial log entries
443
+ if (this.logEntries.length > 0) {
444
+ for (const entry of this.logEntries) {
445
+ this.writeLogEntry(entry);
446
+ }
447
+ }
448
+ }
449
+ async initializeTerminal() {
450
+ const libLoader = DeesServiceLibLoader.getInstance();
451
+ const [xtermBundle, fitBundle, searchBundle] = await Promise.all([
452
+ libLoader.loadXterm(),
453
+ libLoader.loadXtermFitAddon(),
454
+ libLoader.loadXtermSearchAddon(),
455
+ ]);
456
+ // Inject xterm CSS into shadow root (needed because shadow DOM doesn't inherit from document.head)
457
+ await this.injectXtermStylesIntoShadow();
458
+ this.terminal = new xtermBundle.Terminal({
459
+ cursorBlink: false,
460
+ disableStdin: true,
461
+ fontSize: 12,
462
+ fontFamily: "'SF Mono', 'Monaco', 'Consolas', 'Liberation Mono', 'Courier New', monospace",
463
+ theme: this.getTerminalTheme(),
464
+ scrollback: this.maxEntries,
465
+ convertEol: true,
466
+ });
467
+ this.fitAddon = new fitBundle.FitAddon();
468
+ this.searchAddon = new searchBundle.SearchAddon();
469
+ this.terminal.loadAddon(this.fitAddon);
470
+ this.terminal.loadAddon(this.searchAddon);
471
+ const container = this.shadowRoot.querySelector('.terminal-container');
472
+ this.terminal.open(container);
473
+ // Fit after a small delay to ensure proper sizing
474
+ await new Promise((resolve) => requestAnimationFrame(resolve));
475
+ this.fitAddon.fit();
476
+ // Set up resize observer
477
+ this.resizeObserver = new ResizeObserver(() => {
478
+ this.fitAddon?.fit();
479
+ });
480
+ this.resizeObserver.observe(container);
481
+ // Subscribe to theme changes
482
+ this.terminalThemeSubscription = this.domtoolsInstance.themeManager.themeObservable.subscribe(() => {
483
+ if (this.terminal) {
484
+ this.terminal.options.theme = this.getTerminalTheme();
485
+ }
486
+ });
487
+ // Start rate calculation interval
488
+ this.rateInterval = setInterval(() => this.calculateRate(), 1000);
489
+ this.terminalReady = true;
490
+ }
491
+ getTerminalTheme() {
492
+ const isDark = this.domtoolsInstance?.themeManager?.isDarkMode ?? true;
493
+ return isDark
494
+ ? {
495
+ background: '#0a0a0a',
496
+ foreground: '#e0e0e0',
497
+ cursor: '#e0e0e0',
498
+ selectionBackground: '#404040',
499
+ black: '#000000',
500
+ red: '#ff5555',
501
+ green: '#50fa7b',
502
+ yellow: '#f1fa8c',
503
+ blue: '#6272a4',
504
+ magenta: '#ff79c6',
505
+ cyan: '#8be9fd',
506
+ white: '#f8f8f2',
507
+ brightBlack: '#6272a4',
508
+ brightRed: '#ff6e6e',
509
+ brightGreen: '#69ff94',
510
+ brightYellow: '#ffffa5',
511
+ brightBlue: '#d6acff',
512
+ brightMagenta: '#ff92df',
513
+ brightCyan: '#a4ffff',
514
+ brightWhite: '#ffffff',
515
+ }
516
+ : {
517
+ background: '#ffffff',
518
+ foreground: '#333333',
519
+ cursor: '#333333',
520
+ selectionBackground: '#add6ff',
521
+ black: '#000000',
522
+ red: '#cd3131',
523
+ green: '#00bc00',
524
+ yellow: '#949800',
525
+ blue: '#0451a5',
526
+ magenta: '#bc05bc',
527
+ cyan: '#0598bc',
528
+ white: '#555555',
529
+ brightBlack: '#666666',
530
+ brightRed: '#cd3131',
531
+ brightGreen: '#14ce14',
532
+ brightYellow: '#b5ba00',
533
+ brightBlue: '#0451a5',
534
+ brightMagenta: '#bc05bc',
535
+ brightCyan: '#0598bc',
536
+ brightWhite: '#a5a5a5',
537
+ };
538
+ }
539
+ /**
540
+ * Inject xterm CSS styles into shadow root
541
+ * This is needed because shadow DOM doesn't inherit styles from document.head
542
+ */
543
+ async injectXtermStylesIntoShadow() {
544
+ const styleId = 'xterm-shadow-styles';
545
+ if (this.shadowRoot.getElementById(styleId)) {
546
+ return; // Already injected
547
+ }
548
+ const cssUrl = `${CDN_BASE}/xterm@${CDN_VERSIONS.xterm}/css/xterm.css`;
549
+ const response = await fetch(cssUrl);
550
+ const cssText = await response.text();
551
+ const style = document.createElement('style');
552
+ style.id = styleId;
553
+ style.textContent = cssText;
554
+ this.shadowRoot.appendChild(style);
555
+ }
556
+ // =====================
557
+ // Structured Log Methods
558
+ // =====================
559
+ /**
560
+ * Add a single structured log entry
561
+ */
562
+ addLog(level, message, source) {
563
+ const entry = {
564
+ timestamp: new Date().toISOString(),
565
+ level,
566
+ message,
567
+ source,
568
+ };
569
+ // Add to buffer
570
+ this.logBuffer.push(entry);
571
+ if (this.logBuffer.length > this.maxEntries) {
572
+ this.logBuffer.shift();
573
+ }
574
+ // Handle display based on filter mode
575
+ if (!this.filterMode || !this.searchQuery) {
576
+ // No filtering - show all entries
577
+ this.writeLogEntry(entry);
578
+ }
579
+ else if (this.entryMatchesFilter(entry)) {
580
+ // Entry matches filter - reset trailing count and write entry
581
+ this.trailingHiddenCount = 0;
582
+ this.writeLogEntry(entry);
583
+ }
584
+ else {
585
+ // Entry doesn't match - update trailing placeholder
586
+ this.updateTrailingPlaceholder();
587
+ }
588
+ this.updateMetrics(entry.level);
589
+ }
590
+ /**
591
+ * Add multiple structured log entries
592
+ */
593
+ updateLog(entries) {
594
+ if (!entries)
595
+ return;
596
+ for (const entry of entries) {
597
+ // Add to buffer
598
+ this.logBuffer.push(entry);
599
+ if (this.logBuffer.length > this.maxEntries) {
600
+ this.logBuffer.shift();
601
+ }
602
+ // Handle display based on filter mode
603
+ if (!this.filterMode || !this.searchQuery) {
604
+ // No filtering - show all entries
605
+ this.writeLogEntry(entry);
606
+ }
607
+ else if (this.entryMatchesFilter(entry)) {
608
+ // Entry matches filter - reset trailing count and write entry
609
+ this.trailingHiddenCount = 0;
610
+ this.writeLogEntry(entry);
611
+ }
612
+ else {
613
+ // Entry doesn't match - update trailing placeholder
614
+ this.updateTrailingPlaceholder();
615
+ }
616
+ this.updateMetrics(entry.level);
617
+ }
618
+ }
619
+ /**
620
+ * Update the trailing hidden placeholder in real-time
621
+ * Clears the last line if a placeholder already exists, then writes updated count
622
+ */
623
+ updateTrailingPlaceholder() {
624
+ if (!this.terminal)
625
+ return;
626
+ if (this.trailingHiddenCount > 0) {
627
+ // Clear the previous placeholder line (move up, clear line, move to start)
628
+ this.terminal.write('\x1b[1A\x1b[2K\r');
629
+ }
630
+ this.trailingHiddenCount++;
631
+ this.writeHiddenPlaceholder(this.trailingHiddenCount);
632
+ if (this.autoScroll) {
633
+ this.terminal.scrollToBottom();
634
+ }
635
+ }
636
+ /**
637
+ * Check if a log entry matches the current filter
638
+ */
639
+ entryMatchesFilter(entry) {
640
+ if (!this.searchQuery)
641
+ return true;
642
+ const query = this.searchQuery.toLowerCase();
643
+ return (entry.message.toLowerCase().includes(query) ||
644
+ entry.level.toLowerCase().includes(query) ||
645
+ (entry.source?.toLowerCase().includes(query) ?? false));
646
+ }
647
+ writeLogEntry(entry) {
648
+ if (!this.terminal)
649
+ return;
650
+ const formatted = this.formatLogEntry(entry);
651
+ this.terminal.writeln(formatted);
652
+ if (this.autoScroll) {
653
+ this.terminal.scrollToBottom();
654
+ }
655
+ }
656
+ formatLogEntry(entry) {
657
+ const timestamp = this.formatTimestamp(entry.timestamp);
658
+ const levelColors = {
659
+ debug: '\x1b[90m', // Gray
660
+ info: '\x1b[36m', // Cyan
661
+ warn: '\x1b[33m', // Yellow
662
+ error: '\x1b[31m', // Red
663
+ success: '\x1b[32m', // Green
664
+ };
665
+ const reset = '\x1b[0m';
666
+ const dim = '\x1b[2m';
667
+ const levelStr = `${levelColors[entry.level]}[${entry.level.toUpperCase().padEnd(7)}]${reset}`;
668
+ const sourceStr = entry.source ? `${dim}[${entry.source}]${reset} ` : '';
669
+ const messageStr = this.applyHighlights(entry.message);
670
+ return `${dim}${timestamp}${reset} ${levelStr} ${sourceStr}${messageStr}`;
671
+ }
672
+ formatTimestamp(isoString) {
673
+ const date = new Date(isoString);
674
+ return date.toLocaleTimeString('en-US', {
287
675
  hour12: false,
288
676
  hour: '2-digit',
289
677
  minute: '2-digit',
290
678
  second: '2-digit',
291
- fractionalSecondDigits: 3
679
+ fractionalSecondDigits: 3,
292
680
  });
293
- return html `
294
- <div class="logEntry">
295
- <span class="timestamp">${timestamp}</span>
296
- <span class="level ${entry.level}">${entry.level}</span>
297
- ${entry.source ? html `<span class="source">[${entry.source}]</span>` : ''}
298
- <span class="message">${entry.message}</span>
299
- </div>
300
- `;
301
681
  }
302
- async firstUpdated() {
303
- await this.domtoolsPromise;
304
- this.logContainer = this.shadowRoot.querySelector('.logContainer');
305
- // Initialize with demo server logs
306
- const demoLogs = [
307
- { timestamp: new Date().toISOString(), level: 'info', message: 'Server started on port 3000', source: 'Server' },
308
- { timestamp: new Date().toISOString(), level: 'debug', message: 'Loading configuration from /etc/app/config.json', source: 'Config' },
309
- { timestamp: new Date().toISOString(), level: 'info', message: 'Connected to MongoDB at mongodb://localhost:27017', source: 'Database' },
310
- { timestamp: new Date().toISOString(), level: 'success', message: 'Database connection established successfully', source: 'Database' },
311
- { timestamp: new Date().toISOString(), level: 'warn', message: 'No SSL certificate found, using self-signed certificate', source: 'Security' },
312
- { timestamp: new Date().toISOString(), level: 'info', message: 'API routes initialized: GET /api/users, POST /api/users, DELETE /api/users/:id', source: 'Router' },
313
- { timestamp: new Date().toISOString(), level: 'debug', message: 'Middleware stack: cors, bodyParser, authentication, errorHandler', source: 'Middleware' },
314
- { timestamp: new Date().toISOString(), level: 'info', message: 'WebSocket server listening on ws://localhost:3001', source: 'WebSocket' },
315
- ];
316
- this.logEntries = demoLogs;
317
- this.scrollToBottom();
318
- }
319
- async updateLog(entries) {
320
- if (entries) {
321
- // Add new entries
322
- this.logEntries = [...this.logEntries, ...entries];
323
- // Trim if exceeds max entries
324
- if (this.logEntries.length > this.maxEntries) {
325
- this.logEntries = this.logEntries.slice(-this.maxEntries);
682
+ applyHighlights(text) {
683
+ // Collect all keywords to highlight
684
+ const keywords = [...this.highlightKeywords];
685
+ // In filter mode, also highlight the search query
686
+ if (this.filterMode && this.searchQuery) {
687
+ keywords.push(this.searchQuery);
688
+ }
689
+ if (keywords.length === 0)
690
+ return text;
691
+ let result = text;
692
+ for (const keyword of keywords) {
693
+ // Escape regex special characters
694
+ const escaped = keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
695
+ const regex = new RegExp(`(${escaped})`, 'gi');
696
+ // Yellow background, black text for highlights
697
+ result = result.replace(regex, '\x1b[43m\x1b[30m$1\x1b[0m');
698
+ }
699
+ return result;
700
+ }
701
+ // =====================
702
+ // Raw Log Methods
703
+ // =====================
704
+ /**
705
+ * Write raw data to the terminal (for Docker logs, etc.)
706
+ */
707
+ writeRaw(data) {
708
+ if (!this.terminal)
709
+ return;
710
+ this.terminal.write(data);
711
+ this.recordLogEvent();
712
+ if (this.autoScroll) {
713
+ this.terminal.scrollToBottom();
714
+ }
715
+ }
716
+ /**
717
+ * Write a raw line to the terminal
718
+ */
719
+ writelnRaw(line) {
720
+ if (!this.terminal)
721
+ return;
722
+ this.terminal.writeln(line);
723
+ this.recordLogEvent();
724
+ if (this.autoScroll) {
725
+ this.terminal.scrollToBottom();
726
+ }
727
+ }
728
+ // =====================
729
+ // Search Methods
730
+ // =====================
731
+ handleSearchInput(e) {
732
+ const input = e.target;
733
+ const newQuery = input.value;
734
+ const queryChanged = this.searchQuery !== newQuery;
735
+ this.searchQuery = newQuery;
736
+ if (this.filterMode && queryChanged) {
737
+ // Re-render with filtered logs
738
+ this.reRenderFilteredLogs();
739
+ }
740
+ else if (this.searchQuery) {
741
+ // Just highlight/search in current view
742
+ this.searchAddon?.findNext(this.searchQuery);
743
+ }
744
+ }
745
+ handleSearchKeydown(e) {
746
+ if (e.key === 'Enter') {
747
+ if (e.shiftKey) {
748
+ this.searchPrevious();
749
+ }
750
+ else {
751
+ this.searchNext();
752
+ }
753
+ }
754
+ else if (e.key === 'Escape') {
755
+ this.searchQuery = '';
756
+ e.target.value = '';
757
+ }
758
+ }
759
+ /**
760
+ * Search for a query in the terminal
761
+ */
762
+ search(query) {
763
+ this.searchQuery = query;
764
+ this.searchAddon?.findNext(query);
765
+ }
766
+ /**
767
+ * Find next search match
768
+ */
769
+ searchNext() {
770
+ if (this.searchQuery) {
771
+ this.searchAddon?.findNext(this.searchQuery);
772
+ }
773
+ }
774
+ /**
775
+ * Find previous search match
776
+ */
777
+ searchPrevious() {
778
+ if (this.searchQuery) {
779
+ this.searchAddon?.findPrevious(this.searchQuery);
780
+ }
781
+ }
782
+ // =====================
783
+ // Control Methods
784
+ // =====================
785
+ toggleAutoScroll() {
786
+ this.autoScroll = !this.autoScroll;
787
+ if (this.autoScroll && this.terminal) {
788
+ this.terminal.scrollToBottom();
789
+ }
790
+ }
791
+ /**
792
+ * Toggle between filter mode and highlight mode
793
+ */
794
+ toggleFilterMode() {
795
+ this.filterMode = !this.filterMode;
796
+ this.reRenderFilteredLogs();
797
+ }
798
+ /**
799
+ * Re-render logs based on current filter state
800
+ * In filter mode: show matching logs with placeholders for hidden entries
801
+ * In highlight mode: show all logs
802
+ */
803
+ reRenderFilteredLogs() {
804
+ if (!this.terminal)
805
+ return;
806
+ // Clear terminal and re-render
807
+ this.terminal.clear();
808
+ // Reset trailing count for fresh render
809
+ this.trailingHiddenCount = 0;
810
+ if (!this.filterMode || !this.searchQuery) {
811
+ // No filtering - show all entries
812
+ for (const entry of this.logBuffer) {
813
+ const formatted = this.formatLogEntry(entry);
814
+ this.terminal.writeln(formatted);
815
+ }
816
+ }
817
+ else {
818
+ // Filter mode with placeholders for hidden entries
819
+ let hiddenCount = 0;
820
+ for (const entry of this.logBuffer) {
821
+ if (this.entryMatchesFilter(entry)) {
822
+ // Output placeholder for hidden entries if any
823
+ if (hiddenCount > 0) {
824
+ this.writeHiddenPlaceholder(hiddenCount);
825
+ hiddenCount = 0;
826
+ }
827
+ // Output the matching entry
828
+ const formatted = this.formatLogEntry(entry);
829
+ this.terminal.writeln(formatted);
830
+ }
831
+ else {
832
+ hiddenCount++;
833
+ }
326
834
  }
327
- // Trigger re-render
328
- this.requestUpdate();
329
- // Auto-scroll if enabled
330
- await this.updateComplete;
331
- if (this.autoScroll) {
332
- this.scrollToBottom();
835
+ // Handle trailing hidden entries
836
+ if (hiddenCount > 0) {
837
+ this.writeHiddenPlaceholder(hiddenCount);
838
+ // Store trailing count for live updates
839
+ this.trailingHiddenCount = hiddenCount;
333
840
  }
334
841
  }
842
+ if (this.autoScroll) {
843
+ this.terminal.scrollToBottom();
844
+ }
845
+ }
846
+ /**
847
+ * Write a placeholder line showing how many log entries are hidden by filter
848
+ */
849
+ writeHiddenPlaceholder(count) {
850
+ const dim = '\x1b[2m';
851
+ const reset = '\x1b[0m';
852
+ const text = count === 1
853
+ ? `[1 log line hidden by filter ...]`
854
+ : `[${count} log lines hidden by filter ...]`;
855
+ this.terminal?.writeln(`${dim}${text}${reset}`);
335
856
  }
857
+ /**
858
+ * Clear all logs and reset metrics
859
+ */
336
860
  clearLogs() {
337
- this.logEntries = [];
338
- this.requestUpdate();
861
+ this.terminal?.clear();
862
+ this.logBuffer = [];
863
+ this.trailingHiddenCount = 0;
864
+ this.resetMetrics();
339
865
  }
866
+ /**
867
+ * Scroll to the bottom of the log
868
+ */
340
869
  scrollToBottom() {
341
- if (this.logContainer) {
342
- this.logContainer.scrollTop = this.logContainer.scrollHeight;
343
- }
870
+ this.terminal?.scrollToBottom();
344
871
  }
345
- addLog(level, message, source) {
346
- const newEntry = {
347
- timestamp: new Date().toISOString(),
348
- level,
349
- message,
350
- source
872
+ // =====================
873
+ // Metrics Methods
874
+ // =====================
875
+ updateMetrics(level) {
876
+ this.metrics = {
877
+ ...this.metrics,
878
+ [level]: this.metrics[level] + 1,
879
+ total: this.metrics.total + 1,
351
880
  };
352
- this.updateLog([newEntry]);
881
+ this.recordLogEvent();
882
+ }
883
+ recordLogEvent() {
884
+ this.rateBuffer.push(Date.now());
885
+ }
886
+ calculateRate() {
887
+ const now = Date.now();
888
+ // Keep only events from the last 10 seconds
889
+ this.rateBuffer = this.rateBuffer.filter((t) => now - t < 10000);
890
+ const rate = this.rateBuffer.length / 10;
891
+ if (rate !== this.metrics.rate) {
892
+ this.metrics = { ...this.metrics, rate };
893
+ }
894
+ }
895
+ resetMetrics() {
896
+ this.metrics = { debug: 0, info: 0, warn: 0, error: 0, success: 0, total: 0, rate: 0 };
897
+ this.rateBuffer = [];
898
+ }
899
+ // =====================
900
+ // Lifecycle
901
+ // =====================
902
+ async disconnectedCallback() {
903
+ await super.disconnectedCallback();
904
+ if (this.resizeObserver) {
905
+ this.resizeObserver.disconnect();
906
+ }
907
+ if (this.terminalThemeSubscription) {
908
+ this.terminalThemeSubscription.unsubscribe();
909
+ }
910
+ if (this.rateInterval) {
911
+ clearInterval(this.rateInterval);
912
+ }
913
+ if (this.terminal) {
914
+ this.terminal.dispose();
915
+ }
353
916
  }
354
917
  static {
355
918
  __runInitializers(_classThis, _classExtraInitializers);
@@ -358,4 +921,4 @@ let DeesChartLog = (() => {
358
921
  return DeesChartLog = _classThis;
359
922
  })();
360
923
  export { DeesChartLog };
361
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVlcy1jaGFydC1sb2cuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90c193ZWIvZWxlbWVudHMvMDBncm91cC1jaGFydC9kZWVzLWNoYXJ0LWxvZy9kZWVzLWNoYXJ0LWxvZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsT0FBTyxFQUNMLFdBQVcsRUFDWCxHQUFHLEVBQ0gsVUFBVSxFQUNWLGFBQWEsRUFDYixJQUFJLEVBQ0osUUFBUSxHQUVULE1BQU0sNkJBQTZCLENBQUM7QUFFckMsT0FBTyxLQUFLLFFBQVEsTUFBTSw4QkFBOEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDcEQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7SUFpQnpDLFlBQVk7NEJBRHhCLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQzs7OztzQkFDRSxXQUFXOzs7Ozs7Ozs7Ozs7OzRCQUFuQixTQUFRLFdBQVc7Ozs7aUNBSTFDLFFBQVEsRUFBRTtzQ0FHVixRQUFRLENBQUMsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUM7c0NBR3pCLFFBQVEsQ0FBQyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQztzQ0FHM0IsUUFBUSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDO1lBUjNCLG9LQUFTLEtBQUssNkJBQUwsS0FBSyxxRkFBeUI7WUFHdkMsbUxBQVMsVUFBVSw2QkFBVixVQUFVLCtGQUFtQjtZQUd0QyxtTEFBUyxVQUFVLDZCQUFWLFVBQVUsK0ZBQWlCO1lBR3BDLG1MQUFTLFVBQVUsNkJBQVYsVUFBVSwrRkFBZ0I7WUFkckMsNktBNFNDOzs7O1FBM1NRLE1BQU0sQ0FBQyxJQUFJLEdBQUcsUUFBUSxDQUFDO1FBQ3ZCLE1BQU0sQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDO1FBR2xDLHVF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
924
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVlcy1jaGFydC1sb2cuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90c193ZWIvZWxlbWVudHMvMDBncm91cC1jaGFydC9kZWVzLWNoYXJ0LWxvZy9kZWVzLWNoYXJ0LWxvZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsT0FBTyxFQUNMLFdBQVcsRUFDWCxHQUFHLEVBQ0gsVUFBVSxFQUNWLGFBQWEsRUFDYixJQUFJLEVBQ0osUUFBUSxFQUNSLEtBQUssR0FFTixNQUFNLDZCQUE2QixDQUFDO0FBRXJDLE9BQU8sS0FBSyxRQUFRLE1BQU0sOEJBQThCLENBQUM7QUFDekQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxvQkFBb0IsRUFBMEIsUUFBUSxFQUFFLFlBQVksRUFBRSxNQUFNLDRCQUE0QixDQUFDO0lBOEJyRyxZQUFZOzRCQUR4QixhQUFhLENBQUMsZ0JBQWdCLENBQUM7Ozs7c0JBQ0UsV0FBVzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs0QkFBbkIsU0FBUSxXQUFXOzs7O2lDQUkxQyxRQUFRLEVBQUU7Z0NBR1YsUUFBUSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDO3NDQUcxQixRQUFRLENBQUMsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUM7c0NBR3pCLFFBQVEsQ0FBQyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQztzQ0FHM0IsUUFBUSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDOzZDQUcxQixRQUFRLENBQUMsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUM7dUNBR3pCLFFBQVEsQ0FBQyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FB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