Compare commits

...

21 Commits

Author SHA1 Message Date
9bfbfcbb95 v3.55.4
Some checks failed
Default (tags) / security (push) Failing after 1s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-04-04 11:25:19 +00:00
3505c390d8 fix(chart): align ECharts components with theme tokens and load the full ECharts ESM bundle 2026-04-04 11:25:19 +00:00
ff32470d8a update 2026-04-04 11:05:01 +00:00
4dba14060e fix(dees-statsgrid): update styles to use shared theme CSS variables 2026-04-04 10:53:53 +00:00
31d728ec49 v3.55.3
Some checks failed
Default (tags) / security (push) Failing after 0s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-04-04 10:50:19 +00:00
ca290d1267 fix(theme): align component styles with shared theme CSS variables 2026-04-04 10:50:19 +00:00
dcef6faa66 v3.55.2
Some checks failed
Default (tags) / security (push) Failing after 1s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-04-04 09:42:44 +00:00
fe9eb21fe0 fix(dees-simple-appdash,dees-simple-login): migrate app dashboard and login styles to shared theme CSS variables 2026-04-04 09:42:44 +00:00
f352314971 v3.55.1
Some checks failed
Default (tags) / security (push) Failing after 0s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-04-04 09:37:06 +00:00
130ca68471 fix(appui): replace hardcoded app UI theme colors with shared dees CSS variables 2026-04-04 09:37:06 +00:00
cdde25d0b4 v3.55.0
Some checks failed
Default (tags) / security (push) Failing after 0s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-04-04 09:23:11 +00:00
231c57b596 feat(theme): centralize theme CSS tokens in theme defaults and add missing interactive color variables 2026-04-04 09:23:11 +00:00
167dcb2b0a feat(theme): enhance color definitions and add warm text and badge colors 2026-04-04 09:12:54 +00:00
fdccdcdf73 feat(dees-simple-appdash): update color themes for improved UI consistency 2026-04-04 08:38:54 +00:00
bee1cafdb4 v3.54.0
Some checks failed
Default (tags) / security (push) Failing after 1s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-04-04 08:13:56 +00:00
42b40da67c feat(media): rename media tile components to thumbnail components and add shared thumbnail base exports 2026-04-04 08:13:56 +00:00
10cd1e2755 v3.53.0
Some checks failed
Default (tags) / security (push) Failing after 0s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-04-03 20:27:50 +00:00
68ed024aaa feat(dees-pdf-viewer): add configurable sidebar position support 2026-04-03 20:27:50 +00:00
6b6ccd0e3c v3.52.5
Some checks failed
Default (tags) / security (push) Failing after 1s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-04-03 19:58:51 +00:00
d933c47b49 fix(dees-pdf-viewer): add top scroll offset when navigating to a page in the PDF viewer 2026-04-03 19:58:51 +00:00
3defbba5fd feat(pdf-viewer): enhance PDF viewer with file size display and footer layout 2026-04-03 19:50:46 +00:00
80 changed files with 2227 additions and 495 deletions

View File

@@ -1,5 +1,58 @@
# Changelog
## 2026-04-04 - 3.55.4 - fix(chart)
align ECharts components with theme tokens and load the full ECharts ESM bundle
- replace hardcoded chart colors with centralized themeDefaults-based ECharts theme helpers across bar, donut, gauge, and radar components
- improve donut label styling to use theme-aware text colors
- switch CDN loading to the pre-built echarts.esm.min.js bundle so all chart types and components are available
## 2026-04-04 - 3.55.3 - fix(theme)
align component styles with shared theme CSS variables
- replace hardcoded bdTheme color usages across chart, dataview, input, layout, modal, media, simple, and workspace components with shared --dees-* theme tokens
- add themeDefaultStyles to components and style modules that were not yet inheriting the shared theme defaults
- standardize hover, border, background, text, and scrollbar colors for more consistent theming across the catalog
## 2026-04-04 - 3.55.2 - fix(dees-simple-appdash,dees-simple-login)
migrate app dashboard and login styles to shared theme CSS variables
- Replaces hardcoded bdTheme color values with --dees-* design tokens across dashboard and login components
- Aligns backgrounds, borders, text, hover, active, and scrollbar colors with the shared theming system
## 2026-04-04 - 3.55.1 - fix(appui)
replace hardcoded app UI theme colors with shared dees CSS variables
- Standardizes app UI component styling on shared --dees-* theme tokens across app bar, menus, tabs, main content, and bottom bar
- Removes remaining hardcoded light/dark color values in favor of centralized background, border, text, badge, tooltip, scrollbar, and accent variables
## 2026-04-04 - 3.55.0 - feat(theme)
centralize theme CSS tokens in theme defaults and add missing interactive color variables
- Refactors theme CSS variables to derive light and dark values from the shared themeDefaults token map instead of hardcoded color literals.
- Adjusts dark background token values so secondary and tertiary surfaces align more consistently with the dark UI palette.
- Adds new theme variables for interactive states, focus ring, tooltip, link, code, selection, and scrollbar styling.
## 2026-04-04 - 3.54.0 - feat(media)
rename media tile components to thumbnail components and add shared thumbnail base exports
- Replaces dees-tile-* media component exports and implementations with dees-thumbnail-* counterparts for audio, image, video, note, folder, and pdf previews.
- Introduces a shared DeesThumbnailBase and shared thumbnail styles for consistent sizing, hover overlays, loading states, error states, and lazy-loading behavior.
- Updates the media index to export the new thumbnail component modules.
- Includes a small layout cleanup in dees-dataview-codebox by removing forced full-height and absolute grid positioning.
## 2026-04-03 - 3.53.0 - feat(dees-pdf-viewer)
add configurable sidebar position support
- introduces a sidebarPosition property with left and right options
- updates viewer layout and footer alignment when the sidebar is displayed on the right
## 2026-04-03 - 3.52.5 - fix(dees-pdf-viewer)
add top scroll offset when navigating to a page in the PDF viewer
- Subtracts 16px from the calculated scroll target so the selected page is not flush against the top edge of the viewer.
- Improves page navigation positioning in the dees-pdf-viewer component.
## 2026-04-03 - 3.52.4 - fix(appui-maincontent)
adjust main content background theme colors

View File

@@ -1,6 +1,6 @@
{
"name": "@design.estate/dees-catalog",
"version": "3.52.4",
"version": "3.55.4",
"private": false,
"description": "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.",
"main": "dist_ts_web/index.js",
@@ -34,6 +34,7 @@
"@tiptap/extension-underline": "^2.23.0",
"@tiptap/starter-kit": "^2.23.0",
"@tsclass/tsclass": "^9.5.0",
"echarts": "^5.6.0",
"lightweight-charts": "^5.1.0",
"highlight.js": "11.11.1",
"ibantools": "^4.5.1",

23
pnpm-lock.yaml generated
View File

@@ -62,6 +62,9 @@ importers:
'@tsclass/tsclass':
specifier: ^9.5.0
version: 9.5.0
echarts:
specifier: ^5.6.0
version: 5.6.0
highlight.js:
specifier: 11.11.1
version: 11.11.1
@@ -2534,6 +2537,9 @@ packages:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'}
echarts@5.6.0:
resolution: {integrity: sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==}
emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
@@ -3936,6 +3942,9 @@ packages:
tslib@1.14.1:
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
tslib@2.3.0:
resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
@@ -4149,6 +4158,9 @@ packages:
zod@3.25.76:
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
zrender@5.6.1:
resolution: {integrity: sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==}
zwitch@2.0.4:
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
@@ -7671,6 +7683,11 @@ snapshots:
es-errors: 1.3.0
gopd: 1.2.0
echarts@5.6.0:
dependencies:
tslib: 2.3.0
zrender: 5.6.1
emoji-regex@8.0.0: {}
end-of-stream@1.4.5:
@@ -9510,6 +9527,8 @@ snapshots:
tslib@1.14.1: {}
tslib@2.3.0: {}
tslib@2.8.1: {}
tsx@4.21.0:
@@ -9699,4 +9718,8 @@ snapshots:
zod@3.25.76: {}
zrender@5.6.1:
dependencies:
tslib: 2.3.0
zwitch@2.0.4: {}

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@design.estate/dees-catalog',
version: '3.52.4',
version: '3.55.4',
description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
}

View File

@@ -12,8 +12,8 @@ export const appuiAppbarStyles = [
position: relative;
width: 100%;
height: var(--appbar-height);
border-bottom: 1px solid ${cssManager.bdTheme('#e0e0e0', '#202020')};
background: ${cssManager.bdTheme('#ffffff', '#000000')};
border-bottom: 1px solid var(--dees-color-border-default);
background: var(--dees-color-bg-primary);
color: ${cssManager.bdTheme('#00000080', '#ffffff80')};
font-size: var(--appbar-font-size);
display: grid;
@@ -78,8 +78,8 @@ export const appuiAppbarStyles = [
top: 100%;
left: 0;
min-width: 200px;
background: ${cssManager.bdTheme('#ffffff', '#000000')};
border: 1px solid ${cssManager.bdTheme('#e0e0e0', '#202020')};
background: var(--dees-color-bg-primary);
border: 1px solid var(--dees-color-border-default);
border-radius: 4px;
box-shadow: ${cssManager.bdTheme('0 4px 12px rgba(0, 0, 0, 0.15)', '0 4px 12px rgba(0, 0, 0, 0.3)')};
margin-top: 4px;
@@ -112,7 +112,7 @@ export const appuiAppbarStyles = [
.dropdown-divider {
height: 1px;
background: ${cssManager.bdTheme('#e0e0e0', '#202020')};
background: var(--dees-color-border-default);
margin: 4px 0;
}
@@ -215,7 +215,7 @@ export const appuiAppbarStyles = [
width: 8px;
height: 8px;
border-radius: 50%;
border: 2px solid ${cssManager.bdTheme('#ffffff', '#000000')};
border: 2px solid var(--dees-color-bg-primary);
}
.user-status.online {

View File

@@ -52,10 +52,10 @@ export class DeesAppuiBottombar extends DeesElement implements IBottomBarAPI {
align-items: center;
padding: 0 8px;
gap: 4px;
background: ${cssManager.bdTheme('hsl(0 0% 94%)', 'hsl(0 0% 6%)')};
border-top: 1px solid ${cssManager.bdTheme('hsl(0 0% 85%)', 'hsl(0 0% 15%)')};
background: var(--dees-color-bg-tertiary);
border-top: 1px solid var(--dees-color-border-default);
font-size: 11px;
color: ${cssManager.bdTheme('hsl(0 0% 40%)', 'hsl(0 0% 60%)')};
color: var(--dees-color-text-muted);
}
.widget {
@@ -70,8 +70,8 @@ export class DeesAppuiBottombar extends DeesElement implements IBottomBarAPI {
}
.widget:hover {
background: ${cssManager.bdTheme('hsl(0 0% 88%)', 'hsl(0 0% 12%)')};
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 80%)')};
background: var(--dees-color-hover);
color: var(--dees-color-text-secondary);
}
.widget dees-icon {
@@ -81,7 +81,7 @@ export class DeesAppuiBottombar extends DeesElement implements IBottomBarAPI {
.widget-separator {
width: 1px;
height: 14px;
background: ${cssManager.bdTheme('hsl(0 0% 80%)', 'hsl(0 0% 20%)')};
background: var(--dees-color-border-strong);
margin: 0 4px;
}
@@ -124,12 +124,12 @@ export class DeesAppuiBottombar extends DeesElement implements IBottomBarAPI {
border-radius: 3px;
cursor: pointer;
transition: background 0.15s ease;
color: ${cssManager.bdTheme('hsl(0 0% 40%)', 'hsl(0 0% 60%)')};
color: var(--dees-color-text-muted);
}
.action-button:hover {
background: ${cssManager.bdTheme('hsl(0 0% 88%)', 'hsl(0 0% 12%)')};
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 80%)')};
background: var(--dees-color-hover);
color: var(--dees-color-text-secondary);
}
.action-button.disabled {
@@ -139,7 +139,7 @@ export class DeesAppuiBottombar extends DeesElement implements IBottomBarAPI {
.action-button.disabled:hover {
background: transparent;
color: ${cssManager.bdTheme('hsl(0 0% 40%)', 'hsl(0 0% 60%)')};
color: var(--dees-color-text-muted);
}
`,
];

View File

@@ -63,14 +63,13 @@ export class DeesAppuiMaincontent extends DeesElement {
themeDefaultStyles,
cssManager.defaultStyles,
css`
/* TODO: Migrate hardcoded values to --dees-* CSS variables */
:host {
color: ${cssManager.bdTheme('#333', '#fff')};
color: var(--dees-color-text-secondary);
display: grid;
grid-template-rows: auto 1fr;
width: 100%;
height: 100%;
background: ${cssManager.bdTheme('#fafafa', '#0a0a0a')};
background: var(--dees-color-bg-secondary);
}
.maincontainer {

View File

@@ -55,28 +55,27 @@ export class DeesAppuiMainmenu extends DeesElement {
themeDefaultStyles,
cssManager.defaultStyles,
css`
/* TODO: Migrate hardcoded values to --dees-* CSS variables */
:host {
--menu-width-expanded: 200px;
--menu-width-collapsed: 56px;
--tooltip-bg: ${cssManager.bdTheme('#18181b', '#fafafa')};
--tooltip-fg: ${cssManager.bdTheme('#fafafa', '#18181b')};
--tooltip-bg: var(--dees-color-tooltip-bg);
--tooltip-fg: var(--dees-color-tooltip-fg);
position: relative;
display: block;
height: 100%;
}
.mainContainer {
color: ${cssManager.bdTheme('#666', '#ccc')};
color: var(--dees-color-text-secondary);
z-index: ${zIndexLayers.fixed.appBar};
display: flex;
flex-direction: column;
position: relative;
width: var(--menu-width-expanded);
height: 100%;
background: ${cssManager.bdTheme('#fafafa', '#0a0a0a')};
background: var(--dees-color-bg-secondary);
user-select: none;
border-right: 1px solid ${cssManager.bdTheme('#e5e5e5', '#1a1a1a')};
border-right: 1px solid var(--dees-color-border-subtle);
font-family: 'Geist Sans', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
transition: width 0.25s ease;
}
@@ -94,23 +93,23 @@ export class DeesAppuiMainmenu extends DeesElement {
width: 24px;
height: 24px;
border-radius: 50%;
background: ${cssManager.bdTheme('#ffffff', '#27272a')};
border: 1px solid ${cssManager.bdTheme('#e5e5e5', '#3f3f46')};
background: var(--dees-color-bg-primary);
border: 1px solid var(--dees-color-border-strong);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
cursor: pointer;
z-index: 10;
display: flex;
align-items: center;
justify-content: center;
color: ${cssManager.bdTheme('#737373', '#a1a1aa')};
color: var(--dees-color-text-muted);
opacity: 0;
transition: opacity 0.2s ease, background 0.15s ease;
padding: 0;
}
.collapse-toggle:hover {
background: ${cssManager.bdTheme('#f4f4f5', '#3f3f46')};
color: ${cssManager.bdTheme('#0a0a0a', '#fafafa')};
background: var(--dees-color-bg-tertiary);
color: var(--dees-color-text-primary);
}
:host(:hover) .collapse-toggle {
@@ -128,14 +127,14 @@ export class DeesAppuiMainmenu extends DeesElement {
gap: 10px;
height: 48px;
padding: 0 14px;
border-bottom: 1px solid ${cssManager.bdTheme('#e5e5e5', '#1a1a1a')};
border-bottom: 1px solid var(--dees-color-border-subtle);
flex-shrink: 0;
box-sizing: border-box;
}
.logoSection .logoIcon {
font-size: 22px;
color: ${cssManager.bdTheme('#0a0a0a', '#fafafa')};
color: var(--dees-color-text-primary);
flex-shrink: 0;
}
@@ -143,7 +142,7 @@ export class DeesAppuiMainmenu extends DeesElement {
flex: 1;
font-size: 15px;
font-weight: 600;
color: ${cssManager.bdTheme('#0a0a0a', '#fafafa')};
color: var(--dees-color-text-primary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@@ -178,12 +177,12 @@ export class DeesAppuiMainmenu extends DeesElement {
}
.menuSection::-webkit-scrollbar-thumb {
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.15)', 'rgba(255, 255, 255, 0.15)')};
background: var(--dees-color-scrollbar-thumb);
border-radius: 3px;
}
.menuSection::-webkit-scrollbar-thumb:hover {
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.25)', 'rgba(255, 255, 255, 0.25)')};
background: var(--dees-color-scrollbar-thumb-hover);
}
/* Menu Group */
@@ -200,7 +199,7 @@ export class DeesAppuiMainmenu extends DeesElement {
padding: 8px 12px 6px;
font-size: 11px;
font-weight: 600;
color: ${cssManager.bdTheme('#737373', '#737373')};
color: var(--dees-color-text-muted);
text-transform: uppercase;
letter-spacing: 0.5px;
white-space: nowrap;
@@ -238,21 +237,21 @@ export class DeesAppuiMainmenu extends DeesElement {
border-radius: 6px;
cursor: pointer;
transition: all 0.15s ease;
color: ${cssManager.bdTheme('#525252', '#a3a3a3')};
color: var(--dees-color-text-secondary);
}
.tab:hover {
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.04)', 'rgba(255, 255, 255, 0.06)')};
background: var(--dees-color-hover);
color: ${cssManager.bdTheme('#262626', '#e5e5e5')};
}
.tab:active {
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.06)', 'rgba(255, 255, 255, 0.08)')};
background: var(--dees-color-active);
}
.tab.selectedTab {
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.06)', 'rgba(255, 255, 255, 0.08)')};
color: ${cssManager.bdTheme('#0a0a0a', '#fafafa')};
background: var(--dees-color-active);
color: var(--dees-color-text-primary);
}
.tab.selectedTab::before {
@@ -263,7 +262,7 @@ export class DeesAppuiMainmenu extends DeesElement {
transform: translateY(-50%);
width: 3px;
height: 16px;
background: ${cssManager.bdTheme('#0a0a0a', '#fafafa')};
background: var(--dees-color-text-primary);
border-radius: 0 2px 2px 0;
}
@@ -353,23 +352,23 @@ export class DeesAppuiMainmenu extends DeesElement {
}
.badge.default {
background: ${cssManager.bdTheme('#f4f4f5', '#27272a')};
color: ${cssManager.bdTheme('#3f3f46', '#a1a1aa')};
background: var(--dees-color-badge-default-bg);
color: var(--dees-color-badge-default-fg);
}
.badge.success {
background: ${cssManager.bdTheme('#dcfce7', '#14532d')};
color: ${cssManager.bdTheme('#166534', '#4ade80')};
background: var(--dees-color-badge-success-bg);
color: var(--dees-color-badge-success-fg);
}
.badge.warning {
background: ${cssManager.bdTheme('#fef3c7', '#451a03')};
color: ${cssManager.bdTheme('#92400e', '#fbbf24')};
background: var(--dees-color-badge-warning-bg);
color: var(--dees-color-badge-warning-fg);
}
.badge.error {
background: ${cssManager.bdTheme('#fee2e2', '#450a0a')};
color: ${cssManager.bdTheme('#991b1b', '#f87171')};
background: var(--dees-color-badge-error-bg);
color: var(--dees-color-badge-error-fg);
}
:host([collapsed]) .badge {
@@ -380,7 +379,7 @@ export class DeesAppuiMainmenu extends DeesElement {
.bottomSection {
flex-shrink: 0;
padding: 8px;
border-top: 1px solid ${cssManager.bdTheme('#e5e5e5', '#1a1a1a')};
border-top: 1px solid var(--dees-color-border-subtle);
display: flex;
flex-direction: column;
gap: 2px;

View File

@@ -73,30 +73,29 @@ export class DeesAppuiSecondarymenu extends DeesElement {
themeDefaultStyles,
cssManager.defaultStyles,
css`
/* TODO: Migrate hardcoded values to --dees-* CSS variables */
:host {
--sidebar-width-expanded: 240px;
--sidebar-width-collapsed: 56px;
--sidebar-bg: ${cssManager.bdTheme('#fafafa', '#0a0a0a')};
--sidebar-fg: ${cssManager.bdTheme('#525252', '#a3a3a3')};
--sidebar-fg-muted: ${cssManager.bdTheme('#737373', '#737373')};
--sidebar-fg-active: ${cssManager.bdTheme('#0a0a0a', '#fafafa')};
--sidebar-border: ${cssManager.bdTheme('#e5e5e5', '#1a1a1a')};
--sidebar-hover: ${cssManager.bdTheme('rgba(0, 0, 0, 0.04)', 'rgba(255, 255, 255, 0.06)')};
--sidebar-active: ${cssManager.bdTheme('rgba(0, 0, 0, 0.06)', 'rgba(255, 255, 255, 0.08)')};
--sidebar-accent: ${cssManager.bdTheme('#0a0a0a', '#fafafa')};
--tooltip-bg: ${cssManager.bdTheme('#18181b', '#fafafa')};
--tooltip-fg: ${cssManager.bdTheme('#fafafa', '#18181b')};
--sidebar-bg: var(--dees-color-bg-secondary);
--sidebar-fg: var(--dees-color-text-secondary);
--sidebar-fg-muted: var(--dees-color-text-muted);
--sidebar-fg-active: var(--dees-color-text-primary);
--sidebar-border: var(--dees-color-border-subtle);
--sidebar-hover: var(--dees-color-hover);
--sidebar-active: var(--dees-color-active);
--sidebar-accent: var(--dees-color-text-primary);
--tooltip-bg: var(--dees-color-tooltip-bg);
--tooltip-fg: var(--dees-color-tooltip-fg);
/* Badge colors */
--badge-default-bg: ${cssManager.bdTheme('#f4f4f5', '#27272a')};
--badge-default-fg: ${cssManager.bdTheme('#3f3f46', '#a1a1aa')};
--badge-success-bg: ${cssManager.bdTheme('#dcfce7', '#14532d')};
--badge-success-fg: ${cssManager.bdTheme('#166534', '#4ade80')};
--badge-warning-bg: ${cssManager.bdTheme('#fef3c7', '#451a03')};
--badge-warning-fg: ${cssManager.bdTheme('#92400e', '#fbbf24')};
--badge-error-bg: ${cssManager.bdTheme('#fee2e2', '#450a0a')};
--badge-error-fg: ${cssManager.bdTheme('#991b1b', '#f87171')};
--badge-default-bg: var(--dees-color-badge-default-bg);
--badge-default-fg: var(--dees-color-badge-default-fg);
--badge-success-bg: var(--dees-color-badge-success-bg);
--badge-success-fg: var(--dees-color-badge-success-fg);
--badge-warning-bg: var(--dees-color-badge-warning-bg);
--badge-warning-fg: var(--dees-color-badge-warning-fg);
--badge-error-bg: var(--dees-color-badge-error-bg);
--badge-error-fg: var(--dees-color-badge-error-fg);
/* Action colors */
--action-primary: ${cssManager.bdTheme('#2563eb', '#3b82f6')};
@@ -136,23 +135,23 @@ export class DeesAppuiSecondarymenu extends DeesElement {
width: 24px;
height: 24px;
border-radius: 50%;
background: ${cssManager.bdTheme('#ffffff', '#27272a')};
border: 1px solid ${cssManager.bdTheme('#e5e5e5', '#3f3f46')};
background: var(--dees-color-bg-primary);
border: 1px solid var(--dees-color-border-strong);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
cursor: pointer;
z-index: 10;
display: flex;
align-items: center;
justify-content: center;
color: ${cssManager.bdTheme('#737373', '#a1a1aa')};
color: var(--dees-color-text-muted);
opacity: 0;
transition: opacity 0.2s ease, background 0.15s ease;
padding: 0;
}
.collapse-toggle:hover {
background: ${cssManager.bdTheme('#f4f4f5', '#3f3f46')};
color: ${cssManager.bdTheme('#0a0a0a', '#fafafa')};
background: var(--dees-color-bg-tertiary);
color: var(--dees-color-text-primary);
}
:host(:hover) .collapse-toggle {
@@ -215,12 +214,12 @@ export class DeesAppuiSecondarymenu extends DeesElement {
}
.menuSection::-webkit-scrollbar-thumb {
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.15)', 'rgba(255, 255, 255, 0.15)')};
background: var(--dees-color-scrollbar-thumb);
border-radius: 3px;
}
.menuSection::-webkit-scrollbar-thumb:hover {
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.25)', 'rgba(255, 255, 255, 0.25)')};
background: var(--dees-color-scrollbar-thumb-hover);
}
/* Menu Group */
@@ -261,7 +260,7 @@ export class DeesAppuiSecondarymenu extends DeesElement {
gap: 8px;
font-size: 11px;
font-weight: 600;
color: ${cssManager.bdTheme('#78716c', '#b5a99a')};
color: var(--dees-color-text-warm);
text-transform: uppercase;
letter-spacing: 0.5px;
white-space: nowrap;
@@ -270,13 +269,13 @@ export class DeesAppuiSecondarymenu extends DeesElement {
.groupHeader .groupTitle dees-icon {
font-size: 16px;
color: ${cssManager.bdTheme('#78716c', '#b5a99a')};
color: var(--dees-color-text-warm);
}
.groupHeader .chevron {
font-size: 12px;
transition: transform 0.2s ease;
color: ${cssManager.bdTheme('#78716c', '#b5a99a')};
color: var(--dees-color-text-warm);
}
.groupHeader.collapsed .chevron {

View File

@@ -60,7 +60,6 @@ export class DeesAppuiTabs extends DeesElement {
themeDefaultStyles,
cssManager.defaultStyles,
css`
/* TODO: Migrate hardcoded values to --dees-* CSS variables */
:host {
display: block;
position: relative;
@@ -76,7 +75,7 @@ export class DeesAppuiTabs extends DeesElement {
.tabs-wrapper.horizontal-wrapper {
height: 48px;
border-bottom: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
border-bottom: 1px solid var(--dees-color-border-default);
box-sizing: border-box;
overflow: hidden;
display: flex;
@@ -133,13 +132,13 @@ export class DeesAppuiTabs extends DeesElement {
.tab-actions.left {
padding-left: 12px;
padding-right: 8px;
border-right: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
border-right: 1px solid var(--dees-color-border-default);
}
.tab-actions.right {
padding-right: 12px;
padding-left: 8px;
border-left: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
border-left: 1px solid var(--dees-color-border-default);
}
.tab-action-button {
@@ -152,17 +151,17 @@ export class DeesAppuiTabs extends DeesElement {
cursor: pointer;
transition: background 0.15s ease, color 0.15s ease;
background: transparent;
color: ${cssManager.bdTheme('#71717a', '#71717a')};
color: var(--dees-color-text-muted);
flex-shrink: 0;
}
.tab-action-button:hover {
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.06)', 'rgba(255, 255, 255, 0.06)')};
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
background: var(--dees-color-active);
color: var(--dees-color-text-primary);
}
.tab-action-button:active {
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.1)', 'rgba(255, 255, 255, 0.1)')};
background: var(--dees-color-pressed);
}
.tab-action-button.disabled {
@@ -172,7 +171,7 @@ export class DeesAppuiTabs extends DeesElement {
.tab-action-button.disabled:hover {
background: transparent;
color: ${cssManager.bdTheme('#71717a', '#71717a')};
color: var(--dees-color-text-muted);
}
.tab-action-button dees-icon {
@@ -237,12 +236,12 @@ export class DeesAppuiTabs extends DeesElement {
font-size: 14px;
gap: 2px;
position: relative;
background: ${cssManager.bdTheme('#f9fafb', '#18181b')};
background: var(--dees-color-bg-tertiary);
border-radius: 8px;
}
.tab {
color: ${cssManager.bdTheme('#71717a', '#71717a')};
color: var(--dees-color-text-muted);
white-space: nowrap;
cursor: pointer;
transition: color 0.15s ease;
@@ -270,7 +269,7 @@ export class DeesAppuiTabs extends DeesElement {
transform: translateY(-50%);
height: 20px;
width: 1px;
background: ${cssManager.bdTheme('#e5e7eb', '#27272a')};
background: var(--dees-color-border-default);
opacity: 0.5;
}
@@ -291,11 +290,11 @@ export class DeesAppuiTabs extends DeesElement {
}
.tab:hover {
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
color: var(--dees-color-text-primary);
}
.horizontal .tab:hover {
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.03)', 'rgba(255, 255, 255, 0.03)')};
background: var(--dees-color-hover);
}
.horizontal .tab:hover::after,
@@ -308,7 +307,7 @@ export class DeesAppuiTabs extends DeesElement {
}
.horizontal .tab.selectedTab {
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
color: var(--dees-color-text-primary);
}
.horizontal .tab.selectedTab::after,
@@ -317,7 +316,7 @@ export class DeesAppuiTabs extends DeesElement {
}
.vertical .tab.selectedTab {
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
color: var(--dees-color-text-primary);
}
.tab dees-icon {
@@ -337,7 +336,7 @@ export class DeesAppuiTabs extends DeesElement {
.tabs-wrapper .tabIndicator {
height: 3px;
bottom: 0;
background: ${cssManager.bdTheme('#3b82f6', '#3b82f6')};
background: var(--dees-color-accent-primary);
border-radius: 3px 3px 0 0;
z-index: 3;
}
@@ -350,7 +349,7 @@ export class DeesAppuiTabs extends DeesElement {
left: 8px;
right: 8px;
border-radius: 6px;
background: ${cssManager.bdTheme('#ffffff', '#27272a')};
background: var(--dees-color-bg-primary);
z-index: 1;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}
@@ -366,7 +365,7 @@ export class DeesAppuiTabs extends DeesElement {
margin-left: 8px;
opacity: 0.4;
transition: opacity 0.15s, background 0.15s;
color: ${cssManager.bdTheme('#71717a', '#71717a')};
color: var(--dees-color-text-muted);
}
.tab:hover .tab-close {
@@ -375,8 +374,8 @@ export class DeesAppuiTabs extends DeesElement {
.tab-close:hover {
opacity: 1;
background: ${cssManager.bdTheme('rgba(0,0,0,0.1)', 'rgba(255,255,255,0.1)')};
color: ${cssManager.bdTheme('#ef4444', '#f87171')};
background: var(--dees-color-pressed);
color: var(--dees-color-accent-error);
}
.tab.selectedTab .tab-close {

View File

@@ -184,12 +184,11 @@ export class DeesAppui extends DeesElement {
themeDefaultStyles,
cssManager.defaultStyles,
css`
/* TODO: Migrate hardcoded values to --dees-* CSS variables */
:host {
position: absolute;
height: 100%;
width: 100%;
background: ${cssManager.bdTheme('#f0f0f0', '#1a1a1a')};
background: var(--dees-color-bg-tertiary);
}
.maingrid {
position: absolute;

View File

@@ -1,13 +1,15 @@
import { css, cssManager } from '@design.estate/dees-element';
import { themeDefaultStyles } from '../../00theme.js';
export const chartAreaStyles = [
themeDefaultStyles,
cssManager.defaultStyles,
css`
:host {
display: block;
height: 400px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
color: ${cssManager.bdTheme('hsl(0 0% 3.9%)', 'hsl(0 0% 98%)')};
color: var(--dees-color-text-primary);
font-size: 14px;
}
dees-tile {
@@ -24,7 +26,7 @@ export const chartAreaStyles = [
font-size: 14px;
font-weight: 500;
letter-spacing: -0.01em;
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 63.9%)')};
color: var(--dees-color-text-secondary);
}
.expandBtn {
display: flex;
@@ -36,13 +38,13 @@ export const chartAreaStyles = [
border-radius: 4px;
background: transparent;
cursor: pointer;
color: ${cssManager.bdTheme('hsl(0 0% 55%)', 'hsl(0 0% 45%)')};
color: var(--dees-color-text-muted);
transition: all 0.15s ease;
padding: 0;
}
.expandBtn:hover {
background: ${cssManager.bdTheme('hsl(0 0% 93%)', 'hsl(0 0% 12%)')};
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 90%)')};
background: var(--dees-color-hover);
color: var(--dees-color-text-secondary);
}
.chartContainer {
position: absolute;
@@ -64,7 +66,7 @@ export const chartAreaStyles = [
}
.statsSeries + .statsSeries {
padding-left: 24px;
border-left: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
border-left: 1px solid var(--dees-color-border-default);
}
.statsColor {
width: 8px;
@@ -75,15 +77,15 @@ export const chartAreaStyles = [
.statsName {
font-weight: 500;
font-size: 11px;
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 80%)')};
color: var(--dees-color-text-secondary);
margin-right: 4px;
}
.statsItem {
font-size: 11px;
color: ${cssManager.bdTheme('hsl(0 0% 45%)', 'hsl(0 0% 55%)')};
color: var(--dees-color-text-muted);
}
.statsItem strong {
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 90%)')};
color: var(--dees-color-text-primary);
}
.lw-tooltip {
position: absolute;

View File

@@ -0,0 +1,142 @@
import {
customElement,
property,
type TemplateResult,
} from '@design.estate/dees-element';
import { DeesChartEchartsBase } from '../dees-chart-echarts-base.js';
import { demoFunc } from './demo.js';
import { barStyles } from './styles.js';
import { renderChartBar } from './template.js';
import { getEchartsSeriesColors, getThemeColors } from '../dees-chart-echarts-theme.js';
export interface IBarSeriesItem {
name: string;
data: number[];
color?: string;
}
declare global {
interface HTMLElementTagNameMap {
'dees-chart-bar': DeesChartBar;
}
}
@customElement('dees-chart-bar')
export class DeesChartBar extends DeesChartEchartsBase {
public static demo = demoFunc;
public static demoGroups = ['Chart'];
@property({ type: Array })
accessor categories: string[] = [];
@property({ type: Array })
accessor series: IBarSeriesItem[] = [];
@property({ type: Boolean })
accessor horizontal: boolean = false;
@property({ type: Boolean })
accessor stacked: boolean = false;
@property({ type: Boolean })
accessor showLegend: boolean = true;
@property({ attribute: false })
accessor valueFormatter: (value: number) => string = (val) => `${val}`;
public static styles = barStyles;
public render(): TemplateResult {
return renderChartBar(this);
}
public async updated(changedProperties: Map<string, any>) {
super.updated(changedProperties);
if (
this.chartInstance &&
(changedProperties.has('categories') ||
changedProperties.has('series') ||
changedProperties.has('horizontal') ||
changedProperties.has('stacked') ||
changedProperties.has('showLegend'))
) {
this.updateChart();
}
}
protected buildOption(): Record<string, any> {
const colors = getThemeColors(this.goBright);
const seriesColors = getEchartsSeriesColors(this.goBright);
const formatter = this.valueFormatter;
const categoryAxis: Record<string, any> = {
type: 'category',
data: this.categories,
axisLine: { lineStyle: { color: colors.borderStrong } },
axisLabel: { color: colors.textMuted },
};
const valueAxis: Record<string, any> = {
type: 'value',
axisLine: { show: false },
axisLabel: {
color: colors.textMuted,
formatter: (val: number) => formatter(val),
},
splitLine: { lineStyle: { color: colors.borderSubtle } },
};
const seriesData = this.series.map((s, index) => ({
name: s.name,
type: 'bar' as const,
data: s.data,
stack: this.stacked ? 'total' : undefined,
itemStyle: {
color: s.color || seriesColors[index % seriesColors.length],
borderRadius: this.stacked ? [0, 0, 0, 0] : this.horizontal ? [0, 4, 4, 0] : [4, 4, 0, 0],
},
barMaxWidth: 40,
emphasis: {
itemStyle: {
shadowBlur: 6,
shadowColor: 'rgba(0, 0, 0, 0.15)',
},
},
}));
// For stacked bars, round the top corners of the last visible series
if (this.stacked && seriesData.length > 0) {
const last = seriesData[seriesData.length - 1];
last.itemStyle.borderRadius = this.horizontal ? [0, 4, 4, 0] : [4, 4, 0, 0];
}
return {
tooltip: {
trigger: 'axis',
axisPointer: { type: 'shadow' },
formatter: (params: any) => {
const items = Array.isArray(params) ? params : [params];
let result = `<strong>${items[0].axisValueLabel}</strong><br/>`;
for (const p of items) {
result += `${p.marker} ${p.seriesName}: <strong>${formatter(p.value)}</strong><br/>`;
}
return result;
},
},
legend: this.showLegend && this.series.length > 1
? { bottom: 8, itemWidth: 10, itemHeight: 10 }
: { show: false },
grid: {
left: 16,
right: 16,
top: 16,
bottom: this.showLegend && this.series.length > 1 ? 40 : 16,
containLabel: true,
},
xAxis: this.horizontal ? valueAxis : categoryAxis,
yAxis: this.horizontal ? categoryAxis : valueAxis,
series: seriesData,
};
}
}

View File

@@ -0,0 +1,120 @@
import { html, css, cssManager } from '@design.estate/dees-element';
import type { DeesChartBar } from './component.js';
import '@design.estate/dees-wcctools/demotools';
import './component.js';
export const demoFunc = () => {
const endpointCategories = ['/api/users', '/api/orders', '/api/products', '/api/auth', '/api/search'];
const endpointSeries = [
{ name: 'GET', data: [1240, 890, 720, 2100, 560] },
{ name: 'POST', data: [320, 450, 180, 890, 40] },
{ name: 'PUT', data: [90, 210, 150, 30, 10] },
];
const regionCategories = ['US-East', 'US-West', 'EU', 'Asia', 'Other'];
const regionSeries = [
{ name: 'Requests', data: [4500, 3200, 2800, 1900, 600] },
];
return html`
<dees-demowrapper .runAfterRender=${async (elementArg: HTMLElement) => {
const vertChart = elementArg.querySelector('#vert-chart') as DeesChartBar;
const horizChart = elementArg.querySelector('#horiz-chart') as DeesChartBar;
const stackChart = elementArg.querySelector('#stack-chart') as DeesChartBar;
const buttons = elementArg.querySelectorAll('dees-button');
buttons.forEach((button: any) => {
const text = button.text?.trim();
if (text === 'Randomize') {
button.addEventListener('click', () => {
vertChart.series = endpointSeries.map((s) => ({
...s,
data: s.data.map((v) => Math.round(v * (0.5 + Math.random()))),
}));
horizChart.series = regionSeries.map((s) => ({
...s,
data: s.data.map((v) => Math.round(v * (0.5 + Math.random()))),
}));
stackChart.series = endpointSeries.map((s) => ({
...s,
data: s.data.map((v) => Math.round(v * (0.5 + Math.random()))),
}));
});
}
});
}}>
<style>
${css`
.demoBox {
position: relative;
background: ${cssManager.bdTheme('hsl(0 0% 95%)', 'hsl(0 0% 9%)')};
height: 100%;
width: 100%;
padding: 40px;
box-sizing: border-box;
display: flex;
flex-direction: column;
gap: 24px;
}
.chartRow {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
}
.controls {
display: flex;
gap: 12px;
margin-bottom: 8px;
}
.info {
color: ${cssManager.bdTheme('hsl(215.4 16.3% 56.9%)', 'hsl(215 20.2% 55.1%)')};
font-size: 12px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Geist Sans', sans-serif;
text-align: center;
margin-top: 8px;
}
`}
</style>
<div class="demoBox">
<div class="controls">
<dees-button-group label="Actions:">
<dees-button>Randomize</dees-button>
</dees-button-group>
</div>
<div class="chartRow">
<dees-chart-bar
id="vert-chart"
.label=${'Requests by Endpoint'}
.categories=${endpointCategories}
.series=${endpointSeries}
.valueFormatter=${(val: number) => `${val} req`}
></dees-chart-bar>
<dees-chart-bar
id="horiz-chart"
.label=${'Traffic by Region'}
.categories=${regionCategories}
.series=${regionSeries}
.horizontal=${true}
.valueFormatter=${(val: number) => `${(val / 1000).toFixed(1)}k`}
></dees-chart-bar>
</div>
<dees-chart-bar
id="stack-chart"
.label=${'Stacked: Requests by Endpoint'}
.categories=${endpointCategories}
.series=${endpointSeries}
.stacked=${true}
.valueFormatter=${(val: number) => `${val} req`}
></dees-chart-bar>
<div class="info">
Bar chart with vertical, horizontal, and stacked modes •
Click 'Randomize' to update data with animation
</div>
</div>
</dees-demowrapper>
`;
};

View File

@@ -0,0 +1,7 @@
import { css } from '@design.estate/dees-element';
import { echartsBaseStyles } from '../dees-chart-echarts-styles.js';
export const barStyles = [
...echartsBaseStyles,
css``,
];

View File

@@ -0,0 +1,13 @@
import { html, type TemplateResult } from '@design.estate/dees-element';
import type { DeesChartBar } from './component.js';
export const renderChartBar = (component: DeesChartBar): TemplateResult => {
return html`
<dees-tile>
<div slot="header" class="chartHeader">
<span class="chartLabel">${component.label}</span>
</div>
<div class="chartContainer"></div>
</dees-tile>
`;
};

View File

@@ -0,0 +1,132 @@
import {
customElement,
property,
type TemplateResult,
} from '@design.estate/dees-element';
import { DeesChartEchartsBase } from '../dees-chart-echarts-base.js';
import { demoFunc } from './demo.js';
import { donutStyles } from './styles.js';
import { renderChartDonut } from './template.js';
import { getEchartsSeriesColors, getThemeColors } from '../dees-chart-echarts-theme.js';
export interface IDonutDataItem {
name: string;
value: number;
color?: string;
}
declare global {
interface HTMLElementTagNameMap {
'dees-chart-donut': DeesChartDonut;
}
}
@customElement('dees-chart-donut')
export class DeesChartDonut extends DeesChartEchartsBase {
public static demo = demoFunc;
public static demoGroups = ['Chart'];
@property({ type: Array })
accessor data: IDonutDataItem[] = [];
@property({ type: Boolean })
accessor showLegend: boolean = true;
@property({ type: Boolean })
accessor showLabels: boolean = true;
@property({ type: String })
accessor innerRadiusPercent: string = '55%';
@property({ attribute: false })
accessor valueFormatter: (value: number) => string = (val) => `${val}`;
public static styles = donutStyles;
public render(): TemplateResult {
return renderChartDonut(this);
}
public async updated(changedProperties: Map<string, any>) {
super.updated(changedProperties);
if (
this.chartInstance &&
(changedProperties.has('data') ||
changedProperties.has('showLegend') ||
changedProperties.has('showLabels') ||
changedProperties.has('innerRadiusPercent'))
) {
this.updateChart();
}
}
protected buildOption(): Record<string, any> {
const colors = getThemeColors(this.goBright);
const seriesColors = getEchartsSeriesColors(this.goBright);
const data = this.data.map((item, index) => ({
name: item.name,
value: item.value,
itemStyle: item.color ? { color: item.color } : { color: seriesColors[index % seriesColors.length] },
}));
const formatter = this.valueFormatter;
return {
tooltip: {
trigger: 'item',
formatter: (params: any) => {
return `${params.marker} ${params.name}: <strong>${formatter(params.value)}</strong> (${params.percent}%)`;
},
},
legend: this.showLegend
? {
orient: 'vertical',
right: 16,
top: 'center',
itemWidth: 10,
itemHeight: 10,
itemGap: 12,
formatter: (name: string) => {
const item = this.data.find((d) => d.name === name);
return item ? `${name} ${formatter(item.value)}` : name;
},
}
: { show: false },
series: [
{
type: 'pie',
radius: [this.innerRadiusPercent, '85%'],
center: this.showLegend ? ['35%', '50%'] : ['50%', '50%'],
avoidLabelOverlap: true,
itemStyle: {
borderRadius: 4,
borderColor: 'transparent',
borderWidth: 2,
},
label: this.showLabels
? {
show: true,
formatter: '{b}: {d}%',
fontSize: 11,
color: colors.textSecondary,
textBorderColor: 'transparent',
}
: { show: false },
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.2)',
},
label: {
show: true,
fontWeight: 'bold',
},
},
data,
},
],
};
}
}

View File

@@ -0,0 +1,127 @@
import { html, css, cssManager } from '@design.estate/dees-element';
import type { DeesChartDonut } from './component.js';
import '@design.estate/dees-wcctools/demotools';
import './component.js';
export const demoFunc = () => {
const diskData = [
{ name: 'Documents', value: 42 },
{ name: 'Media', value: 28 },
{ name: 'Applications', value: 15 },
{ name: 'System', value: 10 },
{ name: 'Other', value: 5 },
];
const statusData = [
{ name: 'Healthy', value: 156 },
{ name: 'Warning', value: 23 },
{ name: 'Critical', value: 8 },
{ name: 'Unknown', value: 3 },
];
const trafficData = [
{ name: 'API', value: 45200 },
{ name: 'Static Assets', value: 23100 },
{ name: 'WebSocket', value: 12800 },
{ name: 'GraphQL', value: 8900 },
];
return html`
<dees-demowrapper .runAfterRender=${async (elementArg: HTMLElement) => {
const diskChart = elementArg.querySelector('#disk-chart') as DeesChartDonut;
const statusChart = elementArg.querySelector('#status-chart') as DeesChartDonut;
const trafficChart = elementArg.querySelector('#traffic-chart') as DeesChartDonut;
// Wire up buttons
const buttons = elementArg.querySelectorAll('dees-button');
buttons.forEach((button: any) => {
const text = button.text?.trim();
if (text === 'Randomize') {
button.addEventListener('click', () => {
diskChart.data = diskData.map((d) => ({
...d,
value: Math.round(d.value * (0.5 + Math.random())),
}));
statusChart.data = statusData.map((d) => ({
...d,
value: Math.round(d.value * (0.3 + Math.random() * 1.4)),
}));
trafficChart.data = trafficData.map((d) => ({
...d,
value: Math.round(d.value * (0.5 + Math.random())),
}));
});
}
});
}}>
<style>
${css`
.demoBox {
position: relative;
background: ${cssManager.bdTheme('hsl(0 0% 95%)', 'hsl(0 0% 9%)')};
height: 100%;
width: 100%;
padding: 40px;
box-sizing: border-box;
display: flex;
flex-direction: column;
gap: 24px;
}
.chartRow {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
}
.controls {
display: flex;
gap: 12px;
margin-bottom: 8px;
}
.info {
color: ${cssManager.bdTheme('hsl(215.4 16.3% 56.9%)', 'hsl(215 20.2% 55.1%)')};
font-size: 12px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Geist Sans', sans-serif;
text-align: center;
margin-top: 8px;
}
`}
</style>
<div class="demoBox">
<div class="controls">
<dees-button-group label="Actions:">
<dees-button>Randomize</dees-button>
</dees-button-group>
</div>
<div class="chartRow">
<dees-chart-donut
id="disk-chart"
.label=${'Disk Usage (GB)'}
.data=${diskData}
.valueFormatter=${(val: number) => `${val} GB`}
></dees-chart-donut>
<dees-chart-donut
id="status-chart"
.label=${'Service Status'}
.data=${statusData}
.valueFormatter=${(val: number) => `${val} services`}
.innerRadiusPercent=${'0%'}
></dees-chart-donut>
</div>
<dees-chart-donut
id="traffic-chart"
.label=${'Traffic Distribution'}
.data=${trafficData}
.valueFormatter=${(val: number) => `${(val / 1000).toFixed(1)}k req`}
></dees-chart-donut>
<div class="info">
Donut chart with configurable inner radius (set to 0% for full pie) •
Click 'Randomize' to update data with animation
</div>
</div>
</dees-demowrapper>
`;
};

View File

@@ -0,0 +1,11 @@
import { css, cssManager } from '@design.estate/dees-element';
import { echartsBaseStyles } from '../dees-chart-echarts-styles.js';
export const donutStyles = [
...echartsBaseStyles,
css`
:host {
height: 360px;
}
`,
];

View File

@@ -0,0 +1,13 @@
import { html, type TemplateResult } from '@design.estate/dees-element';
import type { DeesChartDonut } from './component.js';
export const renderChartDonut = (component: DeesChartDonut): TemplateResult => {
return html`
<dees-tile>
<div slot="header" class="chartHeader">
<span class="chartLabel">${component.label}</span>
</div>
<div class="chartContainer"></div>
</dees-tile>
`;
};

View File

@@ -0,0 +1,107 @@
import {
DeesElement,
property,
html,
type TemplateResult,
} from '@design.estate/dees-element';
import * as domtools from '@design.estate/dees-domtools';
import { DeesServiceLibLoader, type IEchartsBundle, type IEchartsInstance } from '../../services/index.js';
import { getEchartsThemeOptions } from './dees-chart-echarts-theme.js';
import '../00group-layout/dees-tile/dees-tile.js';
/**
* Abstract base class for ECharts-based chart components.
* Handles library loading, chart lifecycle, resize observation, and theme switching.
* Subclasses implement `buildOption()` to define their chart configuration.
*/
export abstract class DeesChartEchartsBase extends DeesElement {
@property()
accessor label: string = 'Untitled Chart';
protected chartInstance: IEchartsInstance | null = null;
protected echartsBundle: IEchartsBundle | null = null;
private resizeObserver: ResizeObserver | null = null;
constructor() {
super();
domtools.elementBasic.setup();
this.registerGarbageFunction(async () => {
if (this.resizeObserver) {
this.resizeObserver.disconnect();
this.resizeObserver = null;
}
if (this.chartInstance) {
try {
this.chartInstance.dispose();
this.chartInstance = null;
} catch (e) {
console.error('Error disposing ECharts instance:', e);
}
}
});
}
public render(): TemplateResult {
return html`
<dees-tile>
<div slot="header" class="chartHeader">
<span class="chartLabel">${this.label}</span>
</div>
<div class="chartContainer"></div>
</dees-tile>
`;
}
public async firstUpdated() {
await this.domtoolsPromise;
this.echartsBundle = await DeesServiceLibLoader.getInstance().loadEcharts();
await new Promise(resolve => requestAnimationFrame(resolve));
const chartContainer = this.shadowRoot!.querySelector('.chartContainer') as HTMLDivElement;
if (!chartContainer) return;
try {
this.chartInstance = this.echartsBundle.init(chartContainer);
this.updateChart();
this.resizeObserver = new ResizeObserver(() => {
this.chartInstance?.resize();
});
this.resizeObserver.observe(chartContainer);
} catch (error) {
console.error('Failed to initialize ECharts:', error);
}
}
public async updated(changedProperties: Map<string, any>) {
super.updated(changedProperties);
if (changedProperties.has('goBright') && this.chartInstance) {
this.applyTheme();
}
}
protected abstract buildOption(): Record<string, any>;
protected updateChart(): void {
if (!this.chartInstance) return;
const themeOptions = getEchartsThemeOptions(this.goBright);
const chartOption = this.buildOption();
// Merge theme defaults with chart-specific options
const merged = {
...themeOptions,
...chartOption,
textStyle: { ...themeOptions.textStyle, ...(chartOption.textStyle || {}) },
tooltip: { ...themeOptions.tooltip, ...(chartOption.tooltip || {}) },
};
this.chartInstance.setOption(merged, true);
}
protected applyTheme(): void {
this.updateChart();
}
public async forceResize(): Promise<void> {
this.chartInstance?.resize();
}
}

View File

@@ -0,0 +1,36 @@
import { css, cssManager } from '@design.estate/dees-element';
import { themeDefaultStyles } from '../00theme.js';
export const echartsBaseStyles = [
themeDefaultStyles,
cssManager.defaultStyles,
css`
:host {
display: block;
height: 400px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
color: var(--dees-color-text-primary);
font-size: 14px;
}
dees-tile {
height: 100%;
}
.chartHeader {
display: flex;
align-items: center;
height: 32px;
padding: 0 8px 0 16px;
}
.chartLabel {
flex: 1;
font-size: 14px;
font-weight: 500;
letter-spacing: -0.01em;
color: var(--dees-color-text-secondary);
}
.chartContainer {
position: absolute;
inset: 0;
}
`,
];

View File

@@ -0,0 +1,72 @@
/**
* Shared theme utilities for ECharts-based chart components.
* Uses the centralized themeDefaults tokens so chart colors stay in sync
* with the rest of the dees-catalog design system.
*
* ECharts renders on <canvas> and cannot read CSS custom properties,
* so we reference the TypeScript source-of-truth (themeDefaults) directly.
*/
import { themeDefaults } from '../00theme.js';
const light = themeDefaults.colors.light;
const dark = themeDefaults.colors.dark;
const SERIES_COLORS = {
dark: [
dark.accentPrimary, // blue
'hsl(173.4 80.4% 40%)', // teal (no token yet)
'hsl(280.3 87.4% 66.7%)', // purple (no token yet)
dark.accentWarning, // orange/amber
dark.accentSuccess, // green
dark.accentError, // rose/red
],
light: [
light.accentPrimary,
'hsl(142.1 76.2% 36.3%)', // teal (no token yet)
'hsl(280.3 47.7% 50.2%)', // purple (no token yet)
light.accentWarning,
light.accentSuccess,
light.accentError,
],
};
export function getEchartsSeriesColors(goBright: boolean): string[] {
return goBright ? SERIES_COLORS.light : SERIES_COLORS.dark;
}
export function getEchartsThemeOptions(goBright: boolean): Record<string, any> {
const colors = goBright ? light : dark;
return {
backgroundColor: 'transparent',
textStyle: {
color: colors.textSecondary,
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
fontSize: 12,
},
color: goBright ? SERIES_COLORS.light : SERIES_COLORS.dark,
tooltip: {
backgroundColor: colors.bgPrimary,
borderColor: colors.borderDefault,
textStyle: {
color: colors.textPrimary,
fontSize: 12,
},
confine: true,
},
legend: {
textStyle: {
color: colors.textSecondary,
fontSize: 12,
},
},
};
}
/**
* Helper to get the resolved theme colors object for use in buildOption().
* Components can use this instead of hardcoding dark/light color values.
*/
export function getThemeColors(goBright: boolean) {
return goBright ? light : dark;
}

View File

@@ -0,0 +1,161 @@
import {
customElement,
property,
type TemplateResult,
} from '@design.estate/dees-element';
import { DeesChartEchartsBase } from '../dees-chart-echarts-base.js';
import { demoFunc } from './demo.js';
import { gaugeStyles } from './styles.js';
import { renderChartGauge } from './template.js';
import { getEchartsSeriesColors, getThemeColors } from '../dees-chart-echarts-theme.js';
export interface IGaugeThreshold {
value: number;
color: string;
}
declare global {
interface HTMLElementTagNameMap {
'dees-chart-gauge': DeesChartGauge;
}
}
@customElement('dees-chart-gauge')
export class DeesChartGauge extends DeesChartEchartsBase {
public static demo = demoFunc;
public static demoGroups = ['Chart'];
@property({ type: Number })
accessor value: number = 0;
@property({ type: Number })
accessor min: number = 0;
@property({ type: Number })
accessor max: number = 100;
@property({ type: String })
accessor unit: string = '%';
@property({ type: Array })
accessor thresholds: IGaugeThreshold[] = [];
@property({ type: Boolean })
accessor showTicks: boolean = true;
public static styles = gaugeStyles;
public render(): TemplateResult {
return renderChartGauge(this);
}
public async updated(changedProperties: Map<string, any>) {
super.updated(changedProperties);
if (
this.chartInstance &&
(changedProperties.has('value') ||
changedProperties.has('min') ||
changedProperties.has('max') ||
changedProperties.has('unit') ||
changedProperties.has('thresholds') ||
changedProperties.has('showTicks'))
) {
this.updateChart();
}
}
protected buildOption(): Record<string, any> {
const colors = getThemeColors(this.goBright);
const seriesColors = getEchartsSeriesColors(this.goBright);
const primaryColor = seriesColors[0];
// Build axis line color stops from thresholds
let axisLineColors: Array<[number, string]>;
if (this.thresholds.length > 0) {
const sorted = [...this.thresholds].sort((a, b) => a.value - b.value);
axisLineColors = sorted.map((t) => [
(t.value - this.min) / (this.max - this.min),
t.color,
]);
// Ensure we end at 1
if (axisLineColors[axisLineColors.length - 1][0] < 1) {
axisLineColors.push([1, sorted[sorted.length - 1].color]);
}
} else {
axisLineColors = [[1, primaryColor]];
}
return {
series: [
{
type: 'gauge',
min: this.min,
max: this.max,
startAngle: 220,
endAngle: -40,
progress: {
show: true,
width: 14,
roundCap: true,
},
pointer: {
show: true,
length: '60%',
width: 5,
itemStyle: {
color: 'auto',
},
},
axisLine: {
lineStyle: {
width: 14,
color: axisLineColors,
opacity: 0.3,
},
},
axisTick: {
show: this.showTicks,
distance: -20,
length: 6,
lineStyle: {
color: colors.borderStrong,
width: 1,
},
},
splitLine: {
show: this.showTicks,
distance: -24,
length: 10,
lineStyle: {
color: colors.textMuted,
width: 2,
},
},
axisLabel: {
show: this.showTicks,
distance: 30,
color: colors.textMuted,
fontSize: 11,
},
detail: {
valueAnimation: true,
fontSize: 28,
fontWeight: 600,
offsetCenter: [0, '65%'],
color: colors.textPrimary,
formatter: `{value}${this.unit}`,
},
title: {
show: false,
},
data: [
{
value: this.value,
},
],
},
],
};
}
}

View File

@@ -0,0 +1,125 @@
import { html, css, cssManager } from '@design.estate/dees-element';
import type { DeesChartGauge } from './component.js';
import '@design.estate/dees-wcctools/demotools';
import './component.js';
export const demoFunc = () => {
const defaultThresholds = [
{ value: 60, color: 'hsl(142 76% 36%)' },
{ value: 80, color: 'hsl(38 92% 50%)' },
{ value: 100, color: 'hsl(0 72% 50%)' },
];
return html`
<dees-demowrapper .runAfterRender=${async (elementArg: HTMLElement) => {
const cpuGauge = elementArg.querySelector('#cpu-gauge') as DeesChartGauge;
const memGauge = elementArg.querySelector('#mem-gauge') as DeesChartGauge;
const slaGauge = elementArg.querySelector('#sla-gauge') as DeesChartGauge;
let animInterval: number | null = null;
const buttons = elementArg.querySelectorAll('dees-button');
buttons.forEach((button: any) => {
const text = button.text?.trim();
if (text === 'Animate') {
button.addEventListener('click', () => {
if (animInterval) return;
animInterval = window.setInterval(() => {
cpuGauge.value = Math.round(30 + Math.random() * 60);
memGauge.value = Math.round(40 + Math.random() * 50);
slaGauge.value = Math.round((95 + Math.random() * 5) * 100) / 100;
}, 2000);
});
} else if (text === 'Stop') {
button.addEventListener('click', () => {
if (animInterval) {
window.clearInterval(animInterval);
animInterval = null;
}
});
} else if (text === 'Spike') {
button.addEventListener('click', () => {
cpuGauge.value = 95;
memGauge.value = 88;
slaGauge.value = 96.5;
});
}
});
}}>
<style>
${css`
.demoBox {
position: relative;
background: ${cssManager.bdTheme('hsl(0 0% 95%)', 'hsl(0 0% 9%)')};
height: 100%;
width: 100%;
padding: 40px;
box-sizing: border-box;
display: flex;
flex-direction: column;
gap: 24px;
}
.gaugeRow {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 24px;
}
.controls {
display: flex;
gap: 12px;
margin-bottom: 8px;
}
.info {
color: ${cssManager.bdTheme('hsl(215.4 16.3% 56.9%)', 'hsl(215 20.2% 55.1%)')};
font-size: 12px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Geist Sans', sans-serif;
text-align: center;
margin-top: 8px;
}
`}
</style>
<div class="demoBox">
<div class="controls">
<dees-button-group label="Actions:">
<dees-button>Animate</dees-button>
<dees-button>Stop</dees-button>
<dees-button>Spike</dees-button>
</dees-button-group>
</div>
<div class="gaugeRow">
<dees-chart-gauge
id="cpu-gauge"
.label=${'CPU Usage'}
.value=${42}
.unit=${'%'}
.thresholds=${defaultThresholds}
></dees-chart-gauge>
<dees-chart-gauge
id="mem-gauge"
.label=${'Memory Usage'}
.value=${67}
.unit=${'%'}
.thresholds=${defaultThresholds}
></dees-chart-gauge>
<dees-chart-gauge
id="sla-gauge"
.label=${'SLA Uptime'}
.value=${99.8}
.min=${95}
.max=${100}
.unit=${'%'}
.showTicks=${true}
></dees-chart-gauge>
</div>
<div class="info">
Gauge chart with animated value transitions and threshold coloring •
Click 'Animate' for live updates, 'Spike' to simulate high load
</div>
</div>
</dees-demowrapper>
`;
};

View File

@@ -0,0 +1,11 @@
import { css } from '@design.estate/dees-element';
import { echartsBaseStyles } from '../dees-chart-echarts-styles.js';
export const gaugeStyles = [
...echartsBaseStyles,
css`
:host {
height: 320px;
}
`,
];

View File

@@ -0,0 +1,13 @@
import { html, type TemplateResult } from '@design.estate/dees-element';
import type { DeesChartGauge } from './component.js';
export const renderChartGauge = (component: DeesChartGauge): TemplateResult => {
return html`
<dees-tile>
<div slot="header" class="chartHeader">
<span class="chartLabel">${component.label}</span>
</div>
<div class="chartContainer"></div>
</dees-tile>
`;
};

View File

@@ -106,7 +106,7 @@ export class DeesChartLog extends DeesElement {
display: block;
height: 400px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
color: ${cssManager.bdTheme('hsl(0 0% 3.9%)', 'hsl(0 0% 98%)')};
color: var(--dees-color-text-primary);
}
dees-tile {
@@ -124,7 +124,7 @@ export class DeesChartLog extends DeesElement {
.title {
font-weight: 500;
font-size: 14px;
color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 95%)')};
color: var(--dees-color-text-primary);
white-space: nowrap;
}
@@ -141,10 +141,10 @@ export class DeesChartLog extends DeesElement {
flex: 1;
padding: 4px 8px;
font-size: 12px;
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
border: 1px solid var(--dees-color-border-default);
border-radius: 4px;
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 9%)')};
color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 95%)')};
background: var(--dees-color-bg-primary);
color: var(--dees-color-text-primary);
outline: none;
}
@@ -153,7 +153,7 @@ export class DeesChartLog extends DeesElement {
}
.search-box input::placeholder {
color: ${cssManager.bdTheme('hsl(0 0% 63.9%)', 'hsl(0 0% 45.1%)')};
color: var(--dees-color-text-muted);
}
.search-nav {
@@ -164,35 +164,35 @@ export class DeesChartLog extends DeesElement {
.search-nav button {
padding: 4px 6px;
font-size: 11px;
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 14.9%)')};
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
background: var(--dees-color-bg-primary);
border: 1px solid var(--dees-color-border-default);
border-radius: 3px;
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
color: var(--dees-color-text-muted);
cursor: pointer;
line-height: 1;
}
.search-nav button:hover {
background: ${cssManager.bdTheme('hsl(0 0% 95.1%)', 'hsl(0 0% 20%)')};
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 93.9%)')};
background: var(--dees-color-hover);
color: var(--dees-color-text-primary);
}
.filter-toggle {
padding: 4px 8px;
font-size: 11px;
font-weight: 500;
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 14.9%)')};
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
background: var(--dees-color-bg-primary);
border: 1px solid var(--dees-color-border-default);
border-radius: 4px;
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
color: var(--dees-color-text-muted);
cursor: pointer;
transition: all 0.15s;
white-space: nowrap;
}
.filter-toggle:hover {
background: ${cssManager.bdTheme('hsl(0 0% 95.1%)', 'hsl(0 0% 20%)')};
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 93.9%)')};
background: var(--dees-color-hover);
color: var(--dees-color-text-primary);
}
.filter-toggle.active {
@@ -208,11 +208,11 @@ export class DeesChartLog extends DeesElement {
}
.control-button {
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 14.9%)')};
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
background: var(--dees-color-bg-primary);
border: 1px solid var(--dees-color-border-default);
border-radius: 4px;
padding: 4px 10px;
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
color: var(--dees-color-text-muted);
cursor: pointer;
font-size: 12px;
font-weight: 500;
@@ -220,9 +220,9 @@ export class DeesChartLog extends DeesElement {
}
.control-button:hover {
background: ${cssManager.bdTheme('hsl(0 0% 95.1%)', 'hsl(0 0% 20%)')};
border-color: ${cssManager.bdTheme('hsl(0 0% 79.8%)', 'hsl(0 0% 25%)')};
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 93.9%)')};
background: var(--dees-color-hover);
border-color: var(--dees-color-border-strong);
color: var(--dees-color-text-primary);
}
.control-button.active {
@@ -247,7 +247,7 @@ export class DeesChartLog extends DeesElement {
align-items: center;
justify-content: center;
height: 100%;
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
color: var(--dees-color-text-muted);
font-style: italic;
font-size: 13px;
}
@@ -299,7 +299,7 @@ export class DeesChartLog extends DeesElement {
.metric.rate {
margin-left: auto;
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
color: var(--dees-color-text-muted);
}
.metric.rate::before {

View File

@@ -0,0 +1,130 @@
import {
customElement,
property,
type TemplateResult,
} from '@design.estate/dees-element';
import { DeesChartEchartsBase } from '../dees-chart-echarts-base.js';
import { demoFunc } from './demo.js';
import { radarStyles } from './styles.js';
import { renderChartRadar } from './template.js';
import { getEchartsSeriesColors, getThemeColors } from '../dees-chart-echarts-theme.js';
export interface IRadarIndicator {
name: string;
max: number;
}
export interface IRadarSeriesItem {
name: string;
values: number[];
color?: string;
}
declare global {
interface HTMLElementTagNameMap {
'dees-chart-radar': DeesChartRadar;
}
}
@customElement('dees-chart-radar')
export class DeesChartRadar extends DeesChartEchartsBase {
public static demo = demoFunc;
public static demoGroups = ['Chart'];
@property({ type: Array })
accessor indicators: IRadarIndicator[] = [];
@property({ type: Array })
accessor series: IRadarSeriesItem[] = [];
@property({ type: Boolean })
accessor showLegend: boolean = true;
@property({ type: Boolean })
accessor fillArea: boolean = true;
public static styles = radarStyles;
public render(): TemplateResult {
return renderChartRadar(this);
}
public async updated(changedProperties: Map<string, any>) {
super.updated(changedProperties);
if (
this.chartInstance &&
(changedProperties.has('indicators') ||
changedProperties.has('series') ||
changedProperties.has('showLegend') ||
changedProperties.has('fillArea'))
) {
this.updateChart();
}
}
protected buildOption(): Record<string, any> {
const colors = getThemeColors(this.goBright);
const seriesColors = getEchartsSeriesColors(this.goBright);
const seriesData = this.series.map((s, index) => {
const color = s.color || seriesColors[index % seriesColors.length];
return {
name: s.name,
value: s.values,
itemStyle: { color },
lineStyle: { color, width: 2 },
areaStyle: this.fillArea ? { color, opacity: 0.15 } : undefined,
symbol: 'circle',
symbolSize: 6,
};
});
return {
tooltip: {
trigger: 'item',
},
legend: this.showLegend && this.series.length > 1
? { bottom: 8, itemWidth: 10, itemHeight: 10 }
: { show: false },
radar: {
indicator: this.indicators.map((ind) => ({
name: ind.name,
max: ind.max,
})),
shape: 'polygon',
splitNumber: 4,
axisName: {
color: colors.textSecondary,
fontSize: 11,
},
splitArea: {
areaStyle: {
color: [colors.bgTertiary, colors.bgSecondary],
},
},
splitLine: {
lineStyle: {
color: colors.borderDefault,
},
},
axisLine: {
lineStyle: {
color: colors.borderDefault,
},
},
},
series: [
{
type: 'radar',
data: seriesData,
emphasis: {
lineStyle: {
width: 3,
},
},
},
],
};
}
}

View File

@@ -0,0 +1,119 @@
import { html, css, cssManager } from '@design.estate/dees-element';
import type { DeesChartRadar } from './component.js';
import '@design.estate/dees-wcctools/demotools';
import './component.js';
export const demoFunc = () => {
const indicators = [
{ name: 'Latency', max: 100 },
{ name: 'Throughput', max: 100 },
{ name: 'Availability', max: 100 },
{ name: 'Error Rate', max: 100 },
{ name: 'Saturation', max: 100 },
{ name: 'Security', max: 100 },
];
const series = [
{ name: 'Service A', values: [85, 90, 99, 12, 45, 78] },
{ name: 'Service B', values: [70, 65, 95, 28, 60, 90] },
];
const singleIndicators = [
{ name: 'Speed', max: 10 },
{ name: 'Reliability', max: 10 },
{ name: 'Comfort', max: 10 },
{ name: 'Safety', max: 10 },
{ name: 'Cost', max: 10 },
];
const singleSeries = [
{ name: 'Rating', values: [8.5, 9.2, 7.0, 9.5, 6.0] },
];
return html`
<dees-demowrapper .runAfterRender=${async (elementArg: HTMLElement) => {
const compChart = elementArg.querySelector('#comparison-chart') as DeesChartRadar;
const singleChart = elementArg.querySelector('#single-chart') as DeesChartRadar;
const buttons = elementArg.querySelectorAll('dees-button');
buttons.forEach((button: any) => {
const text = button.text?.trim();
if (text === 'Randomize') {
button.addEventListener('click', () => {
compChart.series = series.map((s) => ({
...s,
values: s.values.map(() => Math.round(20 + Math.random() * 80)),
}));
singleChart.series = singleSeries.map((s) => ({
...s,
values: s.values.map(() => Math.round((2 + Math.random() * 8) * 10) / 10),
}));
});
}
});
}}>
<style>
${css`
.demoBox {
position: relative;
background: ${cssManager.bdTheme('hsl(0 0% 95%)', 'hsl(0 0% 9%)')};
height: 100%;
width: 100%;
padding: 40px;
box-sizing: border-box;
display: flex;
flex-direction: column;
gap: 24px;
}
.chartRow {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
}
.controls {
display: flex;
gap: 12px;
margin-bottom: 8px;
}
.info {
color: ${cssManager.bdTheme('hsl(215.4 16.3% 56.9%)', 'hsl(215 20.2% 55.1%)')};
font-size: 12px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Geist Sans', sans-serif;
text-align: center;
margin-top: 8px;
}
`}
</style>
<div class="demoBox">
<div class="controls">
<dees-button-group label="Actions:">
<dees-button>Randomize</dees-button>
</dees-button-group>
</div>
<div class="chartRow">
<dees-chart-radar
id="comparison-chart"
.label=${'Service Health Comparison'}
.indicators=${indicators}
.series=${series}
></dees-chart-radar>
<dees-chart-radar
id="single-chart"
.label=${'Product Rating'}
.indicators=${singleIndicators}
.series=${singleSeries}
.fillArea=${true}
></dees-chart-radar>
</div>
<div class="info">
Radar chart for multi-dimensional comparison •
Supports multiple overlay series and configurable fill •
Click 'Randomize' to update data
</div>
</div>
</dees-demowrapper>
`;
};

View File

@@ -0,0 +1,7 @@
import { css } from '@design.estate/dees-element';
import { echartsBaseStyles } from '../dees-chart-echarts-styles.js';
export const radarStyles = [
...echartsBaseStyles,
css``,
];

View File

@@ -0,0 +1,13 @@
import { html, type TemplateResult } from '@design.estate/dees-element';
import type { DeesChartRadar } from './component.js';
export const renderChartRadar = (component: DeesChartRadar): TemplateResult => {
return html`
<dees-tile>
<div slot="header" class="chartHeader">
<span class="chartLabel">${component.label}</span>
</div>
<div class="chartContainer"></div>
</dees-tile>
`;
};

View File

@@ -1,3 +1,7 @@
// Chart Components
export * from './dees-chart-area/index.js';
export * from './dees-chart-bar/index.js';
export * from './dees-chart-donut/index.js';
export * from './dees-chart-gauge/index.js';
export * from './dees-chart-log/index.js';
export * from './dees-chart-radar/index.js';

View File

@@ -2,6 +2,7 @@ import { demoFunc } from './dees-dataview-codebox.demo.js';
import {
DeesElement,
html,
css,
customElement,
type TemplateResult,
property,
@@ -9,6 +10,7 @@ import {
cssManager,
} from '@design.estate/dees-element';
import { cssGeistFontFamily, cssMonoFontFamily } from '../../00fonts.js';
import { themeDefaultStyles } from '../../00theme.js';
import type { HLJSApi } from 'highlight.js';
@@ -39,6 +41,11 @@ export class DeesDataviewCodebox extends DeesElement {
})
accessor codeToDisplay: string = '';
public static styles = [
themeDefaultStyles,
cssManager.defaultStyles,
];
constructor() {
super();
}
@@ -53,16 +60,14 @@ export class DeesDataviewCodebox extends DeesElement {
text-align: left;
font-size: 16px;
font-family: ${cssGeistFontFamily};
height: 100%;
box-sizing: border-box;
}
dees-tile {
height: 100%;
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
color: var(--dees-color-text-primary);
}
.appbar {
color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
color: var(--dees-color-text-muted);
height: 32px;
display: flex;
font-size: 13px;
@@ -80,7 +85,7 @@ export class DeesDataviewCodebox extends DeesElement {
}
.bottomBar {
color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
color: var(--dees-color-text-muted);
height: 28px;
font-size: 11px;
line-height: 28px;
@@ -114,18 +119,16 @@ export class DeesDataviewCodebox extends DeesElement {
}
.codegrid {
position: absolute;
inset: 0;
display: grid;
grid-template-columns: 50px auto;
overflow: auto;
}
.lineNumbers {
color: ${cssManager.bdTheme('#71717a', '#52525b')};
color: var(--dees-color-text-muted);
padding: 24px 16px 0px 0px;
text-align: right;
border-right: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
border-right: 1px solid var(--dees-color-border-default);
}
.lineCounter:last-child {

View File

@@ -42,7 +42,7 @@ export class DeesDataviewStatusobject extends DeesElement {
}
dees-tile {
color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 98%)')};
color: var(--dees-color-text-primary);
cursor: default;
}
@@ -61,7 +61,7 @@ export class DeesDataviewStatusobject extends DeesElement {
font-size: 14px;
font-weight: 500;
letter-spacing: -0.01em;
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 63.9%)')};
color: var(--dees-color-text-secondary);
flex: 1;
}
@@ -78,21 +78,21 @@ export class DeesDataviewStatusobject extends DeesElement {
.copyMain {
font-size: 11px;
font-weight: 500;
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 14.9%)')};
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
background: var(--dees-color-bg-primary);
border: 1px solid var(--dees-color-border-default);
text-align: center;
padding: 4px 10px;
border-radius: 4px;
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
color: var(--dees-color-text-muted);
user-select: none;
cursor: pointer;
transition: all 0.15s ease;
}
.copyMain:hover {
background: ${cssManager.bdTheme('hsl(0 0% 95.1%)', 'hsl(0 0% 14.9%)')};
border-color: ${cssManager.bdTheme('hsl(0 0% 79.8%)', 'hsl(0 0% 20.9%)')};
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 93.9%)')};
background: var(--dees-color-hover);
border-color: var(--dees-color-border-strong);
color: var(--dees-color-text-primary);
}
.copyMain:active {
@@ -121,7 +121,7 @@ export class DeesDataviewStatusobject extends DeesElement {
gap: 10px;
height: 36px;
padding: 0 16px;
border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 95%)', 'hsl(0 0% 10%)')};
border-bottom: 1px solid var(--dees-color-border-subtle);
transition: background-color 0.15s ease;
cursor: context-menu;
}
@@ -149,7 +149,7 @@ export class DeesDataviewStatusobject extends DeesElement {
.detail .detailsText .label {
font-size: 12px;
font-weight: 500;
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
color: var(--dees-color-text-muted);
letter-spacing: -0.01em;
white-space: nowrap;
flex-shrink: 0;
@@ -167,7 +167,7 @@ export class DeesDataviewStatusobject extends DeesElement {
}
.bottomBar {
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
color: var(--dees-color-text-muted);
height: 28px;
font-size: 11px;
line-height: 28px;

View File

@@ -160,7 +160,7 @@ export class DeesStatsGrid extends DeesElement {
.grid-title {
font-size: 16px;
font-weight: 500;
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
color: var(--dees-color-text-primary);
letter-spacing: -0.01em;
}
@@ -186,7 +186,7 @@ export class DeesStatsGrid extends DeesElement {
}
.stats-tile:hover::part(outer) {
border-color: ${cssManager.bdTheme('#d0d0d0', '#2a2a2a')};
border-color: var(--dees-color-border-strong);
}
.stats-tile.clickable {
@@ -281,7 +281,7 @@ export class DeesStatsGrid extends DeesElement {
.gauge-background {
fill: none;
stroke: ${cssManager.bdTheme('#e8e8e8', '#1a1a1a')};
stroke: var(--dees-color-border-default);
stroke-width: 6;
}
@@ -329,7 +329,7 @@ export class DeesStatsGrid extends DeesElement {
.percentage-bar {
width: 100%;
height: 6px;
background: ${cssManager.bdTheme('#e8e8e8', '#1a1a1a')};
background: var(--dees-color-border-default);
border-radius: 3px;
overflow: hidden;
margin-top: auto;
@@ -337,7 +337,7 @@ export class DeesStatsGrid extends DeesElement {
.percentage-fill {
height: 100%;
background: ${cssManager.bdTheme('#333333', '#e0e0e0')};
background: var(--dees-color-text-muted);
transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1);
border-radius: 3px;
}
@@ -386,14 +386,14 @@ export class DeesStatsGrid extends DeesElement {
.multi-percentage-bar {
width: 100%;
height: 4px;
background: ${cssManager.bdTheme('#e8e8e8', '#1a1a1a')};
background: var(--dees-color-border-default);
border-radius: 2px;
overflow: hidden;
}
.multi-percentage-fill {
height: 100%;
background: ${cssManager.bdTheme('#333333', '#e0e0e0')};
background: var(--dees-color-text-muted);
transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1);
border-radius: 2px;
}
@@ -464,7 +464,7 @@ export class DeesStatsGrid extends DeesElement {
.cpu-core-bar-wrapper {
flex: 1;
width: 100%;
background: ${cssManager.bdTheme('#e8e8e8', '#1a1a1a')};
background: var(--dees-color-border-default);
border-radius: 2px;
position: relative;
overflow: hidden;
@@ -477,21 +477,21 @@ export class DeesStatsGrid extends DeesElement {
left: 0;
right: 0;
width: 100%;
background: ${cssManager.bdTheme('#666666', '#888888')};
background: var(--dees-color-text-muted);
transition: height 0.3s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.3s ease;
border-radius: 2px 2px 0 0;
}
.cpu-core-bar-fill.low {
background: ${cssManager.bdTheme('hsl(142.1 76.2% 36.3%)', 'hsl(142.1 70.6% 45.3%)')};
background: var(--dees-color-accent-success);
}
.cpu-core-bar-fill.medium {
background: ${cssManager.bdTheme('hsl(45.4 93.4% 47.5%)', 'hsl(45.4 93.4% 47.5%)')};
background: var(--dees-color-accent-warning);
}
.cpu-core-bar-fill.high {
background: ${cssManager.bdTheme('hsl(0 84.2% 60.2%)', 'hsl(0 84.2% 60.2%)')};
background: var(--dees-color-accent-error);
}
.cpu-core-label {
@@ -531,24 +531,24 @@ export class DeesStatsGrid extends DeesElement {
.partition-bar {
width: 100%;
height: 6px;
background: ${cssManager.bdTheme('#e8e8e8', '#1a1a1a')};
background: var(--dees-color-border-default);
border-radius: 3px;
overflow: hidden;
}
.partition-bar-fill {
height: 100%;
background: ${cssManager.bdTheme('#333333', '#e0e0e0')};
background: var(--dees-color-text-muted);
transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1);
border-radius: 3px;
}
.partition-bar-fill.warning {
background: ${cssManager.bdTheme('hsl(45.4 93.4% 47.5%)', 'hsl(45.4 93.4% 47.5%)')};
background: var(--dees-color-accent-warning);
}
.partition-bar-fill.critical {
background: ${cssManager.bdTheme('hsl(0 84.2% 60.2%)', 'hsl(0 84.2% 60.2%)')};
background: var(--dees-color-accent-error);
}
.partition-stats {
@@ -695,7 +695,7 @@ export class DeesStatsGrid extends DeesElement {
.disk-health-bar {
width: 100%;
height: 4px;
background: ${cssManager.bdTheme('#e8e8e8', '#1a1a1a')};
background: var(--dees-color-border-default);
border-radius: 2px;
overflow: hidden;
}
@@ -771,7 +771,7 @@ export class DeesStatsGrid extends DeesElement {
.trend-line {
fill: none;
stroke: ${cssManager.bdTheme('#999999', '#666666')};
stroke: var(--dees-color-text-muted);
stroke-width: 1.5;
stroke-linejoin: round;
stroke-linecap: round;

View File

@@ -13,7 +13,7 @@ export const tableStyles: CSSResult[] = [
}
dees-tile {
color: ${cssManager.bdTheme('hsl(0 0% 3.9%)', 'hsl(0 0% 98%)')};
color: var(--dees-color-text-primary);
font-family: ${cssGeistFontFamily};
font-weight: 400;
font-size: 14px;
@@ -41,7 +41,7 @@ export const tableStyles: CSSResult[] = [
.heading1 {
font-size: 14px;
font-weight: 500;
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 63.9%)')};
color: var(--dees-color-text-secondary);
letter-spacing: -0.01em;
}
@@ -69,18 +69,18 @@ export const tableStyles: CSSResult[] = [
padding: 4px 10px;
font-size: 12px;
font-weight: 500;
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
color: var(--dees-color-text-muted);
background: transparent;
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
border: 1px solid var(--dees-color-border-default);
border-radius: 4px;
cursor: pointer;
transition: all 0.15s ease;
}
.headerAction:hover {
color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 95%)')};
background: ${cssManager.bdTheme('hsl(0 0% 95.1%)', 'hsl(0 0% 14.9%)')};
border-color: ${cssManager.bdTheme('hsl(0 0% 79.8%)', 'hsl(0 0% 20.9%)')};
color: var(--dees-color-text-primary);
background: var(--dees-color-hover);
border-color: var(--dees-color-border-strong);
}
.headerAction dees-icon {
@@ -93,8 +93,8 @@ export const tableStyles: CSSResult[] = [
grid-gap: 16px;
grid-template-columns: 1fr max-content;
padding: 16px 24px;
background: ${cssManager.bdTheme('hsl(210 40% 98%)', 'hsl(0 0% 3.9%)')};
border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
background: var(--dees-color-bg-secondary);
border-bottom: 1px solid var(--dees-color-border-default);
transition: all 0.2s ease;
}
@@ -157,7 +157,7 @@ export const tableStyles: CSSResult[] = [
thead {
background: ${cssManager.bdTheme('hsl(210 40% 96.1%)', 'hsl(0 0% 9%)')};
border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 79.8%)', 'hsl(0 0% 20.9%)')};
border-bottom: 1px solid var(--dees-color-border-strong);
}
:host([sticky-header]) thead th {
position: sticky;
@@ -172,7 +172,7 @@ export const tableStyles: CSSResult[] = [
/* Default horizontal lines (bottom border only) */
tbody tr {
border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
border-bottom: 1px solid var(--dees-color-border-default);
}
tbody tr:last-child {
@@ -181,8 +181,8 @@ export const tableStyles: CSSResult[] = [
/* Full horizontal lines when enabled */
:host([show-horizontal-lines]) tbody tr {
border-top: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
border-top: 1px solid var(--dees-color-border-default);
border-bottom: 1px solid var(--dees-color-border-default);
}
:host([show-horizontal-lines]) tbody tr:first-child {
@@ -190,7 +190,7 @@ export const tableStyles: CSSResult[] = [
}
:host([show-horizontal-lines]) tbody tr:last-child {
border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
border-bottom: 1px solid var(--dees-color-border-default);
}
tbody tr:hover {
@@ -222,13 +222,13 @@ export const tableStyles: CSSResult[] = [
/* Grid mode - shows both vertical and horizontal lines */
:host([show-grid]) th {
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
border: 1px solid var(--dees-color-border-default);
border-left: none;
border-top: none;
}
:host([show-grid]) td {
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
border: 1px solid var(--dees-color-border-default);
border-left: none;
border-top: none;
}
@@ -251,12 +251,12 @@ export const tableStyles: CSSResult[] = [
tbody td.actionsCol {
position: sticky;
right: 0;
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 3.9%)')};
background: var(--dees-color-bg-primary);
}
thead th.actionsCol { z-index: 3; }
tbody td.actionsCol {
z-index: 1;
box-shadow: -1px 0 0 0 ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
box-shadow: -1px 0 0 0 var(--dees-color-border-default);
}
tbody tr.selected {
@@ -278,18 +278,18 @@ export const tableStyles: CSSResult[] = [
}
:host([show-vertical-lines]) th {
border-right: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
border-right: 1px solid var(--dees-color-border-default);
}
td {
padding: 8px 16px;
vertical-align: middle;
font-size: 13px;
color: ${cssManager.bdTheme('hsl(0 0% 3.9%)', 'hsl(0 0% 98%)')};
color: var(--dees-color-text-primary);
}
:host([show-vertical-lines]) td {
border-right: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
border-right: 1px solid var(--dees-color-border-default);
}
th:first-child,
@@ -327,10 +327,10 @@ export const tableStyles: CSSResult[] = [
height: calc(100% - 8px);
padding: 0 12px;
outline: none;
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
border: 1px solid var(--dees-color-border-default);
border-radius: 6px;
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 9%)')};
color: ${cssManager.bdTheme('hsl(0 0% 3.9%)', 'hsl(0 0% 98%)')};
color: var(--dees-color-text-primary);
font-family: inherit;
font-size: inherit;
font-weight: inherit;
@@ -355,9 +355,9 @@ export const tableStyles: CSSResult[] = [
padding: 6px 8px;
font-size: 13px;
border-radius: 6px;
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
border: 1px solid var(--dees-color-border-default);
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 9%)')};
color: ${cssManager.bdTheme('hsl(0 0% 3.9%)', 'hsl(0 0% 98%)')};
color: var(--dees-color-text-primary);
}
.actionsContainer {
display: flex;
@@ -398,7 +398,7 @@ export const tableStyles: CSSResult[] = [
height: 32px;
padding: 0 16px;
font-size: 11px;
color: ${cssManager.bdTheme('hsl(0 0% 45%)', 'hsl(0 0% 55%)')};
color: var(--dees-color-text-muted);
width: 100%;
box-sizing: border-box;
}

View File

@@ -142,16 +142,16 @@ export class DeesInputCode extends DeesInputBase<string> {
padding: 4px 10px;
font-size: 12px;
font-weight: 500;
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 12%)')};
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 20%)')};
background: var(--dees-color-bg-primary);
border: 1px solid var(--dees-color-border-default);
border-radius: 4px;
cursor: pointer;
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 90%)')};
color: var(--dees-color-text-secondary);
transition: all 0.15s ease;
}
.language-button:hover {
background: ${cssManager.bdTheme('hsl(0 0% 95%)', 'hsl(0 0% 15%)')};
background: var(--dees-color-hover);
}
.language-dropdown {
@@ -159,8 +159,8 @@ export class DeesInputCode extends DeesInputBase<string> {
top: 100%;
left: 0;
margin-top: 4px;
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 9%)')};
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 20%)')};
background: var(--dees-color-bg-primary);
border: 1px solid var(--dees-color-border-default);
border-radius: 6px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
z-index: 100;
@@ -173,16 +173,16 @@ export class DeesInputCode extends DeesInputBase<string> {
padding: 8px 12px;
font-size: 12px;
cursor: pointer;
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 90%)')};
color: var(--dees-color-text-secondary);
transition: background 0.15s ease;
}
.language-option:hover {
background: ${cssManager.bdTheme('hsl(0 0% 95%)', 'hsl(0 0% 15%)')};
background: var(--dees-color-hover);
}
.language-option.selected {
background: ${cssManager.bdTheme('hsl(0 0% 90%)', 'hsl(0 0% 20%)')};
background: var(--dees-color-active);
}
.toolbar-button {
@@ -195,18 +195,18 @@ export class DeesInputCode extends DeesInputBase<string> {
border: none;
border-radius: 4px;
cursor: pointer;
color: ${cssManager.bdTheme('hsl(0 0% 45%)', 'hsl(0 0% 60%)')};
color: var(--dees-color-text-muted);
transition: all 0.15s ease;
}
.toolbar-button:hover {
background: ${cssManager.bdTheme('hsl(0 0% 90%)', 'hsl(0 0% 15%)')};
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 90%)')};
background: var(--dees-color-hover);
color: var(--dees-color-text-secondary);
}
.toolbar-button.active {
background: ${cssManager.bdTheme('hsl(0 0% 85%)', 'hsl(0 0% 20%)')};
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 90%)')};
background: var(--dees-color-active);
color: var(--dees-color-text-secondary);
}
.toolbar-button.success {
@@ -226,7 +226,7 @@ export class DeesInputCode extends DeesInputBase<string> {
.toolbar-divider {
width: 1px;
height: 20px;
background: ${cssManager.bdTheme('hsl(0 0% 85%)', 'hsl(0 0% 20%)')};
background: var(--dees-color-border-default);
margin: 0 4px;
}

View File

@@ -1,7 +1,9 @@
import { css, cssManager } from '@design.estate/dees-element';
import { DeesInputBase } from '../dees-input-base/dees-input-base.js';
import { themeDefaultStyles } from '../../00theme.js';
export const richtextStyles = [
themeDefaultStyles,
...DeesInputBase.baseStyles,
cssManager.defaultStyles,
css`
@@ -20,7 +22,7 @@ export const richtextStyles = [
margin-bottom: 8px;
font-size: 14px;
font-weight: 500;
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 93.9%)')};
color: var(--dees-color-text-primary);
}
dees-tile {
@@ -28,7 +30,7 @@ export const richtextStyles = [
}
dees-tile:hover::part(outer) {
border-color: ${cssManager.bdTheme('hsl(0 0% 79.8%)', 'hsl(0 0% 20.9%)')};
border-color: var(--dees-color-border-strong);
}
dees-tile.focused::part(outer) {
@@ -68,8 +70,8 @@ export const richtextStyles = [
}
.toolbar-button:hover {
background: ${cssManager.bdTheme('hsl(0 0% 95.1%)', 'hsl(0 0% 14.9%)')};
color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 95%)')};
background: var(--dees-color-hover);
color: var(--dees-color-text-primary);
}
.toolbar-button.active {
@@ -85,7 +87,7 @@ export const richtextStyles = [
.toolbar-divider {
width: 1px;
height: 24px;
background: ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
background: var(--dees-color-border-default);
margin: 0 4px;
}
@@ -99,7 +101,7 @@ export const richtextStyles = [
.editor-content .ProseMirror {
outline: none;
line-height: 1.6;
color: ${cssManager.bdTheme('hsl(0 0% 3.9%)', 'hsl(0 0% 98%)')};
color: var(--dees-color-text-primary);
min-height: 100%;
white-space: pre-wrap;
word-wrap: break-word;
@@ -149,7 +151,7 @@ export const richtextStyles = [
}
.editor-content .ProseMirror blockquote {
border-left: 4px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
border-left: 4px solid var(--dees-color-border-default);
margin: 1em 0;
padding-left: 1em;
color: ${cssManager.bdTheme('hsl(215.4 16.3% 46.9%)', 'hsl(215 20.2% 65.1%)')};
@@ -157,12 +159,12 @@ export const richtextStyles = [
}
.editor-content .ProseMirror code {
background: ${cssManager.bdTheme('hsl(0 0% 95.1%)', 'hsl(0 0% 14.9%)')};
background: var(--dees-color-bg-tertiary);
border-radius: 3px;
padding: 0.2em 0.4em;
font-family: 'Intel One Mono', 'Fira Code', 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
font-size: 0.9em;
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 93.9%)')};
color: var(--dees-color-text-primary);
}
.editor-content .ProseMirror pre {
@@ -195,7 +197,7 @@ export const richtextStyles = [
padding: 0 12px;
height: 28px;
font-size: 11px;
color: ${cssManager.bdTheme('hsl(0 0% 45%)', 'hsl(0 0% 55%)')};
color: var(--dees-color-text-muted);
display: flex;
justify-content: space-between;
align-items: center;
@@ -213,8 +215,8 @@ export const richtextStyles = [
top: 100%;
left: 0;
right: 0;
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 9%)')};
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
background: var(--dees-color-bg-primary);
border: 1px solid var(--dees-color-border-default);
border-radius: 6px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
padding: 12px;
@@ -228,12 +230,12 @@ export const richtextStyles = [
.link-input input {
width: 100%;
padding: 8px 12px;
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
border: 1px solid var(--dees-color-border-default);
border-radius: 6px;
outline: none;
font-size: 14px;
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 9%)')};
color: ${cssManager.bdTheme('hsl(0 0% 3.9%)', 'hsl(0 0% 98%)')};
background: var(--dees-color-bg-primary);
color: var(--dees-color-text-primary);
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
@@ -250,19 +252,19 @@ export const richtextStyles = [
.link-input-buttons button {
padding: 6px 12px;
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
border: 1px solid var(--dees-color-border-default);
border-radius: 4px;
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 9%)')};
background: var(--dees-color-bg-primary);
cursor: pointer;
font-size: 12px;
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
color: var(--dees-color-text-muted);
transition: all 0.15s ease;
font-weight: 500;
}
.link-input-buttons button:hover {
background: ${cssManager.bdTheme('hsl(0 0% 95.1%)', 'hsl(0 0% 14.9%)')};
color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 95%)')};
background: var(--dees-color-hover);
color: var(--dees-color-text-primary);
}
.link-input-buttons button.primary {

View File

@@ -56,7 +56,7 @@ export class DeesTile extends DeesElement {
display: flex;
flex-direction: column;
font-family: ${cssGeistFontFamily};
color: ${cssManager.bdTheme('hsl(0 0% 3.9%)', 'hsl(0 0% 98%)')};
color: var(--dees-color-text-primary);
}
/* --- The frame --- */
@@ -64,8 +64,8 @@ export class DeesTile extends DeesElement {
position: relative;
flex: 1;
min-height: 0;
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 3.9%)')};
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
background: var(--dees-color-bg-primary);
border: 1px solid var(--dees-color-border-default);
border-radius: 8px;
overflow: hidden;
display: flex;
@@ -84,7 +84,7 @@ export class DeesTile extends DeesElement {
font-size: 14px;
font-weight: 500;
letter-spacing: -0.01em;
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 63.9%)')};
color: var(--dees-color-text-secondary);
}
/* --- Content: the rounded inset --- */
@@ -92,8 +92,8 @@ export class DeesTile extends DeesElement {
flex: 1;
position: relative;
border-radius: 8px;
border-top: 1px solid ${cssManager.bdTheme('hsl(0 0% 93%)', 'hsl(0 0% 11%)')};
border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 93%)', 'hsl(0 0% 11%)')};
border-top: 1px solid var(--dees-color-border-subtle);
border-bottom: 1px solid var(--dees-color-border-subtle);
overflow: hidden;
}

View File

@@ -3,6 +3,7 @@ import { PdfManager } from '../dees-pdf-shared/PdfManager.js';
import { viewerStyles } from './styles.js';
import { demo as demoFunc } from './demo.js';
import '../../00group-utility/dees-icon/dees-icon.js';
import '../../00group-layout/dees-tile/dees-tile.js';
declare global {
interface HTMLElementTagNameMap {
@@ -33,6 +34,9 @@ export class DeesPdfViewer extends DeesElement {
@property({ type: Boolean })
accessor showSidebar: boolean = false;
@property({ type: String })
accessor sidebarPosition: 'left' | 'right' = 'left';
@property({ type: Number })
accessor currentPage: number = 1;
@@ -54,6 +58,9 @@ export class DeesPdfViewer extends DeesElement {
@property({ type: Array })
accessor pageData: Array<{page: number, rendered: boolean, rendering: boolean, textLayerRendered: boolean}> = [];
@property({ type: Number })
accessor pdfFileSize: number = 0;
private pdfDocument: any;
private renderState: RenderState = 'idle';
private renderAbortController: AbortController | null = null;
@@ -85,9 +92,9 @@ export class DeesPdfViewer extends DeesElement {
public render(): TemplateResult {
return html`
<div class="pdf-viewer ${this.showSidebar ? 'with-sidebar' : ''}">
<dees-tile class="${this.showSidebar ? 'with-sidebar' : ''} sidebar-${this.sidebarPosition}">
${this.showToolbar ? html`
<div class="toolbar">
<div slot="header" class="toolbar">
<div class="toolbar-group">
<button
class="toolbar-button"
@@ -240,7 +247,23 @@ export class DeesPdfViewer extends DeesElement {
`}
</div>
</div>
</div>
<div slot="footer" class="pdf-footer">
<div class="pdf-footer-left">
<span class="pdf-footer-item">Zoom ${Math.round(this.currentZoom * 100)}%</span>
${this.pdfFileSize > 0 ? html`
<span class="pdf-footer-item">${this.formatFileSize(this.pdfFileSize)}</span>
` : ''}
</div>
<div class="pdf-footer-center" style="margin-left: ${this.showSidebar && this.sidebarPosition === 'left' ? '100px' : this.showSidebar && this.sidebarPosition === 'right' ? '-100px' : '0'}">
<span>Page ${this.currentPage} of ${this.totalPages}</span>
</div>
<div class="pdf-footer-right">
${this.pdfUrl ? html`
<span class="pdf-footer-filename">${this.pdfUrl.split('/').pop()}</span>
` : ''}
</div>
</div>
</dees-tile>
`;
}
@@ -305,6 +328,12 @@ export class DeesPdfViewer extends DeesElement {
}
}
private formatFileSize(bytes: number): string {
if (bytes < 1024) return `${bytes} B`;
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}
private async loadPdf() {
this.loading = true;
this.renderState = 'loading';
@@ -323,6 +352,14 @@ export class DeesPdfViewer extends DeesElement {
this.currentPage = this.initialPage;
this.resolveInitialViewportMode();
// Get file size
try {
const data = await this.pdfDocument.getData();
this.pdfFileSize = data.length;
} catch (e) {
this.pdfFileSize = 0;
}
// Initialize thumbnail and page data arrays
this.thumbnailData = Array.from({length: this.totalPages}, (_, i) => ({
page: i + 1,
@@ -699,8 +736,8 @@ export class DeesPdfViewer extends DeesElement {
const viewerRect = this.viewerMain.getBoundingClientRect();
const currentScrollTop = this.viewerMain.scrollTop;
// Calculate the target scroll position
const targetScrollTop = currentScrollTop + (pageRect.top - viewerRect.top) - this.viewerMain.clientTop;
// Calculate the target scroll position (offset by 16px so page doesn't touch the top edge)
const targetScrollTop = currentScrollTop + (pageRect.top - viewerRect.top) - this.viewerMain.clientTop - 16;
// Scroll to the calculated position
if (smooth) {

View File

@@ -3,8 +3,8 @@ import { html } from '@design.estate/dees-element';
export const demo = () => html`
<style>
.demo-container {
padding: 40px;
background: #f5f5f5;
padding: 20px;
background: #000000;
}
.demo-section {
@@ -15,6 +15,7 @@ export const demo = () => html`
margin-bottom: 20px;
font-size: 18px;
font-weight: 600;
color: #fafafa;
}
dees-pdf-viewer {

View File

@@ -1,6 +1,8 @@
import { css, cssManager } from '@design.estate/dees-element';
import { themeDefaultStyles } from '../../00theme.js';
export const viewerStyles = [
themeDefaultStyles,
cssManager.defaultStyles,
css`
:host {
@@ -12,25 +14,47 @@ export const viewerStyles = [
contain: layout style;
}
.pdf-viewer {
width: 100%;
dees-tile {
height: 100%;
display: flex;
flex-direction: column;
background: ${cssManager.bdTheme('hsl(0 0% 97%)', 'hsl(215 20% 10%)')};
position: relative;
overflow: hidden;
}
.viewer-container::before,
.viewer-container::after {
content: '';
position: absolute;
left: 0;
right: 0;
height: 8px;
z-index: 5;
pointer-events: none;
}
.viewer-container::before {
top: 0;
background: linear-gradient(
to bottom,
${cssManager.bdTheme('hsl(0 0% 0% / 0.08)', 'hsl(0 0% 0% / 0.4)')},
${cssManager.bdTheme('hsl(0 0% 0% / 0.03)', 'hsl(0 0% 0% / 0.12)')},
transparent
);
}
.viewer-container::after {
bottom: 0;
background: linear-gradient(
to top,
${cssManager.bdTheme('hsl(0 0% 0% / 0.08)', 'hsl(0 0% 0% / 0.4)')},
${cssManager.bdTheme('hsl(0 0% 0% / 0.03)', 'hsl(0 0% 0% / 0.12)')},
transparent
);
}
.toolbar {
height: 48px;
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(215 20% 15%)')};
border-bottom: 1px solid ${cssManager.bdTheme('hsl(214 31% 91%)', 'hsl(217 25% 22%)')};
height: 40px;
display: flex;
align-items: center;
padding: 0 16px;
gap: 16px;
flex-shrink: 0;
padding: 0 12px;
gap: 12px;
}
.toolbar-group {
@@ -108,21 +132,27 @@ export const viewerStyles = [
}
.viewer-container {
flex: 1;
position: absolute;
inset: 0;
display: flex;
overflow: hidden;
position: relative;
min-height: 0;
}
.sidebar {
width: 200px;
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(215 20% 15%)')};
background: transparent;
border-right: 1px solid ${cssManager.bdTheme('hsl(214 31% 91%)', 'hsl(217 25% 22%)')};
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
order: 0;
}
.sidebar-right .sidebar {
border-right: none;
border-left: 1px solid ${cssManager.bdTheme('hsl(214 31% 91%)', 'hsl(217 25% 22%)')};
order: 1;
}
.sidebar-header {
@@ -334,5 +364,52 @@ export const viewerStyles = [
.pdf-viewer.with-sidebar .viewer-main {
margin-left: 0;
}
.pdf-footer {
height: 28px;
padding: 0 16px;
display: flex;
align-items: center;
font-size: 11px;
color: var(--dees-color-text-muted);
width: 100%;
box-sizing: border-box;
position: relative;
}
.pdf-footer-left {
display: flex;
align-items: center;
gap: 12px;
}
.pdf-footer-left .pdf-footer-item + .pdf-footer-item {
padding-left: 12px;
border-left: 1px solid var(--dees-color-border-default);
}
.pdf-footer-center {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-weight: 500;
transition: margin-left 0.15s ease;
}
.pdf-footer-right {
margin-left: auto;
}
.pdf-footer-item {
white-space: nowrap;
}
.pdf-footer-filename {
font-family: 'Intel One Mono', 'Geist Mono', monospace;
opacity: 0.7;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
`,
];

View File

@@ -8,22 +8,22 @@ import {
type TemplateResult,
type CSSResult,
} from '@design.estate/dees-element';
import { DeesTileBase } from '../dees-tile-shared/DeesTileBase.js';
import { tileBaseStyles } from '../dees-tile-shared/styles.js';
import { DeesThumbnailBase } from '../dees-thumbnail-shared/DeesThumbnailBase.js';
import { thumbnailBaseStyles } from '../dees-thumbnail-shared/styles.js';
import { demo } from './demo.js';
declare global {
interface HTMLElementTagNameMap {
'dees-tile-audio': DeesTileAudio;
'dees-thumbnail-audio': DeesThumbnailAudio;
}
}
@customElement('dees-tile-audio')
export class DeesTileAudio extends DeesTileBase {
@customElement('dees-thumbnail-audio')
export class DeesThumbnailAudio extends DeesThumbnailBase {
public static demo = demo;
public static demoGroups = ['Media'];
public static styles = [
...tileBaseStyles,
...thumbnailBaseStyles,
css`
.audio-content {
position: relative;

View File

@@ -26,51 +26,51 @@ export const demo = () => html`
<div class="demo-section">
<h3>Audio Tiles</h3>
<div class="tile-row">
<dees-tile-audio
<dees-thumbnail-audio
src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3"
title="SoundHelix Song 1"
artist="T. Schuerger"
label="soundhelix-1.mp3"
@tile-click=${(e: CustomEvent) => console.log('Audio clicked:', e.detail)}
></dees-tile-audio>
></dees-thumbnail-audio>
<dees-tile-audio
<dees-thumbnail-audio
src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3"
title="SoundHelix Song 2"
artist="T. Schuerger"
label="soundhelix-2.mp3"
></dees-tile-audio>
></dees-thumbnail-audio>
<dees-tile-audio
<dees-thumbnail-audio
src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-3.mp3"
title="SoundHelix Song 3"
label="soundhelix-3.mp3"
></dees-tile-audio>
></dees-thumbnail-audio>
</div>
</div>
<div class="demo-section">
<h3>Size Variants</h3>
<div class="tile-row">
<dees-tile-audio
<dees-thumbnail-audio
size="small"
src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3"
title="Small"
label="small.mp3"
></dees-tile-audio>
></dees-thumbnail-audio>
<dees-tile-audio
<dees-thumbnail-audio
src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3"
title="Default"
label="default.mp3"
></dees-tile-audio>
></dees-thumbnail-audio>
<dees-tile-audio
<dees-thumbnail-audio
size="large"
src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3"
title="Large"
label="large.mp3"
></dees-tile-audio>
></dees-thumbnail-audio>
</div>
</div>
</div>

View File

@@ -7,11 +7,11 @@ import {
type TemplateResult,
type CSSResult,
} from '@design.estate/dees-element';
import { DeesTileBase } from '../dees-tile-shared/DeesTileBase.js';
import { tileBaseStyles } from '../dees-tile-shared/styles.js';
import { DeesThumbnailBase } from '../dees-thumbnail-shared/DeesThumbnailBase.js';
import { thumbnailBaseStyles } from '../dees-thumbnail-shared/styles.js';
import { demo } from './demo.js';
export interface ITileFolderItem {
export interface IThumbnailFolderItem {
type: 'pdf' | 'image' | 'audio' | 'video' | 'note' | 'folder' | 'unknown';
thumbnailSrc?: string;
name: string;
@@ -29,16 +29,16 @@ const TYPE_ICON_MAP: Record<string, string> = {
declare global {
interface HTMLElementTagNameMap {
'dees-tile-folder': DeesTileFolder;
'dees-thumbnail-folder': DeesThumbnailFolder;
}
}
@customElement('dees-tile-folder')
export class DeesTileFolder extends DeesTileBase {
@customElement('dees-thumbnail-folder')
export class DeesThumbnailFolder extends DeesThumbnailBase {
public static demo = demo;
public static demoGroups = ['Media'];
public static styles = [
...tileBaseStyles,
...thumbnailBaseStyles,
css`
.folder-content {
position: relative;
@@ -116,7 +116,7 @@ export class DeesTileFolder extends DeesTileBase {
accessor name: string = '';
@property({ attribute: false })
accessor items: ITileFolderItem[] = [];
accessor items: IThumbnailFolderItem[] = [];
protected renderTileContent(): TemplateResult {
const previewItems = this.items.slice(0, 4);

View File

@@ -1,8 +1,8 @@
import { html } from '@design.estate/dees-element';
import type { ITileFolderItem } from './component.js';
import type { IThumbnailFolderItem } from './component.js';
export const demo = () => {
const photosFolder: ITileFolderItem[] = [
const photosFolder: IThumbnailFolderItem[] = [
{ type: 'image', name: 'sunset.jpg', thumbnailSrc: 'https://picsum.photos/200/200?random=1' },
{ type: 'image', name: 'mountain.jpg', thumbnailSrc: 'https://picsum.photos/200/200?random=2' },
{ type: 'image', name: 'ocean.jpg', thumbnailSrc: 'https://picsum.photos/200/200?random=3' },
@@ -11,7 +11,7 @@ export const demo = () => {
{ type: 'image', name: 'desert.jpg', thumbnailSrc: 'https://picsum.photos/200/200?random=6' },
];
const projectFolder: ITileFolderItem[] = [
const projectFolder: IThumbnailFolderItem[] = [
{ type: 'note', name: 'README.md' },
{ type: 'note', name: 'package.json' },
{ type: 'folder', name: 'src' },
@@ -21,16 +21,16 @@ export const demo = () => {
{ type: 'image', name: 'logo.png', thumbnailSrc: 'https://picsum.photos/100/100?random=10' },
];
const mediaFolder: ITileFolderItem[] = [
const mediaFolder: IThumbnailFolderItem[] = [
{ type: 'video', name: 'intro.mp4' },
{ type: 'audio', name: 'background.mp3' },
{ type: 'image', name: 'thumbnail.jpg', thumbnailSrc: 'https://picsum.photos/200/200?random=20' },
{ type: 'pdf', name: 'storyboard.pdf' },
];
const emptyFolder: ITileFolderItem[] = [];
const emptyFolder: IThumbnailFolderItem[] = [];
const singleItemFolder: ITileFolderItem[] = [
const singleItemFolder: IThumbnailFolderItem[] = [
{ type: 'pdf', name: 'report.pdf' },
];
@@ -60,61 +60,61 @@ export const demo = () => {
<div class="demo-section">
<h3>Folder Tiles</h3>
<div class="tile-row">
<dees-tile-folder
<dees-thumbnail-folder
name="Photos"
.items=${photosFolder}
label="6 photos"
@tile-click=${(e: CustomEvent) => console.log('Folder clicked:', e.detail)}
></dees-tile-folder>
></dees-thumbnail-folder>
<dees-tile-folder
<dees-thumbnail-folder
name="my-project"
.items=${projectFolder}
label="Project files"
></dees-tile-folder>
></dees-thumbnail-folder>
<dees-tile-folder
<dees-thumbnail-folder
name="Media Assets"
.items=${mediaFolder}
label="Mixed media"
></dees-tile-folder>
></dees-thumbnail-folder>
</div>
</div>
<div class="demo-section">
<h3>Edge Cases</h3>
<div class="tile-row">
<dees-tile-folder
<dees-thumbnail-folder
name="Empty Folder"
.items=${emptyFolder}
></dees-tile-folder>
></dees-thumbnail-folder>
<dees-tile-folder
<dees-thumbnail-folder
name="Single Item"
.items=${singleItemFolder}
></dees-tile-folder>
></dees-thumbnail-folder>
</div>
</div>
<div class="demo-section">
<h3>Size Variants</h3>
<div class="tile-row">
<dees-tile-folder
<dees-thumbnail-folder
size="small"
name="Small"
.items=${photosFolder}
></dees-tile-folder>
></dees-thumbnail-folder>
<dees-tile-folder
<dees-thumbnail-folder
name="Default"
.items=${photosFolder}
></dees-tile-folder>
></dees-thumbnail-folder>
<dees-tile-folder
<dees-thumbnail-folder
size="large"
name="Large"
.items=${photosFolder}
></dees-tile-folder>
></dees-thumbnail-folder>
</div>
</div>
</div>

View File

@@ -8,22 +8,22 @@ import {
type TemplateResult,
type CSSResult,
} from '@design.estate/dees-element';
import { DeesTileBase } from '../dees-tile-shared/DeesTileBase.js';
import { tileBaseStyles } from '../dees-tile-shared/styles.js';
import { DeesThumbnailBase } from '../dees-thumbnail-shared/DeesThumbnailBase.js';
import { thumbnailBaseStyles } from '../dees-thumbnail-shared/styles.js';
import { demo } from './demo.js';
declare global {
interface HTMLElementTagNameMap {
'dees-tile-image': DeesTileImage;
'dees-thumbnail-image': DeesThumbnailImage;
}
}
@customElement('dees-tile-image')
export class DeesTileImage extends DeesTileBase {
@customElement('dees-thumbnail-image')
export class DeesThumbnailImage extends DeesThumbnailBase {
public static demo = demo;
public static demoGroups = ['Media'];
public static styles = [
...tileBaseStyles,
...thumbnailBaseStyles,
css`
.image-wrapper {
position: relative;

View File

@@ -26,59 +26,59 @@ export const demo = () => html`
<div class="demo-section">
<h3>Image Tiles</h3>
<div class="tile-row">
<dees-tile-image
<dees-thumbnail-image
src="https://picsum.photos/800/600"
alt="Landscape photo"
label="landscape.jpg"
@tile-click=${(e: CustomEvent) => console.log('Image clicked:', e.detail)}
></dees-tile-image>
></dees-thumbnail-image>
<dees-tile-image
<dees-thumbnail-image
src="https://picsum.photos/400/400"
alt="Square photo"
label="square.png"
></dees-tile-image>
></dees-thumbnail-image>
<dees-tile-image
<dees-thumbnail-image
src="https://picsum.photos/300/900"
alt="Portrait photo"
label="portrait.webp"
></dees-tile-image>
></dees-thumbnail-image>
</div>
</div>
<div class="demo-section">
<h3>Size Variants</h3>
<div class="tile-row">
<dees-tile-image
<dees-thumbnail-image
size="small"
src="https://picsum.photos/200/200"
alt="Small"
label="small.jpg"
></dees-tile-image>
></dees-thumbnail-image>
<dees-tile-image
<dees-thumbnail-image
src="https://picsum.photos/600/400"
alt="Default"
label="default.jpg"
></dees-tile-image>
></dees-thumbnail-image>
<dees-tile-image
<dees-thumbnail-image
size="large"
src="https://picsum.photos/1200/800"
alt="Large"
label="large.jpg"
></dees-tile-image>
></dees-thumbnail-image>
</div>
</div>
<div class="demo-section">
<h3>Error State (broken URL)</h3>
<dees-tile-image
<dees-thumbnail-image
src="https://invalid-url-that-does-not-exist.example/image.png"
alt="Broken"
label="broken.png"
></dees-tile-image>
></dees-thumbnail-image>
</div>
</div>
`;

View File

@@ -0,0 +1 @@
export * from './component.js';

View File

@@ -8,22 +8,22 @@ import {
type TemplateResult,
type CSSResult,
} from '@design.estate/dees-element';
import { DeesTileBase } from '../dees-tile-shared/DeesTileBase.js';
import { tileBaseStyles } from '../dees-tile-shared/styles.js';
import { DeesThumbnailBase } from '../dees-thumbnail-shared/DeesThumbnailBase.js';
import { thumbnailBaseStyles } from '../dees-thumbnail-shared/styles.js';
import { demo } from './demo.js';
declare global {
interface HTMLElementTagNameMap {
'dees-tile-note': DeesTileNote;
'dees-thumbnail-note': DeesThumbnailNote;
}
}
@customElement('dees-tile-note')
export class DeesTileNote extends DeesTileBase {
@customElement('dees-thumbnail-note')
export class DeesThumbnailNote extends DeesThumbnailBase {
public static demo = demo;
public static demoGroups = ['Media'];
public static styles = [
...tileBaseStyles,
...thumbnailBaseStyles,
css`
.note-content {
position: relative;

View File

@@ -72,63 +72,63 @@ Action Items:
<div class="demo-section">
<h3>Note Tiles</h3>
<div class="tile-row">
<dees-tile-note
<dees-thumbnail-note
title="component.ts"
.content=${sampleCode}
language="typescript"
label="component.ts"
@tile-click=${(e: CustomEvent) => console.log('Note clicked:', e.detail)}
></dees-tile-note>
></dees-thumbnail-note>
<dees-tile-note
<dees-thumbnail-note
title="Meeting Notes"
.content=${sampleText}
label="meeting-notes.txt"
></dees-tile-note>
></dees-thumbnail-note>
<dees-tile-note
<dees-thumbnail-note
title="package.json"
.content=${sampleJson}
language="json"
label="package.json"
></dees-tile-note>
></dees-thumbnail-note>
</div>
</div>
<div class="demo-section">
<h3>Size Variants</h3>
<div class="tile-row">
<dees-tile-note
<dees-thumbnail-note
size="small"
title="small.ts"
.content=${sampleCode}
language="ts"
label="small.ts"
></dees-tile-note>
></dees-thumbnail-note>
<dees-tile-note
<dees-thumbnail-note
title="default.ts"
.content=${sampleCode}
language="ts"
label="default.ts"
></dees-tile-note>
></dees-thumbnail-note>
<dees-tile-note
<dees-thumbnail-note
size="large"
title="large.ts"
.content=${sampleCode}
language="ts"
label="large.ts"
></dees-tile-note>
></dees-thumbnail-note>
</div>
</div>
<div class="demo-section">
<h3>Without Title</h3>
<dees-tile-note
<dees-thumbnail-note
.content=${sampleText}
label="untitled.txt"
></dees-tile-note>
></dees-thumbnail-note>
</div>
</div>
`;

View File

@@ -0,0 +1 @@
export * from './component.js';

View File

@@ -1,6 +1,6 @@
import { property, state, html, customElement, type TemplateResult, type CSSResult } from '@design.estate/dees-element';
import { DeesTileBase } from '../dees-tile-shared/DeesTileBase.js';
import { tileBaseStyles } from '../dees-tile-shared/styles.js';
import { DeesThumbnailBase } from '../dees-thumbnail-shared/DeesThumbnailBase.js';
import { thumbnailBaseStyles } from '../dees-thumbnail-shared/styles.js';
import { PdfManager } from '../dees-pdf-shared/PdfManager.js';
import { CanvasPool, type PooledCanvas } from '../dees-pdf-shared/CanvasPool.js';
import { PerformanceMonitor, throttle, formatFileSize } from '../dees-pdf-shared/utils.js';
@@ -9,15 +9,15 @@ import { demo as demoFunc } from './demo.js';
declare global {
interface HTMLElementTagNameMap {
'dees-tile-pdf': DeesTilePdf;
'dees-thumbnail-pdf': DeesThumbnailPdf;
}
}
@customElement('dees-tile-pdf')
export class DeesTilePdf extends DeesTileBase {
@customElement('dees-thumbnail-pdf')
export class DeesThumbnailPdf extends DeesThumbnailBase {
public static demo = demoFunc;
public static demoGroups = ['Media', 'PDF'];
public static styles = [...tileBaseStyles, tilePdfStyles] as any;
public static styles = [...thumbnailBaseStyles, tilePdfStyles] as any;
@property({ type: String })
accessor pdfUrl: string = '';

View File

@@ -11,7 +11,7 @@ export const demo = () => {
for (let i = 0; i < count; i++) {
const pdfUrl = samplePdfs[i % samplePdfs.length];
items.push(html`
<dees-tile-pdf
<dees-thumbnail-pdf
pdfUrl="${pdfUrl}"
clickable="true"
grid-mode
@@ -19,7 +19,7 @@ export const demo = () => {
console.log('PDF Tile clicked:', e.detail);
alert(`PDF clicked: ${e.detail.pageCount} pages`);
}}
></dees-tile-pdf>
></dees-thumbnail-pdf>
`);
}
return items;
@@ -67,56 +67,56 @@ export const demo = () => {
<div class="demo-container">
<div class="demo-section">
<h3>Single PDF Tile</h3>
<dees-tile-pdf
<dees-thumbnail-pdf
pdfUrl="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf"
clickable="true"
></dees-tile-pdf>
></dees-thumbnail-pdf>
</div>
<div class="demo-section">
<h3>Different Sizes</h3>
<div class="preview-row">
<div class="preview-label">Small:</div>
<dees-tile-pdf
<dees-thumbnail-pdf
size="small"
pdfUrl="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/examples/learning/helloworld.pdf"
clickable="true"
></dees-tile-pdf>
></dees-thumbnail-pdf>
</div>
<div class="preview-row">
<div class="preview-label">Default:</div>
<dees-tile-pdf
<dees-thumbnail-pdf
pdfUrl="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/examples/learning/helloworld.pdf"
clickable="true"
></dees-tile-pdf>
></dees-thumbnail-pdf>
</div>
<div class="preview-row">
<div class="preview-label">Large:</div>
<dees-tile-pdf
<dees-thumbnail-pdf
size="large"
pdfUrl="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/examples/learning/helloworld.pdf"
clickable="true"
></dees-tile-pdf>
></dees-thumbnail-pdf>
</div>
</div>
<div class="demo-section">
<h3>With Label</h3>
<dees-tile-pdf
<dees-thumbnail-pdf
pdfUrl="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf"
clickable="true"
label="Research Paper.pdf"
></dees-tile-pdf>
></dees-thumbnail-pdf>
</div>
<div class="demo-section">
<h3>Non-Clickable</h3>
<dees-tile-pdf
<dees-thumbnail-pdf
pdfUrl="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/examples/learning/helloworld.pdf"
clickable="false"
></dees-tile-pdf>
></dees-thumbnail-pdf>
</div>
<div class="demo-section">

View File

@@ -0,0 +1 @@
export * from './component.js';

View File

@@ -5,11 +5,11 @@ import {
type TemplateResult,
type CSSResult,
} from '@design.estate/dees-element';
import { tileBaseStyles } from './styles.js';
import { thumbnailBaseStyles } from './styles.js';
import '../../00group-utility/dees-icon/dees-icon.js';
export abstract class DeesTileBase extends DeesElement {
public static styles: CSSResult[] = tileBaseStyles as any;
export abstract class DeesThumbnailBase extends DeesElement {
public static styles: CSSResult[] = thumbnailBaseStyles as any;
@property({ type: Boolean })
accessor clickable: boolean = true;

View File

@@ -0,0 +1,2 @@
export { DeesThumbnailBase } from './DeesThumbnailBase.js';
export { thumbnailBaseStyles } from './styles.js';

View File

@@ -1,6 +1,6 @@
import { css, cssManager } from '@design.estate/dees-element';
export const tileBaseStyles = [
export const thumbnailBaseStyles = [
cssManager.defaultStyles,
css`
:host {

View File

@@ -8,22 +8,22 @@ import {
type TemplateResult,
type CSSResult,
} from '@design.estate/dees-element';
import { DeesTileBase } from '../dees-tile-shared/DeesTileBase.js';
import { tileBaseStyles } from '../dees-tile-shared/styles.js';
import { DeesThumbnailBase } from '../dees-thumbnail-shared/DeesThumbnailBase.js';
import { thumbnailBaseStyles } from '../dees-thumbnail-shared/styles.js';
import { demo } from './demo.js';
declare global {
interface HTMLElementTagNameMap {
'dees-tile-video': DeesTileVideo;
'dees-thumbnail-video': DeesThumbnailVideo;
}
}
@customElement('dees-tile-video')
export class DeesTileVideo extends DeesTileBase {
@customElement('dees-thumbnail-video')
export class DeesThumbnailVideo extends DeesThumbnailBase {
public static demo = demo;
public static demoGroups = ['Media'];
public static styles = [
...tileBaseStyles,
...thumbnailBaseStyles,
css`
.video-wrapper {
position: relative;

View File

@@ -26,54 +26,54 @@ export const demo = () => html`
<div class="demo-section">
<h3>Video Tiles</h3>
<div class="tile-row">
<dees-tile-video
<dees-thumbnail-video
src="https://www.w3schools.com/html/mov_bbb.mp4"
label="bunny.mp4"
@tile-click=${(e: CustomEvent) => console.log('Video clicked:', e.detail)}
></dees-tile-video>
></dees-thumbnail-video>
<dees-tile-video
<dees-thumbnail-video
src="https://www.w3schools.com/html/movie.mp4"
poster="https://picsum.photos/400/300"
label="movie.mp4"
></dees-tile-video>
></dees-thumbnail-video>
<dees-tile-video
<dees-thumbnail-video
src="https://www.w3schools.com/html/mov_bbb.mp4"
label="another-video.mp4"
></dees-tile-video>
></dees-thumbnail-video>
</div>
</div>
<div class="demo-section">
<h3>Size Variants</h3>
<div class="tile-row">
<dees-tile-video
<dees-thumbnail-video
size="small"
src="https://www.w3schools.com/html/mov_bbb.mp4"
label="small.mp4"
></dees-tile-video>
></dees-thumbnail-video>
<dees-tile-video
<dees-thumbnail-video
src="https://www.w3schools.com/html/mov_bbb.mp4"
label="default.mp4"
></dees-tile-video>
></dees-thumbnail-video>
<dees-tile-video
<dees-thumbnail-video
size="large"
src="https://www.w3schools.com/html/mov_bbb.mp4"
label="large.mp4"
></dees-tile-video>
></dees-thumbnail-video>
</div>
</div>
<div class="demo-section">
<h3>With Poster Image</h3>
<dees-tile-video
<dees-thumbnail-video
src="https://www.w3schools.com/html/movie.mp4"
poster="https://picsum.photos/600/400"
label="poster-video.mp4"
></dees-tile-video>
></dees-thumbnail-video>
</div>
</div>
`;

View File

@@ -0,0 +1 @@
export * from './component.js';

View File

@@ -1,2 +0,0 @@
export { DeesTileBase } from './DeesTileBase.js';
export { tileBaseStyles } from './styles.js';

View File

@@ -8,11 +8,11 @@ export * from './dees-preview/index.js';
export * from './dees-pdf-shared/index.js';
export * from './dees-pdf-viewer/index.js';
// Tile Components
export * from './dees-tile-shared/index.js';
export * from './dees-tile-pdf/index.js';
export * from './dees-tile-image/index.js';
export * from './dees-tile-audio/index.js';
export * from './dees-tile-video/index.js';
export * from './dees-tile-note/index.js';
export * from './dees-tile-folder/index.js';
// Thumbnail Components
export * from './dees-thumbnail-shared/index.js';
export * from './dees-thumbnail-pdf/index.js';
export * from './dees-thumbnail-image/index.js';
export * from './dees-thumbnail-audio/index.js';
export * from './dees-thumbnail-video/index.js';
export * from './dees-thumbnail-note/index.js';
export * from './dees-thumbnail-folder/index.js';

View File

@@ -129,7 +129,7 @@ export class DeesModal extends DeesElement {
/* TODO: Migrate hardcoded values to --dees-* CSS variables */
:host {
font-family: ${cssGeistFontFamily};
color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 95%)')};
color: var(--dees-color-text-primary);
}
.modalContainer {
display: flex;
@@ -231,7 +231,7 @@ export class DeesModal extends DeesElement {
font-weight: 500;
font-size: 13px;
letter-spacing: -0.01em;
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 63.9%)')};
color: var(--dees-color-text-secondary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@@ -255,12 +255,12 @@ export class DeesModal extends DeesElement {
cursor: pointer;
transition: all 0.15s ease;
background: transparent;
color: ${cssManager.bdTheme('hsl(0 0% 55%)', 'hsl(0 0% 45%)')};
color: var(--dees-color-text-muted);
}
.heading .header-button:hover {
background: ${cssManager.bdTheme('hsl(0 0% 93%)', 'hsl(0 0% 12%)')};
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 90%)')};
background: var(--dees-color-hover);
color: var(--dees-color-text-secondary);
}
.heading .header-button:active {
@@ -278,7 +278,7 @@ export class DeesModal extends DeesElement {
overflow-x: hidden;
overscroll-behavior: contain;
scrollbar-width: thin;
scrollbar-color: ${cssManager.bdTheme('hsl(0 0% 85%)', 'hsl(0 0% 20%)')} transparent;
scrollbar-color: var(--dees-color-scrollbar-thumb) transparent;
}
.bottomButtons {
display: flex;
@@ -302,8 +302,8 @@ export class DeesModal extends DeesElement {
transition: all 0.15s ease;
background: transparent;
border: none;
border-left: 1px solid ${cssManager.bdTheme('hsl(0 0% 93%)', 'hsl(0 0% 11%)')};
color: ${cssManager.bdTheme('hsl(0 0% 45%)', 'hsl(0 0% 55%)')};
border-left: 1px solid var(--dees-color-border-subtle);
color: var(--dees-color-text-muted);
white-space: nowrap;
display: flex;
align-items: center;
@@ -314,8 +314,8 @@ export class DeesModal extends DeesElement {
}
.bottomButtons .bottomButton:hover {
background: ${cssManager.bdTheme('hsl(0 0% 95%)', 'hsl(0 0% 10%)')};
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 90%)')};
background: var(--dees-color-hover);
color: var(--dees-color-text-primary);
}
.bottomButtons .bottomButton:active {

View File

@@ -67,7 +67,7 @@ export class DeesShoppingProductcard extends DeesElement {
}
dees-tile:hover::part(outer) {
border-color: ${cssManager.bdTheme('hsl(0 0% 79.8%)', 'hsl(0 0% 20.9%)')};
border-color: var(--dees-color-border-strong);
box-shadow: 0 4px 6px -1px hsl(0 0% 0% / 0.1), 0 2px 4px -2px hsl(0 0% 0% / 0.1);
}
@@ -148,7 +148,7 @@ export class DeesShoppingProductcard extends DeesElement {
.product-name {
font-size: 14px;
font-weight: 500;
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 63.9%)')};
color: var(--dees-color-text-secondary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@@ -204,7 +204,7 @@ export class DeesShoppingProductcard extends DeesElement {
.price-current {
font-size: 20px;
font-weight: 600;
color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 95%)')};
color: var(--dees-color-text-primary);
}
.price-original {

View File

@@ -76,9 +76,8 @@ export class DeesSimpleAppDash extends DeesElement {
themeDefaultStyles,
cssManager.defaultStyles,
css`
/* TODO: Migrate hardcoded values to --dees-* CSS variables */
:host {
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 90%)')};
color: var(--dees-color-text-primary);
user-select: none;
display: block;
overflow: hidden;
@@ -102,8 +101,8 @@ export class DeesSimpleAppDash extends DeesElement {
left: 0px;
height: calc(100% - 24px);
width: 240px;
background: ${cssManager.bdTheme('hsl(0 0% 99%)', 'hsl(0 0% 7%)')};
border-right: 1px solid ${cssManager.bdTheme('hsl(0 0% 91%)', 'hsl(0 0% 13%)')};
background: var(--dees-color-bg-secondary);
border-right: 1px solid var(--dees-color-border-default);
font-size: 13px;
font-family: 'Geist Sans', sans-serif;
z-index: 2;
@@ -114,7 +113,7 @@ export class DeesSimpleAppDash extends DeesElement {
.sidebar-header {
padding: 20px 16px;
border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 91%)', 'hsl(0 0% 13%)')};
border-bottom: 1px solid var(--dees-color-border-default);
display: flex;
align-items: center;
gap: 12px;
@@ -127,25 +126,22 @@ export class DeesSimpleAppDash extends DeesElement {
width: 36px;
height: 36px;
border-radius: 10px;
background: ${cssManager.bdTheme(
'linear-gradient(135deg, hsl(215 20% 95%) 0%, hsl(215 20% 90%) 100%)',
'linear-gradient(135deg, hsl(215 20% 18%) 0%, hsl(215 20% 14%) 100%)'
)};
background: var(--dees-color-bg-tertiary);
box-shadow: ${cssManager.bdTheme(
'0 1px 2px rgb(0 0 0 / 0.05), inset 0 1px 0 rgb(255 255 255 / 0.5)',
'0 1px 2px rgb(0 0 0 / 0.2), inset 0 1px 0 rgb(255 255 255 / 0.05)'
'0 1px 2px rgb(0 0 0 / 0.05)',
'0 1px 2px rgb(0 0 0 / 0.2)'
)};
}
.header-icon-wrapper dees-icon {
font-size: 18px;
color: ${cssManager.bdTheme('hsl(215 20% 40%)', 'hsl(215 20% 70%)')};
color: var(--dees-color-text-primary);
}
.appName {
font-size: 15px;
font-weight: 600;
color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 98%)')};
color: var(--dees-color-text-primary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@@ -156,7 +152,7 @@ export class DeesSimpleAppDash extends DeesElement {
overflow-y: auto;
padding: 12px 8px;
scrollbar-width: thin;
scrollbar-color: ${cssManager.bdTheme('hsl(0 0% 85%)', 'hsl(0 0% 20%)')} transparent;
scrollbar-color: var(--dees-color-scrollbar-thumb) transparent;
}
.viewTabs-container::-webkit-scrollbar {
@@ -168,12 +164,12 @@ export class DeesSimpleAppDash extends DeesElement {
}
.viewTabs-container::-webkit-scrollbar-thumb {
background: ${cssManager.bdTheme('hsl(0 0% 85%)', 'hsl(0 0% 20%)')};
background: var(--dees-color-scrollbar-thumb);
border-radius: 3px;
}
.viewTabs-container::-webkit-scrollbar-thumb:hover {
background: ${cssManager.bdTheme('hsl(0 0% 75%)', 'hsl(0 0% 30%)')};
background: var(--dees-color-scrollbar-thumb-hover);
}
.section-label {
@@ -181,7 +177,7 @@ export class DeesSimpleAppDash extends DeesElement {
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
color: ${cssManager.bdTheme('hsl(0 0% 50%)', 'hsl(0 0% 50%)')};
color: var(--dees-color-text-muted);
padding: 8px 12px 8px;
margin-bottom: 4px;
}
@@ -199,25 +195,25 @@ export class DeesSimpleAppDash extends DeesElement {
padding: 10px 12px;
cursor: default;
transition: all 0.15s ease;
color: ${cssManager.bdTheme('hsl(0 0% 40%)', 'hsl(0 0% 65%)')};
color: var(--dees-color-text-secondary);
user-select: none;
position: relative;
border-radius: 8px;
}
.viewTab:hover {
background: ${cssManager.bdTheme('hsl(0 0% 0% / 0.04)', 'hsl(0 0% 100% / 0.05)')};
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 90%)')};
background: var(--dees-color-hover);
color: ${cssManager.bdTheme('#262626', '#e5e5e5')};
}
.viewTab:active {
background: ${cssManager.bdTheme('hsl(0 0% 0% / 0.06)', 'hsl(0 0% 100% / 0.07)')};
background: var(--dees-color-active);
transform: scale(0.99);
}
.viewTab.selected {
background: ${cssManager.bdTheme('hsl(215 25% 95%)', 'hsl(215 20% 15%)')};
color: ${cssManager.bdTheme('hsl(215 25% 30%)', 'hsl(215 25% 85%)')};
background: var(--dees-color-active);
color: var(--dees-color-text-primary);
font-weight: 500;
}
@@ -229,7 +225,7 @@ export class DeesSimpleAppDash extends DeesElement {
bottom: 8px;
width: 3px;
border-radius: 0 2px 2px 0;
background: ${cssManager.bdTheme('hsl(215 70% 50%)', 'hsl(215 70% 60%)')};
background: var(--dees-color-text-primary);
}
.viewTab dees-icon {
@@ -243,8 +239,8 @@ export class DeesSimpleAppDash extends DeesElement {
}
.viewTab.selected dees-icon {
opacity: 0.9;
color: ${cssManager.bdTheme('hsl(215 70% 45%)', 'hsl(215 70% 65%)')};
opacity: 1;
color: var(--dees-color-text-primary);
}
.viewTab span {
@@ -256,7 +252,7 @@ export class DeesSimpleAppDash extends DeesElement {
.appActions {
padding: 12px 8px;
border-top: 1px solid ${cssManager.bdTheme('hsl(0 0% 91%)', 'hsl(0 0% 13%)')};
border-top: 1px solid var(--dees-color-border-default);
}
.action {
@@ -267,7 +263,7 @@ export class DeesSimpleAppDash extends DeesElement {
border-radius: 8px;
cursor: default;
transition: all 0.15s ease;
color: ${cssManager.bdTheme('hsl(0 0% 40%)', 'hsl(0 0% 65%)')};
color: var(--dees-color-text-secondary);
}
.action:hover {
@@ -295,7 +291,7 @@ export class DeesSimpleAppDash extends DeesElement {
bottom: 24px;
width: calc(100% - 240px);
overflow: auto;
background: ${cssManager.bdTheme('hsl(0 0% 97%)', 'hsl(0 0% 5%)')};
background: var(--dees-color-bg-secondary);
overscroll-behavior: contain;
}
@@ -335,14 +331,14 @@ export class DeesSimpleAppDash extends DeesElement {
}
.controlbar {
color: ${cssManager.bdTheme('hsl(0 0% 45%)', 'hsl(0 0% 55%)')};
color: var(--dees-color-text-muted);
position: absolute;
bottom: 0px;
left: 0px;
width: 100%;
height: 24px;
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 3.9%)')};
border-top: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
background: var(--dees-color-bg-tertiary);
border-top: 1px solid var(--dees-color-border-default);
z-index: 11;
display: flex;
justify-content: flex-end;
@@ -361,9 +357,9 @@ export class DeesSimpleAppDash extends DeesElement {
height: 100%;
white-space: nowrap;
cursor: default;
color: ${cssManager.bdTheme('hsl(0 0% 55%)', 'hsl(0 0% 50%)')};
color: var(--dees-color-text-muted);
transition: all 0.15s ease;
border-left: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
border-left: 1px solid var(--dees-color-border-strong);
}
@@ -372,8 +368,8 @@ export class DeesSimpleAppDash extends DeesElement {
}
.control:hover {
background: ${cssManager.bdTheme('hsl(0 0% 0% / 0.04)', 'hsl(0 0% 100% / 0.06)')};
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 90%)')};
background: var(--dees-color-hover);
color: var(--dees-color-text-primary);
}
.control dees-icon {
@@ -381,11 +377,11 @@ export class DeesSimpleAppDash extends DeesElement {
}
.control.status-connected dees-icon {
color: hsl(142 70% 50%);
color: ${cssManager.bdTheme('hsl(142 70% 35%)', 'hsl(142 70% 50%)')};
}
.control.status-terminal dees-icon {
color: hsl(45 90% 55%);
color: ${cssManager.bdTheme('hsl(38 92% 45%)', 'hsl(38 92% 55%)')};
}
/* Global Message Banners */
@@ -408,7 +404,7 @@ export class DeesSimpleAppDash extends DeesElement {
font-size: 13px;
font-family: 'Geist Sans', sans-serif;
font-weight: 500;
border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 91%)', 'hsl(0 0% 13%)')};
border-bottom: 1px solid var(--dees-color-border-default);
animation: bannerSlideDown 0.25s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

View File

@@ -31,9 +31,8 @@ export class DeesSimpleLogin extends DeesElement {
themeDefaultStyles,
cssManager.defaultStyles,
css`
/* TODO: Migrate hardcoded values to --dees-* CSS variables */
:host {
color: ${cssManager.bdTheme('hsl(0 0% 3.9%)', 'hsl(0 0% 98%)')};
color: var(--dees-color-text-primary);
user-select: none;
display: block;
width: 100%;
@@ -50,7 +49,7 @@ export class DeesSimpleLogin extends DeesElement {
height: 100%;
top: 0;
left: 0;
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 3.9%)')};
background: var(--dees-color-bg-primary);
}
.slotContainer {
@@ -83,17 +82,17 @@ export class DeesSimpleLogin extends DeesElement {
font-size: 24px;
font-weight: 600;
letter-spacing: -0.025em;
color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 98%)')};
color: var(--dees-color-text-primary);
}
.subheader {
font-size: 14px;
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
color: var(--dees-color-text-muted);
}
.login-card {
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 9%)')};
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
background: var(--dees-color-bg-primary);
border: 1px solid var(--dees-color-border-default);
border-radius: 8px;
padding: 24px;
}

View File

@@ -81,15 +81,15 @@ export class DeesWorkspaceTerminalPreview extends DeesElement {
height: 32px;
font-size: 12px;
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', monospace;
color: ${cssManager.bdTheme('hsl(0 0% 40%)', 'hsl(0 0% 60%)')};
color: var(--dees-color-text-muted);
}
.terminal-header-icon {
color: ${cssManager.bdTheme('hsl(0 0% 50%)', 'hsl(0 0% 50%)')};
color: var(--dees-color-text-muted);
}
.terminal-header-command {
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 80%)')};
color: var(--dees-color-text-secondary);
font-weight: 500;
}
@@ -243,12 +243,12 @@ export class DeesWorkspaceTerminalPreview extends DeesElement {
}
.xterm .xterm-viewport::-webkit-scrollbar-thumb {
background: ${cssManager.bdTheme('hsl(0 0% 80%)', 'hsl(0 0% 25%)')};
background: var(--dees-color-scrollbar-thumb);
border-radius: 4px;
}
.xterm .xterm-viewport::-webkit-scrollbar-thumb:hover {
background: ${cssManager.bdTheme('hsl(0 0% 70%)', 'hsl(0 0% 35%)')};
background: var(--dees-color-scrollbar-thumb-hover);
}
`,
];

View File

@@ -1,4 +1,4 @@
import { css, type CSSResult } from '@design.estate/dees-element';
import { css, cssManager, unsafeCSS, type CSSResult } from '@design.estate/dees-element';
// ============================================
// Theme Token Type Definitions
@@ -11,6 +11,7 @@ export interface IThemeColors {
textPrimary: string;
textSecondary: string;
textMuted: string;
textWarm: string;
borderDefault: string;
borderSubtle: string;
borderStrong: string;
@@ -18,6 +19,14 @@ export interface IThemeColors {
accentSuccess: string;
accentWarning: string;
accentError: string;
badgeDefaultBg: string;
badgeDefaultFg: string;
badgeSuccessBg: string;
badgeSuccessFg: string;
badgeWarningBg: string;
badgeWarningFg: string;
badgeErrorBg: string;
badgeErrorFg: string;
}
export interface IThemeSpacing {
@@ -79,34 +88,52 @@ export interface ITheme {
export const themeDefaults: ITheme = {
colors: {
light: {
bgPrimary: '#ffffff',
bgSecondary: '#fafafa',
bgTertiary: '#f4f4f5',
textPrimary: '#09090b',
textSecondary: '#374151',
textMuted: '#71717a',
borderDefault: '#e5e7eb',
borderSubtle: '#f4f4f5',
borderStrong: '#d1d5db',
bgPrimary: 'hsl(0 0% 100%)', // #ffffff
bgSecondary: 'hsl(0 0% 98%)', // #fafafa
bgTertiary: 'hsl(0 0% 96%)', // #f5f5f5
textPrimary: 'hsl(0 0% 3.9%)', // #0a0a0a
textSecondary: 'hsl(0 0% 20%)', // #333333
textMuted: 'hsl(0 0% 45%)', // #737373
textWarm: '#78716c', // warm stone
borderDefault: 'hsl(0 0% 89.8%)', // #e5e5e5
borderSubtle: 'hsl(0 0% 93%)', // #ededed
borderStrong: 'hsl(0 0% 80%)', // #cccccc
accentPrimary: '#3b82f6',
accentSuccess: '#22c55e',
accentWarning: '#f59e0b',
accentError: '#ef4444',
badgeDefaultBg: '#f4f4f5',
badgeDefaultFg: '#3f3f46',
badgeSuccessBg: '#dcfce7',
badgeSuccessFg: '#166534',
badgeWarningBg: '#fef3c7',
badgeWarningFg: '#92400e',
badgeErrorBg: '#fee2e2',
badgeErrorFg: '#991b1b',
},
dark: {
bgPrimary: '#09090b',
bgSecondary: '#0a0a0a',
bgTertiary: '#18181b',
textPrimary: '#fafafa',
textSecondary: '#d4d4d8',
textMuted: '#a1a1aa',
borderDefault: '#27272a',
borderSubtle: '#1a1a1a',
borderStrong: '#3f3f46',
bgPrimary: 'hsl(0 0% 3.9%)', // #0a0a0a
bgSecondary: 'hsl(0 0% 3.9%)', // #0a0a0a (matches sidebar/tile in dark)
bgTertiary: 'hsl(0 0% 7%)', // #121212
textPrimary: 'hsl(0 0% 98%)', // #fafafa
textSecondary: 'hsl(0 0% 63.9%)', // #a3a3a3
textMuted: 'hsl(0 0% 55%)', // #8c8c8c
textWarm: '#b5a99a', // warm stone
borderDefault: 'hsl(0 0% 14.9%)', // #262626
borderSubtle: 'hsl(0 0% 11%)', // #1c1c1c
borderStrong: 'hsl(0 0% 20%)', // #333333
accentPrimary: '#3b82f6',
accentSuccess: '#22c55e',
accentWarning: '#f59e0b',
accentError: '#ef4444',
badgeDefaultBg: '#27272a',
badgeDefaultFg: '#a1a1aa',
badgeSuccessBg: '#14532d',
badgeSuccessFg: '#4ade80',
badgeWarningBg: '#451a03',
badgeWarningFg: '#fbbf24',
badgeErrorBg: '#450a0a',
badgeErrorFg: '#f87171',
},
},
spacing: {
@@ -146,13 +173,17 @@ export const themeDefaults: ITheme = {
},
};
// Shorthand aliases for CSS template usage
const l = themeDefaults.colors.light;
const d = themeDefaults.colors.dark;
// ============================================
// CSS Block for Component Import
// ============================================
/**
* Default theme styles to be imported into every component's static styles array.
* Provides CSS custom properties for spacing, radius, shadows, transitions, and control heights.
* Provides CSS custom properties for colors, spacing, radius, shadows, transitions, and control heights.
*
* Usage:
* ```typescript
@@ -170,6 +201,93 @@ export const themeDefaults: ITheme = {
*/
export const themeDefaultStyles: CSSResult = css`
:host {
/* ========================================
* Colors — Background (from themeDefaults)
* ======================================== */
--dees-color-bg-primary: ${cssManager.bdTheme(l.bgPrimary, d.bgPrimary)};
--dees-color-bg-secondary: ${cssManager.bdTheme(l.bgSecondary, d.bgSecondary)};
--dees-color-bg-tertiary: ${cssManager.bdTheme(l.bgTertiary, d.bgTertiary)};
/* ========================================
* Colors — Text (from themeDefaults)
* ======================================== */
--dees-color-text-primary: ${cssManager.bdTheme(l.textPrimary, d.textPrimary)};
--dees-color-text-secondary: ${cssManager.bdTheme(l.textSecondary, d.textSecondary)};
--dees-color-text-muted: ${cssManager.bdTheme(l.textMuted, d.textMuted)};
/* ========================================
* Colors — Border (from themeDefaults)
* ======================================== */
--dees-color-border-default: ${cssManager.bdTheme(l.borderDefault, d.borderDefault)};
--dees-color-border-subtle: ${cssManager.bdTheme(l.borderSubtle, d.borderSubtle)};
--dees-color-border-strong: ${cssManager.bdTheme(l.borderStrong, d.borderStrong)};
/* ========================================
* Colors — Warm Text (from themeDefaults)
* ======================================== */
--dees-color-text-warm: ${cssManager.bdTheme(l.textWarm, d.textWarm)};
/* ========================================
* Colors — Accent (from themeDefaults)
* ======================================== */
--dees-color-accent-primary: ${cssManager.bdTheme(l.accentPrimary, d.accentPrimary)};
--dees-color-accent-success: ${cssManager.bdTheme(l.accentSuccess, d.accentSuccess)};
--dees-color-accent-warning: ${cssManager.bdTheme(l.accentWarning, d.accentWarning)};
--dees-color-accent-error: ${cssManager.bdTheme(l.accentError, d.accentError)};
/* ========================================
* Colors — Badge (from themeDefaults)
* ======================================== */
--dees-color-badge-default-bg: ${cssManager.bdTheme(l.badgeDefaultBg, d.badgeDefaultBg)};
--dees-color-badge-default-fg: ${cssManager.bdTheme(l.badgeDefaultFg, d.badgeDefaultFg)};
--dees-color-badge-success-bg: ${cssManager.bdTheme(l.badgeSuccessBg, d.badgeSuccessBg)};
--dees-color-badge-success-fg: ${cssManager.bdTheme(l.badgeSuccessFg, d.badgeSuccessFg)};
--dees-color-badge-warning-bg: ${cssManager.bdTheme(l.badgeWarningBg, d.badgeWarningBg)};
--dees-color-badge-warning-fg: ${cssManager.bdTheme(l.badgeWarningFg, d.badgeWarningFg)};
--dees-color-badge-error-bg: ${cssManager.bdTheme(l.badgeErrorBg, d.badgeErrorBg)};
--dees-color-badge-error-fg: ${cssManager.bdTheme(l.badgeErrorFg, d.badgeErrorFg)};
/* ========================================
* Colors — Interactive States
* ======================================== */
--dees-color-hover: ${cssManager.bdTheme('rgba(0, 0, 0, 0.04)', 'rgba(255, 255, 255, 0.06)')};
--dees-color-active: ${cssManager.bdTheme('rgba(0, 0, 0, 0.06)', 'rgba(255, 255, 255, 0.08)')};
--dees-color-pressed: ${cssManager.bdTheme('rgba(0, 0, 0, 0.08)', 'rgba(255, 255, 255, 0.12)')};
/* ========================================
* Colors — Focus Ring
* ======================================== */
--dees-color-focus-ring: ${cssManager.bdTheme('rgba(59, 130, 246, 0.4)', 'rgba(59, 130, 246, 0.4)')};
/* ========================================
* Colors — Tooltip (inverted contrast)
* ======================================== */
--dees-color-tooltip-bg: ${cssManager.bdTheme('#18181b', '#fafafa')};
--dees-color-tooltip-fg: ${cssManager.bdTheme('#fafafa', '#18181b')};
/* ========================================
* Colors — Link
* ======================================== */
--dees-color-link: ${cssManager.bdTheme('#3b82f6', '#60a5fa')};
--dees-color-link-hover: ${cssManager.bdTheme('#2563eb', '#93bbfd')};
/* ========================================
* Colors — Code
* ======================================== */
--dees-color-code-bg: ${cssManager.bdTheme('rgba(0, 0, 0, 0.06)', 'rgba(255, 255, 255, 0.1)')};
--dees-color-code-block-bg: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
/* ========================================
* Colors — Selection
* ======================================== */
--dees-color-selection: ${cssManager.bdTheme('rgba(59, 130, 246, 0.2)', 'rgba(59, 130, 246, 0.3)')};
/* ========================================
* Colors — Scrollbar
* ======================================== */
--dees-color-scrollbar-thumb: ${cssManager.bdTheme('rgba(0, 0, 0, 0.15)', 'rgba(255, 255, 255, 0.15)')};
--dees-color-scrollbar-thumb-hover: ${cssManager.bdTheme('rgba(0, 0, 0, 0.25)', 'rgba(255, 255, 255, 0.25)')};
/* ========================================
* Spacing Scale
* ======================================== */

View File

@@ -74,6 +74,28 @@ export interface ILightweightChartsBundle {
};
}
/**
* Minimal type for an ECharts instance (loaded from CDN)
*/
export interface IEchartsInstance {
setOption(option: Record<string, any>, notMerge?: boolean): void;
resize(opts?: { width?: number; height?: number }): void;
dispose(): void;
on(eventName: string, handler: (...args: any[]) => void): void;
off(eventName: string, handler?: (...args: any[]) => void): void;
getOption(): Record<string, any>;
clear(): void;
}
/**
* Bundle type for Apache ECharts
*/
export interface IEchartsBundle {
init: (dom: HTMLElement, theme?: string | object | null, opts?: Record<string, any>) => IEchartsInstance;
dispose: (chart: IEchartsInstance | HTMLElement | string) => void;
getInstanceByDom: (dom: HTMLElement) => IEchartsInstance | undefined;
}
/**
* Bundle type for Tiptap editor and extensions
*/
@@ -108,6 +130,7 @@ export class DeesServiceLibLoader {
private xtermSearchAddonLib: IXtermSearchAddonBundle | null = null;
private highlightJsLib: HLJSApi | null = null;
private lightweightChartsLib: ILightweightChartsBundle | null = null;
private echartsLib: IEchartsBundle | null = null;
private tiptapLib: ITiptapBundle | null = null;
// Loading promises to prevent duplicate concurrent loads
@@ -116,6 +139,7 @@ export class DeesServiceLibLoader {
private xtermSearchAddonLoadingPromise: Promise<IXtermSearchAddonBundle> | null = null;
private highlightJsLoadingPromise: Promise<HLJSApi> | null = null;
private lightweightChartsLoadingPromise: Promise<ILightweightChartsBundle> | null = null;
private echartsLoadingPromise: Promise<IEchartsBundle> | null = null;
private tiptapLoadingPromise: Promise<ITiptapBundle> | null = null;
private constructor() {}
@@ -296,6 +320,36 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
return this.lightweightChartsLoadingPromise;
}
/**
* Load Apache ECharts from CDN
* @returns Promise resolving to ECharts bundle
*/
public async loadEcharts(): Promise<IEchartsBundle> {
if (this.echartsLib) {
return this.echartsLib;
}
if (this.echartsLoadingPromise) {
return this.echartsLoadingPromise;
}
this.echartsLoadingPromise = (async () => {
// Use the pre-built ESM bundle which includes all chart types and components.
// The +esm wrapper only exports the core without auto-registered chart types.
const url = `${CDN_BASE}/echarts@${CDN_VERSIONS.echarts}/dist/echarts.esm.min.js`;
const module = await import(/* @vite-ignore */ url);
this.echartsLib = {
init: module.init,
dispose: module.dispose,
getInstanceByDom: module.getInstanceByDom,
};
return this.echartsLib;
})();
return this.echartsLoadingPromise;
}
/**
* Load Tiptap rich text editor and extensions from CDN
* @returns Promise resolving to Tiptap bundle with Editor and extensions
@@ -348,6 +402,7 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
this.loadXtermSearchAddon(),
this.loadHighlightJs(),
this.loadLightweightCharts(),
this.loadEcharts(),
this.loadTiptap(),
]);
}
@@ -355,7 +410,7 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
/**
* Check if a specific library is already loaded
*/
public isLoaded(library: 'xterm' | 'xtermFitAddon' | 'xtermSearchAddon' | 'highlightJs' | 'lightweightCharts' | 'tiptap'): boolean {
public isLoaded(library: 'xterm' | 'xtermFitAddon' | 'xtermSearchAddon' | 'highlightJs' | 'lightweightCharts' | 'echarts' | 'tiptap'): boolean {
switch (library) {
case 'xterm':
return this.xtermLib !== null;
@@ -367,6 +422,8 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
return this.highlightJsLib !== null;
case 'lightweightCharts':
return this.lightweightChartsLib !== null;
case 'echarts':
return this.echartsLib !== null;
case 'tiptap':
return this.tiptapLib !== null;
default:

View File

@@ -1,3 +1,3 @@
export { DeesServiceLibLoader } from './DeesServiceLibLoader.js';
export type { IXtermBundle, IXtermFitAddonBundle, IXtermSearchAddonBundle, IXtermSearchAddon, ITiptapBundle, ILightweightChartsBundle } from './DeesServiceLibLoader.js';
export type { IXtermBundle, IXtermFitAddonBundle, IXtermSearchAddonBundle, IXtermSearchAddon, ITiptapBundle, ILightweightChartsBundle, IEchartsBundle, IEchartsInstance } from './DeesServiceLibLoader.js';
export { CDN_BASE, CDN_VERSIONS } from './versions.js';

View File

@@ -7,6 +7,7 @@ export const CDN_VERSIONS = {
xtermAddonFit: '0.8.0',
xtermAddonSearch: '0.13.0',
highlightJs: '11.11.1',
echarts: '5.6.0',
lightweightCharts: '5.1.0',
tiptap: '2.27.2',
fontawesome: '7.2.0',