@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@design.estate/dees-catalog",
3
- "version": "3.35.1",
3
+ "version": "3.37.0",
4
4
  "private": false,
5
5
  "description": "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.",
6
6
  "main": "dist_ts_web/index.js",
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@design.estate/dees-catalog',
6
- version: '3.35.1',
6
+ version: '3.37.0',
7
7
  description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
8
8
  }
@@ -142,54 +142,95 @@ export const demoFunc = () => html`
142
142
  <dees-panel .title=${'3. Buttons with Icons'} .subtitle=${'Combining icons with text for enhanced visual communication'}>
143
143
  <div class="icon-row">
144
144
  <dees-button>
145
- <dees-icon iconFA="faPlus"></dees-icon>
145
+ <dees-icon icon="fa:plus"></dees-icon>
146
146
  Add Item
147
147
  </dees-button>
148
148
  <dees-button type="destructive">
149
- <dees-icon iconFA="faTrash"></dees-icon>
149
+ <dees-icon icon="fa:trash"></dees-icon>
150
150
  Delete
151
151
  </dees-button>
152
152
  <dees-button type="outline">
153
- <dees-icon iconFA="faDownload"></dees-icon>
153
+ <dees-icon icon="lucide:Download"></dees-icon>
154
154
  Download
155
155
  </dees-button>
156
156
  </div>
157
-
157
+
158
158
  <div class="icon-row">
159
159
  <dees-button type="secondary" size="sm">
160
- <dees-icon iconFA="faCog"></dees-icon>
160
+ <dees-icon icon="fa:gear"></dees-icon>
161
161
  Settings
162
162
  </dees-button>
163
163
  <dees-button type="ghost">
164
- <dees-icon iconFA="faChevronLeft"></dees-icon>
164
+ <dees-icon icon="fa:caretLeft"></dees-icon>
165
165
  Back
166
166
  </dees-button>
167
167
  <dees-button type="ghost">
168
168
  Next
169
- <dees-icon iconFA="faChevronRight"></dees-icon>
169
+ <dees-icon icon="fa:caretRight"></dees-icon>
170
170
  </dees-button>
171
171
  </div>
172
-
172
+
173
173
  <div class="icon-row">
174
174
  <dees-button size="icon" type="default">
175
- <dees-icon iconFA="faPlus"></dees-icon>
175
+ <dees-icon icon="fa:plus"></dees-icon>
176
176
  </dees-button>
177
177
  <dees-button size="icon" type="secondary">
178
- <dees-icon iconFA="faCog"></dees-icon>
178
+ <dees-icon icon="fa:gear"></dees-icon>
179
179
  </dees-button>
180
180
  <dees-button size="icon" type="outline">
181
- <dees-icon iconFA="faSearch"></dees-icon>
181
+ <dees-icon icon="lucide:Search"></dees-icon>
182
182
  </dees-button>
183
183
  <dees-button size="icon" type="ghost">
184
- <dees-icon iconFA="faEllipsisV"></dees-icon>
184
+ <dees-icon icon="lucide:MoreVertical"></dees-icon>
185
185
  </dees-button>
186
186
  <dees-button size="icon" type="destructive">
187
- <dees-icon iconFA="faTrash"></dees-icon>
187
+ <dees-icon icon="fa:trash"></dees-icon>
188
188
  </dees-button>
189
189
  </div>
190
190
  </dees-panel>
191
191
  </dees-demowrapper>
192
-
192
+
193
+ <dees-demowrapper .runAfterRender=${async (elementArg: HTMLElement) => {
194
+ // Track icon property button clicks
195
+ const buttons = elementArg.querySelectorAll('dees-button');
196
+ buttons.forEach((button) => {
197
+ button.addEventListener('clicked', () => {
198
+ const icon = button.getAttribute('icon') || 'none';
199
+ const position = button.getAttribute('iconPosition') || 'left';
200
+ console.log(`Icon property button: icon=${icon}, position=${position}`);
201
+ });
202
+ });
203
+ }}>
204
+ <dees-panel .title=${'4. Icons via Property'} .subtitle=${'Simplified icon syntax using the icon property'}>
205
+ <div class="icon-row">
206
+ <dees-button icon="fa:plus">Add Item</dees-button>
207
+ <dees-button type="destructive" icon="fa:trash">Delete</dees-button>
208
+ <dees-button type="outline" icon="lucide:Download">Download</dees-button>
209
+ </div>
210
+
211
+ <div class="icon-row">
212
+ <dees-button type="secondary" size="sm" icon="fa:gear">Settings</dees-button>
213
+ <dees-button type="ghost" icon="fa:caretLeft">Back</dees-button>
214
+ <dees-button type="ghost" icon="fa:caretRight" iconPosition="right">Next</dees-button>
215
+ </div>
216
+
217
+ <div class="icon-row">
218
+ <dees-button size="icon" type="default" icon="fa:plus"></dees-button>
219
+ <dees-button size="icon" type="secondary" icon="lucide:Settings"></dees-button>
220
+ <dees-button size="icon" type="outline" icon="lucide:Search"></dees-button>
221
+ <dees-button size="icon" type="ghost" icon="lucide:MoreVertical"></dees-button>
222
+ <dees-button size="icon" type="destructive" icon="fa:trash"></dees-button>
223
+ </div>
224
+
225
+ <div style="margin-top: 16px;">
226
+ <div class="code-snippet">
227
+ &lt;dees-button icon="fa:plus"&gt;Add Item&lt;/dees-button&gt;<br>
228
+ &lt;dees-button icon="fa:caretRight" iconPosition="right"&gt;Next&lt;/dees-button&gt;
229
+ </div>
230
+ </div>
231
+ </dees-panel>
232
+ </dees-demowrapper>
233
+
193
234
  <dees-demowrapper .runAfterRender=${async (elementArg: HTMLElement) => {
194
235
  // Demonstrate status changes
195
236
  const pendingButton = elementArg.querySelector('dees-button[status="pending"]');
@@ -215,7 +256,7 @@ export const demoFunc = () => html`
215
256
  });
216
257
  }
217
258
  }}>
218
- <dees-panel .title=${'4. Button States'} .subtitle=${'Different states to indicate button status and loading conditions'}>
259
+ <dees-panel .title=${'5. Button States'} .subtitle=${'Different states to indicate button status and loading conditions'}>
219
260
  <div class="button-group">
220
261
  <dees-button status="normal">Normal</dees-button>
221
262
  <dees-button status="pending">Processing...</dees-button>
@@ -260,7 +301,7 @@ export const demoFunc = () => html`
260
301
  });
261
302
  }
262
303
  }}>
263
- <dees-panel .title=${'5. Event Handling'} .subtitle=${'Interactive examples with click event handling'}>
304
+ <dees-panel .title=${'6. Event Handling'} .subtitle=${'Interactive examples with click event handling'}>
264
305
  <div class="button-group">
265
306
  <dees-button>Click Me</dees-button>
266
307
  <dees-button type="secondary" .eventDetailData=${'custom-data-123'}>
@@ -303,7 +344,7 @@ export const demoFunc = () => html`
303
344
  });
304
345
  }
305
346
  }}>
306
- <dees-panel .title=${'6. Form Integration'} .subtitle=${'Buttons working within forms with automatic spacing'}>
347
+ <dees-panel .title=${'7. Form Integration'} .subtitle=${'Buttons working within forms with automatic spacing'}>
307
348
  <dees-form>
308
349
  <dees-input-text label="Name" key="name" required></dees-input-text>
309
350
  <dees-input-text label="Email" key="email" type="email" required></dees-input-text>
@@ -330,7 +371,7 @@ export const demoFunc = () => html`
330
371
  }
331
372
  });
332
373
  }}>
333
- <dees-panel .title=${'7. Backward Compatibility'} .subtitle=${'Old button types are automatically mapped to new variants'}>
374
+ <dees-panel .title=${'8. Backward Compatibility'} .subtitle=${'Old button types are automatically mapped to new variants'}>
334
375
  <div class="button-group">
335
376
  <dees-button type="normal">Normal → Default</dees-button>
336
377
  <dees-button type="highlighted">Highlighted → Destructive</dees-button>
@@ -371,36 +412,36 @@ export const demoFunc = () => html`
371
412
  });
372
413
  }
373
414
  }}>
374
- <dees-panel .title=${'8. Advanced Examples'} .subtitle=${'Complex button configurations and real-world use cases'}>
415
+ <dees-panel .title=${'9. Advanced Examples'} .subtitle=${'Complex button configurations and real-world use cases'}>
375
416
  <div class="horizontal-group">
376
417
  <div class="vertical-group">
377
418
  <h4 style="margin: 0 0 8px 0; font-size: 14px; font-weight: 500;">Action Group</h4>
378
419
  <dees-button type="default" size="sm">
379
- <dees-icon iconFA="faSave"></dees-icon>
420
+ <dees-icon icon="lucide:Save"></dees-icon>
380
421
  Save Changes
381
422
  </dees-button>
382
423
  <dees-button type="secondary" size="sm">
383
- <dees-icon iconFA="faUndo"></dees-icon>
424
+ <dees-icon icon="lucide:Undo2"></dees-icon>
384
425
  Discard
385
426
  </dees-button>
386
427
  <dees-button type="ghost" size="sm">
387
- <dees-icon iconFA="faQuestionCircle"></dees-icon>
428
+ <dees-icon icon="lucide:HelpCircle"></dees-icon>
388
429
  Help
389
430
  </dees-button>
390
431
  </div>
391
-
432
+
392
433
  <div class="vertical-group">
393
434
  <h4 style="margin: 0 0 8px 0; font-size: 14px; font-weight: 500;">Danger Zone</h4>
394
435
  <dees-button type="destructive" size="sm">
395
- <dees-icon iconFA="faTrash"></dees-icon>
436
+ <dees-icon icon="fa:trash"></dees-icon>
396
437
  Delete Account
397
438
  </dees-button>
398
439
  <dees-button type="outline" size="sm">
399
- <dees-icon iconFA="faArchive"></dees-icon>
440
+ <dees-icon icon="lucide:Archive"></dees-icon>
400
441
  Archive Data
401
442
  </dees-button>
402
443
  <dees-button type="ghost" size="sm" disabled>
403
- <dees-icon iconFA="faBan"></dees-icon>
444
+ <dees-icon icon="lucide:Ban"></dees-icon>
404
445
  Not Available
405
446
  </dees-button>
406
447
  </div>
@@ -409,8 +450,7 @@ export const demoFunc = () => html`
409
450
  <div style="margin-top: 24px;">
410
451
  <h4 style="margin: 0 0 8px 0; font-size: 14px; font-weight: 500;">Code Example:</h4>
411
452
  <div class="code-snippet">
412
- &lt;dees-button type="default" size="sm" @clicked="\${handleClick}"&gt;<br>
413
- &nbsp;&nbsp;&lt;dees-icon iconFA="faSave"&gt;&lt;/dees-icon&gt;<br>
453
+ &lt;dees-button type="default" size="sm" icon="lucide:Save" @clicked="\${handleClick}"&gt;<br>
414
454
  &nbsp;&nbsp;Save Changes<br>
415
455
  &lt;/dees-button&gt;
416
456
  </div>
@@ -68,6 +68,12 @@ export class DeesButton extends DeesElement {
68
68
  })
69
69
  accessor insideForm: boolean = false;
70
70
 
71
+ @property({ type: String, reflect: true })
72
+ accessor icon: string;
73
+
74
+ @property({ type: String, reflect: true })
75
+ accessor iconPosition: 'left' | 'right' = 'left';
76
+
71
77
  constructor() {
72
78
  super();
73
79
  }
@@ -340,9 +346,62 @@ export class DeesButton extends DeesElement {
340
346
  height: 18px;
341
347
  }
342
348
 
349
+ /* Text alignment */
350
+ .textbox {
351
+ display: flex;
352
+ align-items: center;
353
+ }
354
+
343
355
  `,
344
356
  ];
345
357
 
358
+ /**
359
+ * Extracts icon and text from light DOM and sets properties
360
+ */
361
+ private extractLightDom(): void {
362
+ const iconElement = this.querySelector('dees-icon') as any;
363
+
364
+ // Get all text content from light DOM
365
+ const textContent = Array.from(this.childNodes)
366
+ .filter(node => node.nodeType === Node.TEXT_NODE)
367
+ .map(node => node.textContent?.trim())
368
+ .filter(Boolean)
369
+ .join(' ');
370
+
371
+ if (textContent && !this.text) {
372
+ this.text = textContent;
373
+ }
374
+
375
+ if (iconElement) {
376
+ // Get icon value
377
+ const iconValue = iconElement.icon || iconElement.getAttribute('icon') ||
378
+ (iconElement.iconFA ? `fa:${iconElement.iconFA}` : null);
379
+
380
+ if (iconValue) {
381
+ // Determine position based on DOM order
382
+ const children = Array.from(this.childNodes);
383
+ const iconIndex = children.indexOf(iconElement);
384
+ const textNodes = children.filter(node =>
385
+ node.nodeType === Node.TEXT_NODE && node.textContent?.trim()
386
+ );
387
+
388
+ if (textNodes.length > 0) {
389
+ const firstTextIndex = children.indexOf(textNodes[0]);
390
+ this.iconPosition = iconIndex < firstTextIndex ? 'left' : 'right';
391
+ }
392
+
393
+ // Set the icon property
394
+ this.icon = iconValue;
395
+ }
396
+
397
+ // Remove the light DOM icon element
398
+ iconElement.remove();
399
+ }
400
+
401
+ // Clear all remaining light DOM
402
+ this.innerHTML = '';
403
+ }
404
+
346
405
  public render(): TemplateResult {
347
406
  // Map old types to new types for backward compatibility
348
407
  const typeMap: {[key: string]: string} = {
@@ -351,10 +410,20 @@ export class DeesButton extends DeesElement {
351
410
  'discreet': 'outline',
352
411
  'big': 'default' // Will use size instead
353
412
  };
354
-
413
+
355
414
  const actualType = typeMap[this.type] || this.type;
356
415
  const actualSize = this.type === 'big' ? 'lg' : this.size;
357
-
416
+
417
+ const leftIcon = this.iconPosition === 'left' && this.icon
418
+ ? html`<dees-icon .icon=${this.icon}></dees-icon>`
419
+ : '';
420
+ const rightIcon = this.iconPosition === 'right' && this.icon
421
+ ? html`<dees-icon .icon=${this.icon}></dees-icon>`
422
+ : '';
423
+
424
+ // For icon-only buttons, hide the textbox
425
+ const isIconOnly = actualSize === 'icon' && this.icon;
426
+
358
427
  return html`
359
428
  <div
360
429
  class="button ${this.isHidden ? 'hidden' : ''} ${actualType} size-${actualSize} ${this.status} ${this.disabled
@@ -363,13 +432,15 @@ export class DeesButton extends DeesElement {
363
432
  @click="${this.dispatchClick}"
364
433
  >
365
434
  ${this.status === 'normal' ? html``: html`
366
- <dees-spinner
367
- .bnw=${true}
435
+ <dees-spinner
436
+ .bnw=${true}
368
437
  status="${this.status}"
369
438
  size="${actualSize === 'sm' ? 14 : actualSize === 'lg' ? 18 : 16}"
370
439
  ></dees-spinner>
371
440
  `}
372
- <div class="textbox">${this.text || html`<slot>Button</slot>`}</div>
441
+ ${leftIcon}
442
+ ${isIconOnly ? '' : html`<div class="textbox">${this.text || 'Button'}</div>`}
443
+ ${rightIcon}
373
444
  </div>
374
445
  `;
375
446
  }
@@ -390,6 +461,7 @@ export class DeesButton extends DeesElement {
390
461
  }
391
462
 
392
463
  public async firstUpdated() {
393
- // Don't set default text here as it interferes with slotted content
464
+ // Extract light DOM content (icon + text) and set as properties
465
+ this.extractLightDom();
394
466
  }
395
467
  }
@@ -1,16 +1,18 @@
1
- import { html } from '@design.estate/dees-element';
1
+ import { html, css, cssManager } from '@design.estate/dees-element';
2
2
  import type { DeesChartLog } from '../dees-chart-log/dees-chart-log.js';
3
3
  import '@design.estate/dees-wcctools/demotools';
4
4
 
5
5
  export const demoFunc = () => {
6
6
  return html`
7
7
  <dees-demowrapper .runAfterRender=${async (elementArg: HTMLElement) => {
8
- // Get the log element
9
- const logElement = elementArg.querySelector('dees-chart-log') as DeesChartLog;
10
- let intervalId: number;
8
+ // Get the log elements
9
+ const structuredLog = elementArg.querySelector('#structured-log') as DeesChartLog;
10
+ const rawLog = elementArg.querySelector('#raw-log') as DeesChartLog;
11
+ let structuredIntervalId: number;
12
+ let rawIntervalId: number;
11
13
 
12
14
  const serverSources = ['Server', 'Database', 'API', 'Auth', 'Cache', 'Queue', 'WebSocket', 'Scheduler'];
13
-
15
+
14
16
  const logTemplates = {
15
17
  debug: [
16
18
  'Loading module: {{module}}',
@@ -49,14 +51,30 @@ export const demoFunc = () => {
49
51
  ],
50
52
  };
51
53
 
54
+ // Docker-like raw log lines with ANSI colors
55
+ const dockerLogTemplates = [
56
+ '\x1b[90m2024-01-15T10:23:45.123Z\x1b[0m \x1b[36mINFO\x1b[0m [nginx] GET /api/health 200 - 2ms',
57
+ '\x1b[90m2024-01-15T10:23:45.456Z\x1b[0m \x1b[33mWARN\x1b[0m [redis] Connection pool running low: 3/10',
58
+ '\x1b[90m2024-01-15T10:23:45.789Z\x1b[0m \x1b[31mERROR\x1b[0m [mongodb] Query timeout after 30000ms',
59
+ '\x1b[90m2024-01-15T10:23:46.012Z\x1b[0m \x1b[36mINFO\x1b[0m [app] Processing batch job #{{jobId}}',
60
+ '\x1b[90m2024-01-15T10:23:46.345Z\x1b[0m \x1b[32mOK\x1b[0m [health] All services healthy',
61
+ '\x1b[90m2024-01-15T10:23:46.678Z\x1b[0m \x1b[36mINFO\x1b[0m [kafka] Message consumed from topic: events',
62
+ '\x1b[90m2024-01-15T10:23:47.001Z\x1b[0m \x1b[35mDEBUG\x1b[0m [grpc] Request received: GetUser(id={{userId}})',
63
+ '\x1b[90m2024-01-15T10:23:47.234Z\x1b[0m \x1b[31mERROR\x1b[0m [auth] Token validation failed: expired',
64
+ '\x1b[90m2024-01-15T10:23:47.567Z\x1b[0m \x1b[33mWARN\x1b[0m [rate-limit] IP {{ip}} approaching rate limit',
65
+ '\x1b[90m2024-01-15T10:23:47.890Z\x1b[0m \x1b[36mINFO\x1b[0m [websocket] Client connected: session={{session}}',
66
+ // Multi-line log entry like stack traces
67
+ '\x1b[31mError: Connection refused\x1b[0m\n at TcpConnection.connect (/app/node_modules/pg/lib/connection.js:12:15)\n at Pool.connect (/app/node_modules/pg/lib/pool.js:45:23)\n at async DatabaseService.query (/app/src/db/service.ts:89:12)',
68
+ ];
69
+
52
70
  const generateRandomLog = () => {
53
71
  const levels: Array<'debug' | 'info' | 'warn' | 'error' | 'success'> = ['debug', 'info', 'warn', 'error', 'success'];
54
- const weights = [0.2, 0.5, 0.15, 0.1, 0.05]; // Weighted probability
55
-
72
+ const weights = [0.2, 0.5, 0.15, 0.1, 0.05];
73
+
56
74
  const random = Math.random();
57
75
  let cumulative = 0;
58
76
  let level: typeof levels[0] = 'info';
59
-
77
+
60
78
  for (let i = 0; i < weights.length; i++) {
61
79
  cumulative += weights[i];
62
80
  if (random < cumulative) {
@@ -68,7 +86,7 @@ export const demoFunc = () => {
68
86
  const source = serverSources[Math.floor(Math.random() * serverSources.length)];
69
87
  const templates = logTemplates[level];
70
88
  const template = templates[Math.floor(Math.random() * templates.length)];
71
-
89
+
72
90
  // Replace placeholders with random values
73
91
  const message = template
74
92
  .replace('{{module}}', ['express', 'mongoose', 'redis', 'socket.io'][Math.floor(Math.random() * 4)])
@@ -92,17 +110,52 @@ export const demoFunc = () => {
92
110
  .replace('{{port}}', String(3000 + Math.floor(Math.random() * 10)))
93
111
  .replace('{{size}}', String(Math.floor(Math.random() * 500) + 100));
94
112
 
95
- logElement.addLog(level, message, source);
113
+ structuredLog.addLog(level, message, source);
114
+ };
115
+
116
+ const generateDockerLog = () => {
117
+ const template = dockerLogTemplates[Math.floor(Math.random() * dockerLogTemplates.length)];
118
+ const now = new Date().toISOString();
119
+
120
+ const logLine = template
121
+ .replace(/2024-01-15T10:23:\d{2}\.\d{3}Z/g, now)
122
+ .replace('{{jobId}}', String(Math.floor(Math.random() * 10000)))
123
+ .replace('{{userId}}', String(Math.floor(Math.random() * 10000)))
124
+ .replace('{{ip}}', `192.168.1.${Math.floor(Math.random() * 255)}`)
125
+ .replace('{{session}}', Math.random().toString(36).substring(2, 11));
126
+
127
+ rawLog.writelnRaw(logLine);
96
128
  };
97
129
 
98
- const startSimulation = () => {
99
- if (!intervalId) {
100
- // Generate logs at random intervals between 500ms and 2500ms
130
+ const startStructuredSimulation = () => {
131
+ if (!structuredIntervalId) {
101
132
  const scheduleNext = () => {
102
133
  generateRandomLog();
103
134
  const nextDelay = Math.random() * 2000 + 500;
104
- intervalId = window.setTimeout(() => {
105
- if (intervalId) {
135
+ structuredIntervalId = window.setTimeout(() => {
136
+ if (structuredIntervalId) {
137
+ scheduleNext();
138
+ }
139
+ }, nextDelay);
140
+ };
141
+ scheduleNext();
142
+ }
143
+ };
144
+
145
+ const stopStructuredSimulation = () => {
146
+ if (structuredIntervalId) {
147
+ window.clearTimeout(structuredIntervalId);
148
+ structuredIntervalId = null;
149
+ }
150
+ };
151
+
152
+ const startRawSimulation = () => {
153
+ if (!rawIntervalId) {
154
+ const scheduleNext = () => {
155
+ generateDockerLog();
156
+ const nextDelay = Math.random() * 1000 + 200;
157
+ rawIntervalId = window.setTimeout(() => {
158
+ if (rawIntervalId) {
106
159
  scheduleNext();
107
160
  }
108
161
  }, nextDelay);
@@ -111,10 +164,10 @@ export const demoFunc = () => {
111
164
  }
112
165
  };
113
166
 
114
- const stopSimulation = () => {
115
- if (intervalId) {
116
- window.clearTimeout(intervalId);
117
- intervalId = null;
167
+ const stopRawSimulation = () => {
168
+ if (rawIntervalId) {
169
+ window.clearTimeout(rawIntervalId);
170
+ rawIntervalId = null;
118
171
  }
119
172
  };
120
173
 
@@ -122,49 +175,103 @@ export const demoFunc = () => {
122
175
  const buttons = elementArg.querySelectorAll('dees-button');
123
176
  buttons.forEach(button => {
124
177
  const text = button.textContent?.trim();
125
- if (text === 'Add Single Log') {
126
- button.addEventListener('click', () => generateRandomLog());
127
- } else if (text === 'Start Simulation') {
128
- button.addEventListener('click', () => startSimulation());
129
- } else if (text === 'Stop Simulation') {
130
- button.addEventListener('click', () => stopSimulation());
178
+ switch (text) {
179
+ case 'Add Structured Log':
180
+ button.addEventListener('click', () => generateRandomLog());
181
+ break;
182
+ case 'Start Structured':
183
+ button.addEventListener('click', () => startStructuredSimulation());
184
+ break;
185
+ case 'Stop Structured':
186
+ button.addEventListener('click', () => stopStructuredSimulation());
187
+ break;
188
+ case 'Add Docker Log':
189
+ button.addEventListener('click', () => generateDockerLog());
190
+ break;
191
+ case 'Start Docker':
192
+ button.addEventListener('click', () => startRawSimulation());
193
+ break;
194
+ case 'Stop Docker':
195
+ button.addEventListener('click', () => stopRawSimulation());
196
+ break;
131
197
  }
132
198
  });
133
199
  }}>
134
200
  <style>
135
- .demoBox {
136
- position: relative;
137
- background: #000000;
138
- height: 100%;
139
- width: 100%;
140
- padding: 40px;
141
- box-sizing: border-box;
142
- display: flex;
143
- flex-direction: column;
144
- gap: 20px;
145
- }
146
- .controls {
147
- display: flex;
148
- gap: 10px;
149
- flex-wrap: wrap;
150
- }
151
- .info {
152
- color: #888;
153
- font-size: 12px;
154
- font-family: 'Geist Sans', sans-serif;
155
- }
156
- </style>
201
+ ${css`
202
+ .demoBox {
203
+ position: relative;
204
+ background: ${cssManager.bdTheme('hsl(0 0% 95%)', 'hsl(0 0% 5%)')};
205
+ height: 100%;
206
+ width: 100%;
207
+ padding: 40px;
208
+ box-sizing: border-box;
209
+ display: flex;
210
+ flex-direction: column;
211
+ gap: 24px;
212
+ }
213
+ .section {
214
+ display: flex;
215
+ flex-direction: column;
216
+ gap: 12px;
217
+ }
218
+ .section-title {
219
+ color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 95%)')};
220
+ font-size: 14px;
221
+ font-weight: 600;
222
+ font-family: 'Geist Sans', sans-serif;
223
+ }
224
+ .section-description {
225
+ color: ${cssManager.bdTheme('hsl(215.4 16.3% 46.9%)', 'hsl(215 20.2% 65.1%)')};
226
+ font-size: 12px;
227
+ font-family: 'Geist Sans', sans-serif;
228
+ }
229
+ .controls {
230
+ display: flex;
231
+ gap: 10px;
232
+ flex-wrap: wrap;
233
+ }
234
+ `}
235
+ </style>
157
236
  <div class="demoBox">
158
- <div class="controls">
159
- <dees-button>Add Single Log</dees-button>
160
- <dees-button>Start Simulation</dees-button>
161
- <dees-button>Stop Simulation</dees-button>
237
+ <!-- Structured Logs Section -->
238
+ <div class="section">
239
+ <div class="section-title">Structured Logs (ILogEntry)</div>
240
+ <div class="section-description">
241
+ Structured log entries with level, message, and source. Supports search and keyword highlighting.
242
+ </div>
243
+ <div class="controls">
244
+ <dees-button>Add Structured Log</dees-button>
245
+ <dees-button>Start Structured</dees-button>
246
+ <dees-button>Stop Structured</dees-button>
247
+ </div>
248
+ <dees-chart-log
249
+ id="structured-log"
250
+ .label=${'Production Server Logs'}
251
+ .highlightKeywords=${['error', 'failed', 'timeout']}
252
+ .showMetrics=${true}
253
+ ></dees-chart-log>
254
+ </div>
255
+
256
+ <!-- Raw Logs Section -->
257
+ <div class="section">
258
+ <div class="section-title">Raw Logs (Docker/Container Style)</div>
259
+ <div class="section-description">
260
+ Raw log output with ANSI escape sequences for real Docker/container logs.
261
+ </div>
262
+ <div class="controls">
263
+ <dees-button>Add Docker Log</dees-button>
264
+ <dees-button>Start Docker</dees-button>
265
+ <dees-button>Stop Docker</dees-button>
266
+ </div>
267
+ <dees-chart-log
268
+ id="raw-log"
269
+ .label=${'Docker Container Logs'}
270
+ .mode=${'raw'}
271
+ .showMetrics=${false}
272
+ ></dees-chart-log>
162
273
  </div>
163
- <div class="info">Simulating realistic server logs with various levels and sources</div>
164
- <dees-chart-log
165
- .label=${'Production Server Logs'}
166
- ></dees-chart-log>
167
274
  </div>
168
275
  </dees-demowrapper>
169
276
  `;
170
- };
277
+ };