diff --git a/package.json b/package.json
index f663e58..aa5e660 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,7 @@
"dependencies": {
"@design.estate/dees-domtools": "^2.1.1",
"@design.estate/dees-element": "^2.0.42",
- "@design.estate/dees-wcctools": "^1.0.90",
+ "@design.estate/dees-wcctools": "^1.0.92",
"@fortawesome/fontawesome-svg-core": "^6.7.2",
"@fortawesome/free-brands-svg-icons": "^6.7.2",
"@fortawesome/free-regular-svg-icons": "^6.7.2",
@@ -30,7 +30,7 @@
"apexcharts": "^4.7.0",
"highlight.js": "11.11.1",
"ibantools": "^4.5.1",
- "lucide": "^0.514.0",
+ "lucide": "^0.515.0",
"monaco-editor": "^0.52.2",
"pdfjs-dist": "^4.10.38",
"xterm": "^5.3.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index db91c1a..9a20650 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -15,8 +15,8 @@ importers:
specifier: ^2.0.42
version: 2.0.42
'@design.estate/dees-wcctools':
- specifier: ^1.0.90
- version: 1.0.90
+ specifier: ^1.0.92
+ version: 1.0.92
'@fortawesome/fontawesome-svg-core':
specifier: ^6.7.2
version: 6.7.2
@@ -54,8 +54,8 @@ importers:
specifier: ^4.5.1
version: 4.5.1
lucide:
- specifier: ^0.514.0
- version: 0.514.0
+ specifier: ^0.515.0
+ version: 0.515.0
monaco-editor:
specifier: ^0.52.2
version: 0.52.2
@@ -305,8 +305,8 @@ packages:
'@design.estate/dees-element@2.0.42':
resolution: {integrity: sha512-1PzHP6q/PtSiu4P0nCxjSeHtRHn62zoSouMy8JFW2h29FT/CSDVaTUAUqYqnvwE/U98aLNivWTmerZitDF7kBQ==}
- '@design.estate/dees-wcctools@1.0.90':
- resolution: {integrity: sha512-EHYWHiOe+P261e9fBbOBmkD7lIsOpD+tu4VZQr20oc8vhsFjeUGJqYeBm/Ghwg+Gck/dto+K9zyJNIyQ642cEw==}
+ '@design.estate/dees-wcctools@1.0.92':
+ resolution: {integrity: sha512-E4Hnxvvzy2ivJzPHzWL2dmJtBtAD+stnEG7uQ0usQM6NVnarIGPI9PflGSspM75nnA/HKi+lpsqRgp1DtbPqTQ==}
'@esbuild/aix-ppc64@0.24.2':
resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==}
@@ -3153,8 +3153,8 @@ packages:
resolution: {integrity: sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==}
engines: {node: '>=16.14'}
- lucide@0.514.0:
- resolution: {integrity: sha512-GQ3Rzj1qFANBvTmhe8RM3vR491RGnSjHsivA5wSuEj5taLwH1Sv4N7n6ae3ENGsYRzdrkVXZo4ieUbD1WOXmoA==}
+ lucide@0.515.0:
+ resolution: {integrity: sha512-n7tFK3R1HdsxwM5rMOa6twAi/4RGZCysc7dmk7Cr2GiOUcnHX0+MX9xw3xynpbekXCgS4+o9HeIWhBl3rZHIAA==}
make-dir@3.1.0:
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
@@ -5176,7 +5176,7 @@ snapshots:
- supports-color
- vue
- '@design.estate/dees-wcctools@1.0.90':
+ '@design.estate/dees-wcctools@1.0.92':
dependencies:
'@design.estate/dees-domtools': 2.3.2
'@design.estate/dees-element': 2.0.42
@@ -8846,7 +8846,7 @@ snapshots:
lru-cache@8.0.5: {}
- lucide@0.514.0: {}
+ lucide@0.515.0: {}
make-dir@3.1.0:
dependencies:
diff --git a/readme.hints.md b/readme.hints.md
index 0d83bdc..85438f8 100644
--- a/readme.hints.md
+++ b/readme.hints.md
@@ -25,6 +25,7 @@
- Methods:
- `updateSeries()`: Update chart data
- `appendData()`: Add new data points to existing series
+- Demo uses global reference to access chart element (window.__demoChartElement)
### dees-chart-log
- Server log viewer component (not a chart despite the name)
@@ -40,4 +41,21 @@
- Light/dark theme support
- Demo includes realistic server log simulation
- Note: In demos, buttons use `@clicked` event (not `@click`)
-- Demo uses global reference to access log element (window.__demoLogElement)
\ No newline at end of file
+- Demo uses global reference to access log element (window.__demoLogElement)
+
+## UI Components
+
+### dees-button-group
+- Groups multiple buttons together with a unified background
+- Properties:
+ - `label`: Optional label text displayed before the buttons
+ - `direction`: 'horizontal' | 'vertical' layout
+- Features:
+ - Light/dark theme support
+ - Flexible layout with proper spacing
+ - Works with all button types (normal, highlighted, success, danger)
+- Use cases:
+ - View mode selectors
+ - Action grouping
+ - Navigation options
+ - Filter controls
\ No newline at end of file
diff --git a/ts_web/elements/dees-button-group.demo.ts b/ts_web/elements/dees-button-group.demo.ts
new file mode 100644
index 0000000..fd6e3b4
--- /dev/null
+++ b/ts_web/elements/dees-button-group.demo.ts
@@ -0,0 +1,114 @@
+import { html, css } from '@design.estate/dees-element';
+
+export const demoFunc = () => {
+ return html`
+
+
+
+
Basic Button Groups
+
Button groups without labels for simple grouping
+
+
+ Option 1
+ Option 2
+ Option 3
+
+
+
+
+
Labeled Button Groups
+
Button groups with descriptive labels
+
+
+ Grid
+ List
+ Cards
+
+
+
+
+
Multiple Groups
+
Multiple button groups used together
+
+
+
+ System
+ Network
+ Sales
+
+
+
+ 1H
+ 24H
+ 7D
+ 30D
+
+
+
+ Refresh
+ Export
+
+
+
+
+
+
Vertical Button Groups
+
Button groups with vertical layout
+
+
+
+ Dashboard
+ Analytics
+ Reports
+ Settings
+
+
+
+ Add Item
+ Edit Item
+ Delete Item
+
+
+
+
+
+
Mixed Button Types
+
Different button types within groups
+
+
+ Active
+ Pending
+ Inactive
+
+
+
+ `;
+};
\ No newline at end of file
diff --git a/ts_web/elements/dees-button-group.ts b/ts_web/elements/dees-button-group.ts
new file mode 100644
index 0000000..c8238f8
--- /dev/null
+++ b/ts_web/elements/dees-button-group.ts
@@ -0,0 +1,83 @@
+import {
+ DeesElement,
+ css,
+ cssManager,
+ customElement,
+ html,
+ property,
+ type TemplateResult,
+} from '@design.estate/dees-element';
+
+import * as domtools from '@design.estate/dees-domtools';
+import { demoFunc } from './dees-button-group.demo.js';
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'dees-button-group': DeesButtonGroup;
+ }
+}
+
+@customElement('dees-button-group')
+export class DeesButtonGroup extends DeesElement {
+ public static demo = demoFunc;
+
+ @property()
+ public label: string = '';
+
+ @property()
+ public direction: 'horizontal' | 'vertical' = 'horizontal';
+
+ constructor() {
+ super();
+ domtools.elementBasic.setup();
+ }
+
+ public static styles = [
+ cssManager.defaultStyles,
+ css`
+ :host {
+ display: inline-block;
+ }
+
+ .button-group {
+ display: flex;
+ gap: 8px;
+ align-items: center;
+ padding: 8px;
+ background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.05)', 'rgba(255, 255, 255, 0.05)')};
+ border-radius: 6px;
+ }
+
+ .button-group.vertical {
+ flex-direction: column;
+ align-items: stretch;
+ }
+
+ .label {
+ color: ${cssManager.bdTheme('#666', '#999')};
+ font-size: 12px;
+ font-family: 'Geist Sans', sans-serif;
+ margin-right: 8px;
+ white-space: nowrap;
+ }
+
+ .button-group.vertical .label {
+ margin-right: 0;
+ margin-bottom: 8px;
+ }
+
+ ::slotted(*) {
+ margin: 0 !important;
+ }
+ `,
+ ];
+
+ public render(): TemplateResult {
+ return html`
+
+ ${this.label ? html`${this.label}` : ''}
+
+
+ `;
+ }
+}
\ No newline at end of file
diff --git a/ts_web/elements/dees-chart-area.demo.ts b/ts_web/elements/dees-chart-area.demo.ts
index 34f9fef..35a4c49 100644
--- a/ts_web/elements/dees-chart-area.demo.ts
+++ b/ts_web/elements/dees-chart-area.demo.ts
@@ -1,18 +1,11 @@
import { html, css } from '@design.estate/dees-element';
import type { DeesChartArea } from './dees-chart-area.js';
+import '@design.estate/dees-wcctools';
export const demoFunc = () => {
let chartElement: DeesChartArea;
let intervalId: number;
let currentDataset = 'system';
-
- // Get element reference after render
- setTimeout(() => {
- const charts = document.querySelectorAll('dees-chart-area');
- if (charts.length > 0) {
- chartElement = charts[charts.length - 1] as DeesChartArea;
- }
- }, 100);
// Y-axis formatters for different datasets
const formatters = {
@@ -111,11 +104,15 @@ export const demoFunc = () => {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
+ // Get chart element
+ const getChartElement = () => {
+ return chartElement;
+ };
+
// Add real-time data
const addRealtimeData = () => {
- if (!chartElement) return;
-
- const dataset = datasets[currentDataset];
+ const chart = getChartElement();
+ if (!chart) return;
const newTimestamp = new Date().toISOString();
// Generate new data points based on dataset type
@@ -133,29 +130,48 @@ export const demoFunc = () => {
];
}
- // Keep only last 10 data points
- const currentSeries = chartElement.series.map((series, index) => ({
+ // Keep only last 20 data points and update without animation
+ const currentSeries = chart.series.map((series, index) => ({
...series,
- data: [...series.data.slice(-9), ...(newData[index] || [])],
+ data: [...series.data.slice(-19), ...(newData[index] || [])],
}));
- chartElement.series = currentSeries;
+ // Update without animation for smoother real-time updates
+ chart.updateSeries(currentSeries, false);
};
// Switch dataset
const switchDataset = (name: string) => {
currentDataset = name;
- if (chartElement) {
- const dataset = datasets[name];
- chartElement.label = dataset.label;
- chartElement.series = dataset.series;
- chartElement.yAxisFormatter = formatters[name];
- }
+
+ const updateChart = () => {
+ const chart = getChartElement();
+ if (chart) {
+ const dataset = datasets[name];
+ chart.label = dataset.label;
+ chart.series = dataset.series;
+ chart.yAxisFormatter = formatters[name];
+ }
+ };
+
+ updateChart();
};
// Start/stop real-time updates
const startRealtime = () => {
if (!intervalId && (currentDataset === 'system' || currentDataset === 'network')) {
+ const chart = getChartElement();
+ if (chart) {
+ // Disable animations for real-time mode
+ chart.updateOptions({
+ chart: {
+ animations: {
+ enabled: false
+ }
+ }
+ }, false, false);
+ }
+
intervalId = window.setInterval(() => addRealtimeData(), 2000);
}
};
@@ -164,29 +180,52 @@ export const demoFunc = () => {
if (intervalId) {
window.clearInterval(intervalId);
intervalId = null;
+
+ const chart = getChartElement();
+ if (chart) {
+ // Re-enable animations when stopping real-time
+ chart.updateOptions({
+ chart: {
+ animations: {
+ enabled: true,
+ speed: 400,
+ animateGradually: {
+ enabled: true,
+ delay: 150
+ }
+ }
+ }
+ }, false, true);
+ }
}
};
// Randomize current data
const randomizeData = () => {
- if (!chartElement) return;
+ const chart = getChartElement();
+ if (!chart) return;
- const currentSeries = chartElement.series.map(series => ({
+ const currentSeries = chart.series.map(series => ({
...series,
- data: series.data.map(point => ({
+ data: series.data.map((point: any) => ({
...point,
y: typeof point.y === 'number'
- ? point.y * (0.8 + Math.random() * 0.4) // +/- 20% variation
+ ? Math.round(point.y * (0.8 + Math.random() * 0.4)) // +/- 20% variation
: point.y,
})),
}));
- chartElement.series = currentSeries;
+ // Update with animation for single updates
+ chart.updateSeries(currentSeries, true);
};
return html`
-
-
- Dataset:
+
switchDataset('system')}
type=${currentDataset === 'system' ? 'highlighted' : 'normal'}
@@ -252,19 +274,17 @@ export const demoFunc = () => {
@clicked=${() => switchDataset('sales')}
type=${currentDataset === 'sales' ? 'highlighted' : 'normal'}
>Sales Data
-
+
-
- Real-time:
+
startRealtime()}>Start Live
stopRealtime()}>Stop Live
-
+
-
- Actions:
+
randomizeData()}>Randomize Values
addRealtimeData()}>Add Point
-
+
@@ -280,6 +300,7 @@ export const demoFunc = () => {
Chart updates every 2 seconds when live mode is active •
Try switching datasets and randomizing values
-
+
+
`;
};
diff --git a/ts_web/elements/dees-chart-area.ts b/ts_web/elements/dees-chart-area.ts
index 56b0e74..c9f97ca 100644
--- a/ts_web/elements/dees-chart-area.ts
+++ b/ts_web/elements/dees-chart-area.ts
@@ -6,7 +6,6 @@ import {
html,
property,
state,
- type CSSResult,
type TemplateResult,
} from '@design.estate/dees-element';
@@ -35,7 +34,7 @@ export class DeesChartArea extends DeesElement {
@property({ type: Array })
public series: ApexAxisChartSeries = [];
- @property({ type: Function })
+ @property({ attribute: false })
public yAxisFormatter: (value: number) => string = (val) => `${val} Mbps`;
private resizeObserver: ResizeObserver;
@@ -187,9 +186,13 @@ export class DeesChartArea extends DeesElement {
enabled: true,
speed: 400,
animateGradually: {
- enabled: true,
- delay: 150
+ enabled: false, // Disable gradual animation for cleaner updates
+ delay: 0
},
+ dynamicAnimation: {
+ enabled: true,
+ speed: 350
+ }
},
},
dataLabels: {
@@ -312,24 +315,29 @@ export class DeesChartArea extends DeesElement {
}
}
- public async updateSeries(newSeries: ApexAxisChartSeries) {
+ public async updateSeries(newSeries: ApexAxisChartSeries, animate: boolean = true) {
if (!this.chart) {
return;
}
- await this.chart.updateSeries(newSeries, true);
+ this.chart.updateSeries(newSeries, animate);
}
- public async appendData(seriesIndex: number, newData: any[]) {
+ public async appendData(newData: { data: any[] }[]) {
if (!this.chart) {
return;
}
- const currentSeries = [...this.series];
- if (currentSeries[seriesIndex]) {
- currentSeries[seriesIndex].data = [...currentSeries[seriesIndex].data, ...newData];
- await this.updateSeries(currentSeries);
+ // Use ApexCharts' appendData method for smoother real-time updates
+ await this.chart.appendData(newData);
+ }
+
+ public async updateOptions(options: ApexCharts.ApexOptions, redrawPaths?: boolean, animate?: boolean) {
+ if (!this.chart) {
+ return;
}
+
+ return this.chart.updateOptions(options, redrawPaths, animate);
}
public async resizeChart() {
diff --git a/ts_web/elements/dees-chart-log.demo.ts b/ts_web/elements/dees-chart-log.demo.ts
index 2fa968a..5ccdc37 100644
--- a/ts_web/elements/dees-chart-log.demo.ts
+++ b/ts_web/elements/dees-chart-log.demo.ts
@@ -1,7 +1,10 @@
import { html } from '@design.estate/dees-element';
+import type { DeesChartLog } from './dees-chart-log.js';
+import '@design.estate/dees-wcctools';
export const demoFunc = () => {
let intervalId: number;
+ let logElement: DeesChartLog;
const serverSources = ['Server', 'Database', 'API', 'Auth', 'Cache', 'Queue', 'WebSocket', 'Scheduler'];
@@ -44,7 +47,6 @@ export const demoFunc = () => {
};
const generateRandomLog = () => {
- const logElement = (window as any).__demoLogElement;
if (!logElement) {
console.warn('Log element not ready yet');
return;
@@ -119,7 +121,11 @@ export const demoFunc = () => {
return html`
-