Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b6ccd0e3c | |||
| d933c47b49 | |||
| 3defbba5fd | |||
| 02522c9a15 | |||
| 4370efe6fb | |||
| cde2a833ef | |||
| 31fbe22f55 | |||
| e6f501e804 | |||
| f052fb9c9f | |||
| 77130ffb5e | |||
| 236b83d0a0 | |||
| a2e0760cc6 | |||
| 2e24d77f6a | |||
| 10b67adfe1 | |||
| 0d7f68086d | |||
| 9d0f6da905 | |||
| 42fd0b276e | |||
| 23d672040c | |||
| 24f96788d5 | |||
| 6e5def5708 | |||
| 472132e8cf | |||
| e062f5046e | |||
| f2d3fc28f8 | |||
| 7295bfcf92 |
50
changelog.md
50
changelog.md
@@ -1,5 +1,55 @@
|
||||
# Changelog
|
||||
|
||||
## 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
|
||||
|
||||
- Update the main content background from pure white/near-black to softer light and dark theme values.
|
||||
|
||||
## 2026-04-03 - 3.52.3 - fix(input-richtext)
|
||||
resolve rich text editor initialization and layout issues by bundling Tiptap locally and anchoring editor containers
|
||||
|
||||
- Switch Tiptap imports from CDN URLs to bundled npm packages to avoid duplicate ProseMirror instances
|
||||
- Update rich text, code, dataview, and terminal preview containers to use absolute inset positioning for stable full-size layouts
|
||||
- Trigger a component update after rich text editor initialization and improve ProseMirror wrapping behavior
|
||||
|
||||
## 2026-04-03 - 3.52.2 - fix(chart-log, simple-appdash)
|
||||
align terminal and dashboard theming with brightness mode and improve app dashboard scroll presentation
|
||||
|
||||
- Update dees-chart-log to refresh the terminal theme when goBright changes and derive dark mode directly from the brightness setting.
|
||||
- Refine dees-simple-appdash control bar colors, borders, and shadow gradients for better light and dark theme consistency.
|
||||
- Expand the app dashboard demo with recent activity content to showcase scrollable layout behavior.
|
||||
|
||||
## 2026-04-03 - 3.52.1 - fix(dees-modal)
|
||||
refine modal styling, spacing, and animations for a cleaner overlay presentation
|
||||
|
||||
- Adjust modal entrance and exit transitions with updated transform, opacity, and timing values
|
||||
- Refresh heading and action button styling with tighter spacing, smaller controls, and improved theme-aware colors
|
||||
- Update tile shadow, margins, and content scrollbar styling to improve modal visual polish and readability
|
||||
|
||||
## 2026-04-03 - 3.52.0 - feat(dees-chart-area)
|
||||
add full page toggle control for chart area
|
||||
|
||||
- adds a header action to expand and collapse the chart area into a full page view
|
||||
- updates chart area styling for the custom header, label, and expand button
|
||||
- resizes the chart after toggling full page mode by fitting the visible time scale
|
||||
|
||||
## 2026-04-03 - 3.51.2 - fix(ui)
|
||||
standardize tile-based layouts across input, product card, and terminal preview components
|
||||
|
||||
- Replace custom card containers with dees-tile in code input, richtext editor, shopping product card, and terminal preview components
|
||||
- Move toolbars and footers into dees-tile header/footer slots for more consistent structure and spacing
|
||||
- Update hover, focus, and selected state styling to target dees-tile parts while preserving existing component behavior
|
||||
|
||||
## 2026-04-03 - 3.51.1 - fix(repo)
|
||||
no changes to commit
|
||||
|
||||
|
||||
## 2026-04-03 - 3.51.0 - feat(chart-area)
|
||||
replace ApexCharts with Lightweight Charts for area chart rendering
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@design.estate/dees-catalog",
|
||||
"version": "3.51.0",
|
||||
"version": "3.52.5",
|
||||
"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",
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@design.estate/dees-catalog',
|
||||
version: '3.51.0',
|
||||
version: '3.52.5',
|
||||
description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ export class DeesAppuiMaincontent extends DeesElement {
|
||||
grid-template-rows: auto 1fr;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: ${cssManager.bdTheme('#ffffff', '#161616')};
|
||||
background: ${cssManager.bdTheme('#fafafa', '#0a0a0a')};
|
||||
}
|
||||
|
||||
.maincontainer {
|
||||
|
||||
@@ -13,6 +13,7 @@ import { renderChartArea } from './template.js';
|
||||
|
||||
import type { IChartApi, ISeriesApi, UTCTimestamp, MouseEventParams } from 'lightweight-charts';
|
||||
import { DeesServiceLibLoader, type ILightweightChartsBundle } from '../../../services/index.js';
|
||||
import '../../00group-layout/dees-tile/dees-tile.js';
|
||||
|
||||
export type ChartSeriesConfig = {
|
||||
name?: string;
|
||||
@@ -33,6 +34,12 @@ export class DeesChartArea extends DeesElement {
|
||||
@state()
|
||||
accessor chart: IChartApi | null = null;
|
||||
|
||||
@state()
|
||||
accessor seriesStats: Array<{ name: string; latest: number; min: number; max: number; avg: number; color: string }> = [];
|
||||
|
||||
@state()
|
||||
accessor isFullPage: boolean = false;
|
||||
|
||||
@property()
|
||||
accessor label: string = 'Untitled Chart';
|
||||
|
||||
@@ -163,8 +170,8 @@ export class DeesChartArea extends DeesElement {
|
||||
attributionLogo: false,
|
||||
},
|
||||
grid: {
|
||||
vertLines: { visible: false },
|
||||
horzLines: { color: isDark ? 'hsl(0 0% 14.9%)' : 'hsl(0 0% 94%)' },
|
||||
vertLines: { color: isDark ? 'hsl(0 0% 8.5%)' : 'hsl(0 0% 95.5%)' },
|
||||
horzLines: { color: isDark ? 'hsl(0 0% 8.5%)' : 'hsl(0 0% 95.5%)' },
|
||||
},
|
||||
} as any);
|
||||
|
||||
@@ -172,7 +179,7 @@ export class DeesChartArea extends DeesElement {
|
||||
for (const [, api] of this.seriesApis) {
|
||||
const color = colors[idx % colors.length];
|
||||
api.applyOptions({
|
||||
topColor: this.hslToRgba(color, isDark ? 0.2 : 0.3),
|
||||
topColor: this.hslToRgba(color, isDark ? 0.4 : 0.5),
|
||||
bottomColor: this.hslToRgba(color, 0),
|
||||
lineColor: color,
|
||||
});
|
||||
@@ -194,7 +201,7 @@ export class DeesChartArea extends DeesElement {
|
||||
chartSeries.forEach((s, index) => {
|
||||
const color = colors[index % colors.length];
|
||||
const api = this.chart!.addSeries(this.lcBundle!.AreaSeries, {
|
||||
topColor: this.hslToRgba(color, isDark ? 0.2 : 0.3),
|
||||
topColor: this.hslToRgba(color, isDark ? 0.4 : 0.5),
|
||||
bottomColor: this.hslToRgba(color, 0),
|
||||
lineColor: color,
|
||||
lineWidth: 2,
|
||||
@@ -218,6 +225,23 @@ export class DeesChartArea extends DeesElement {
|
||||
|
||||
this.seriesApis.set(s.name || `series-${index}`, api);
|
||||
});
|
||||
this.computeStats(chartSeries);
|
||||
}
|
||||
|
||||
private computeStats(chartSeries: ChartSeriesConfig) {
|
||||
const isDark = !this.goBright;
|
||||
const colors = this.getSeriesColors(isDark);
|
||||
this.seriesStats = chartSeries.map((s, index) => {
|
||||
const values = s.data.map(d => d.y);
|
||||
if (values.length === 0) {
|
||||
return { name: s.name || `series-${index}`, latest: 0, min: 0, max: 0, avg: 0, color: colors[index % colors.length] };
|
||||
}
|
||||
const latest = values[values.length - 1];
|
||||
const min = Math.min(...values);
|
||||
const max = Math.max(...values);
|
||||
const avg = Math.round((values.reduce((sum, v) => sum + v, 0) / values.length) * 100) / 100;
|
||||
return { name: s.name || `series-${index}`, latest, min, max, avg, color: colors[index % colors.length] };
|
||||
});
|
||||
}
|
||||
|
||||
private updatePriceLines(name: string, api: ISeriesApi<any>, data: Array<{ x: any; y: number }>, color: string) {
|
||||
@@ -348,8 +372,8 @@ export class DeesChartArea extends DeesElement {
|
||||
attributionLogo: false,
|
||||
},
|
||||
grid: {
|
||||
vertLines: { visible: false },
|
||||
horzLines: { color: isDark ? 'hsl(0 0% 14.9%)' : 'hsl(0 0% 94%)' },
|
||||
vertLines: { color: isDark ? 'hsl(0 0% 8.5%)' : 'hsl(0 0% 95.5%)' },
|
||||
horzLines: { color: isDark ? 'hsl(0 0% 8.5%)' : 'hsl(0 0% 95.5%)' },
|
||||
},
|
||||
rightPriceScale: {
|
||||
borderVisible: false,
|
||||
@@ -468,6 +492,7 @@ export class DeesChartArea extends DeesElement {
|
||||
api.setData(this.convertDataToLC(filtered));
|
||||
this.updatePriceLines(name, api, filtered, colors[index % colors.length]);
|
||||
});
|
||||
this.computeStats(newSeries);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -505,6 +530,7 @@ export class DeesChartArea extends DeesElement {
|
||||
api.setData(this.convertDataToLC(s.data));
|
||||
this.updatePriceLines(name, api, s.data, colors[index % colors.length]);
|
||||
});
|
||||
this.computeStats(newSeries);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -554,6 +580,29 @@ export class DeesChartArea extends DeesElement {
|
||||
await this.resizeChart();
|
||||
}
|
||||
|
||||
public toggleFullPage() {
|
||||
this.isFullPage = !this.isFullPage;
|
||||
if (this.isFullPage) {
|
||||
this.style.position = 'fixed';
|
||||
this.style.inset = '0';
|
||||
this.style.zIndex = '10000';
|
||||
this.style.height = '100vh';
|
||||
this.style.padding = '0';
|
||||
document.body.style.overflow = 'hidden';
|
||||
} else {
|
||||
this.style.position = '';
|
||||
this.style.inset = '';
|
||||
this.style.zIndex = '';
|
||||
this.style.height = '';
|
||||
this.style.padding = '';
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
// Give LC a tick to resize
|
||||
requestAnimationFrame(() => {
|
||||
this.chart?.timeScale().fitContent();
|
||||
});
|
||||
}
|
||||
|
||||
private startAutoScroll() {
|
||||
if (this.autoScrollTimer) return;
|
||||
this.autoScrollTimer = window.setInterval(() => {
|
||||
|
||||
@@ -4,38 +4,86 @@ export const chartAreaStyles = [
|
||||
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%)')};
|
||||
font-size: 14px;
|
||||
}
|
||||
.mainbox {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 400px;
|
||||
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%)')};
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
dees-tile {
|
||||
height: 100%;
|
||||
}
|
||||
.chartTitle {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding: 16px 24px;
|
||||
z-index: 10;
|
||||
.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: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 63.9%)')};
|
||||
}
|
||||
.expandBtn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 55%)', 'hsl(0 0% 45%)')};
|
||||
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%)')};
|
||||
}
|
||||
.chartContainer {
|
||||
position: absolute;
|
||||
top: 44px;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
inset: 0 0 4px 0;
|
||||
}
|
||||
.statsBar {
|
||||
height: 32px;
|
||||
padding: 0 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.statsSeries {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.statsSeries + .statsSeries {
|
||||
padding-left: 24px;
|
||||
border-left: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
|
||||
}
|
||||
.statsColor {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 2px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.statsName {
|
||||
font-weight: 500;
|
||||
font-size: 11px;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 80%)')};
|
||||
margin-right: 4px;
|
||||
}
|
||||
.statsItem {
|
||||
font-size: 11px;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 45%)', 'hsl(0 0% 55%)')};
|
||||
}
|
||||
.statsItem strong {
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 90%)')};
|
||||
}
|
||||
.lw-tooltip {
|
||||
position: absolute;
|
||||
|
||||
@@ -1,12 +1,31 @@
|
||||
import { html, type TemplateResult } from '@design.estate/dees-element';
|
||||
import type { DeesChartArea } from './component.js';
|
||||
import '../../00group-utility/dees-icon/dees-icon.js';
|
||||
|
||||
export const renderChartArea = (component: DeesChartArea): TemplateResult => {
|
||||
return html`
|
||||
<div class="mainbox">
|
||||
<div class="chartTitle">${component.label}</div>
|
||||
<dees-tile>
|
||||
<div slot="header" class="chartHeader">
|
||||
<span class="chartLabel">${component.label}</span>
|
||||
<button class="expandBtn" @click=${() => component.toggleFullPage()} title="${component.isFullPage ? 'Exit full page' : 'Full page'}">
|
||||
<dees-icon .icon=${component.isFullPage ? 'lucide:Minimize2' : 'lucide:Maximize2'} .iconSize=${14}></dees-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="chartContainer"></div>
|
||||
</div>
|
||||
${component.seriesStats.length > 0 ? html`
|
||||
<div slot="footer" class="statsBar">
|
||||
${component.seriesStats.map(s => html`
|
||||
<div class="statsSeries">
|
||||
<span class="statsColor" style="background:${s.color}"></span>
|
||||
<span class="statsName">${s.name}</span>
|
||||
<span class="statsItem">latest <strong>${component.yAxisFormatter(s.latest)}</strong></span>
|
||||
<span class="statsItem">min <strong>${component.yAxisFormatter(s.min)}</strong></span>
|
||||
<span class="statsItem">max <strong>${component.yAxisFormatter(s.max)}</strong></span>
|
||||
<span class="statsItem">avg <strong>${component.yAxisFormatter(s.avg)}</strong></span>
|
||||
</div>
|
||||
`)}
|
||||
</div>
|
||||
` : ''}
|
||||
</dees-tile>
|
||||
`;
|
||||
|
||||
};
|
||||
|
||||
@@ -13,6 +13,7 @@ import * as domtools from '@design.estate/dees-domtools';
|
||||
import { demoFunc } from './dees-chart-log.demo.js';
|
||||
import { themeDefaultStyles } from '../../00theme.js';
|
||||
import { DeesServiceLibLoader, type IXtermSearchAddon, CDN_BASE, CDN_VERSIONS } from '../../../services/index.js';
|
||||
import '../../00group-layout/dees-tile/dees-tile.js';
|
||||
|
||||
// Type imports (no runtime overhead)
|
||||
import type { Terminal } from 'xterm';
|
||||
@@ -103,30 +104,20 @@ export class DeesChartLog extends DeesElement {
|
||||
css`
|
||||
:host {
|
||||
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%)')};
|
||||
}
|
||||
|
||||
.mainbox {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 400px;
|
||||
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%)')};
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
dees-tile {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.header {
|
||||
background: ${cssManager.bdTheme('hsl(0 0% 97%)', 'hsl(0 0% 7%)')};
|
||||
padding: 8px 12px;
|
||||
border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
flex-shrink: 0;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
@@ -241,10 +232,10 @@ export class DeesChartLog extends DeesElement {
|
||||
}
|
||||
|
||||
.terminal-container {
|
||||
flex: 1;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
overflow: hidden;
|
||||
padding: 8px;
|
||||
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 3.9%)')};
|
||||
}
|
||||
|
||||
.terminal-container .xterm {
|
||||
@@ -262,14 +253,15 @@ export class DeesChartLog extends DeesElement {
|
||||
}
|
||||
|
||||
.metrics-bar {
|
||||
background: ${cssManager.bdTheme('hsl(0 0% 97%)', 'hsl(0 0% 7%)')};
|
||||
border-top: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
|
||||
padding: 6px 12px;
|
||||
height: 32px;
|
||||
padding: 0 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
flex-shrink: 0;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.metric {
|
||||
@@ -323,8 +315,8 @@ export class DeesChartLog extends DeesElement {
|
||||
|
||||
public render(): TemplateResult {
|
||||
return html`
|
||||
<div class="mainbox">
|
||||
<div class="header">
|
||||
<dees-tile .heading=${this.label}>
|
||||
<div slot="header" class="header">
|
||||
<div class="title">${this.label}</div>
|
||||
<div class="search-box">
|
||||
<input
|
||||
@@ -367,7 +359,7 @@ export class DeesChartLog extends DeesElement {
|
||||
|
||||
${this.showMetrics
|
||||
? html`
|
||||
<div class="metrics-bar">
|
||||
<div slot="footer" class="metrics-bar">
|
||||
<span class="metric error">errors: ${this.metrics.error}</span>
|
||||
<span class="metric warn">warns: ${this.metrics.warn}</span>
|
||||
<span class="metric info">info: ${this.metrics.info}</span>
|
||||
@@ -377,7 +369,7 @@ export class DeesChartLog extends DeesElement {
|
||||
</div>
|
||||
`
|
||||
: ''}
|
||||
</div>
|
||||
</dees-tile>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -466,6 +458,9 @@ export class DeesChartLog extends DeesElement {
|
||||
|
||||
public updated(changedProperties: Map<string, any>) {
|
||||
super.updated(changedProperties);
|
||||
if (changedProperties.has('goBright') && this.terminal) {
|
||||
this.terminal.options.theme = this.getTerminalTheme();
|
||||
}
|
||||
if (changedProperties.has('logEntries') && this.terminalReady && this.logEntries.length > 0) {
|
||||
const oldEntries: ILogEntry[] = changedProperties.get('logEntries') || [];
|
||||
const newEntries = this.logEntries;
|
||||
@@ -512,7 +507,7 @@ export class DeesChartLog extends DeesElement {
|
||||
}
|
||||
|
||||
private getTerminalTheme() {
|
||||
const isDark = this.domtoolsInstance?.themeManager?.isDarkMode ?? true;
|
||||
const isDark = !this.goBright;
|
||||
return isDark
|
||||
? {
|
||||
background: '#0a0a0a',
|
||||
|
||||
@@ -17,6 +17,7 @@ import * as smartstring from '@push.rocks/smartstring';
|
||||
import * as domtools from '@design.estate/dees-domtools';
|
||||
import { DeesContextmenu } from '../../00group-overlay/dees-contextmenu/dees-contextmenu.js';
|
||||
import { DeesServiceLibLoader } from '../../../services/index.js';
|
||||
import '../../00group-layout/dees-tile/dees-tile.js';
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
@@ -55,32 +56,20 @@ export class DeesDataviewCodebox extends DeesElement {
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.mainbox {
|
||||
position: relative;
|
||||
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
|
||||
border: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06);
|
||||
background: ${cssManager.bdTheme('#ffffff', '#09090b')};
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
dees-tile {
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
|
||||
}
|
||||
|
||||
.appbar {
|
||||
position: relative;
|
||||
color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
|
||||
background: ${cssManager.bdTheme('#f9fafb', '#18181b')};
|
||||
border-bottom: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
|
||||
height: 32px;
|
||||
display: flex;
|
||||
font-size: 13px;
|
||||
line-height: 32px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.appbar .fileName {
|
||||
@@ -91,18 +80,16 @@ export class DeesDataviewCodebox extends DeesElement {
|
||||
}
|
||||
|
||||
.bottomBar {
|
||||
position: relative;
|
||||
color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
|
||||
background: ${cssManager.bdTheme('#f9fafb', '#18181b')};
|
||||
border-top: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
|
||||
height: 28px;
|
||||
font-size: 12px;
|
||||
font-size: 11px;
|
||||
line-height: 28px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: stretch;
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.spacesLabel {
|
||||
@@ -127,11 +114,11 @@ export class DeesDataviewCodebox extends DeesElement {
|
||||
}
|
||||
|
||||
.codegrid {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: grid;
|
||||
grid-template-columns: 50px auto;
|
||||
overflow: auto;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.lineNumbers {
|
||||
@@ -201,8 +188,7 @@ export class DeesDataviewCodebox extends DeesElement {
|
||||
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
|
||||
}
|
||||
</style>
|
||||
<div
|
||||
class="mainbox"
|
||||
<dees-tile
|
||||
@contextmenu="${(eventArg: MouseEvent) => {
|
||||
DeesContextmenu.openContextMenuWithOptions(eventArg, [
|
||||
{
|
||||
@@ -215,7 +201,7 @@ export class DeesDataviewCodebox extends DeesElement {
|
||||
]);
|
||||
}}"
|
||||
>
|
||||
<div class="appbar">
|
||||
<div slot="header" class="appbar">
|
||||
<div class="fileName">index.ts</div>
|
||||
</div>
|
||||
<div class="codegrid">
|
||||
@@ -230,11 +216,11 @@ export class DeesDataviewCodebox extends DeesElement {
|
||||
</div>
|
||||
<pre><code></code></pre>
|
||||
</div>
|
||||
<div class="bottomBar">
|
||||
<div slot="footer" class="bottomBar">
|
||||
<div class="spacesLabel">Spaces: 2</div>
|
||||
<div class="languageLabel">${this.progLang}</div>
|
||||
</div>
|
||||
</div>
|
||||
</dees-tile>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
import * as tsclass from '@tsclass/tsclass';
|
||||
import { DeesContextmenu } from '../../00group-overlay/dees-contextmenu/dees-contextmenu.js';
|
||||
import { themeDefaultStyles } from '../../00theme.js';
|
||||
import '../../00group-layout/dees-tile/dees-tile.js';
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
@@ -40,35 +41,28 @@ export class DeesDataviewStatusobject extends DeesElement {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
|
||||
}
|
||||
|
||||
.mainbox {
|
||||
border-radius: 8px;
|
||||
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%)')};
|
||||
box-shadow: 0 1px 3px 0 hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);
|
||||
min-height: 48px;
|
||||
dees-tile {
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 98%)')};
|
||||
cursor: default;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.heading {
|
||||
display: grid;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
grid-template-columns: 48px auto 100px;
|
||||
height: 56px;
|
||||
gap: 8px;
|
||||
height: 32px;
|
||||
padding: 0 16px;
|
||||
background: ${cssManager.bdTheme('hsl(0 0% 97%)', 'hsl(0 0% 7%)')};
|
||||
border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
|
||||
}
|
||||
|
||||
h1 {
|
||||
display: block;
|
||||
margin: 0px;
|
||||
padding: 0px 12px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
letter-spacing: -0.01em;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 93.9%)')};
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 63.9%)')};
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.statusdot {
|
||||
@@ -82,13 +76,13 @@ export class DeesDataviewStatusobject extends DeesElement {
|
||||
}
|
||||
|
||||
.copyMain {
|
||||
font-size: 12px;
|
||||
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%)')};
|
||||
text-align: center;
|
||||
padding: 6px 12px;
|
||||
border-radius: 6px;
|
||||
padding: 4px 10px;
|
||||
border-radius: 4px;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
@@ -122,63 +116,70 @@ export class DeesDataviewStatusobject extends DeesElement {
|
||||
}
|
||||
|
||||
.detail {
|
||||
min-height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
display: grid;
|
||||
grid-template-columns: 48px auto;
|
||||
border-top: 1px solid ${cssManager.bdTheme('hsl(0 0% 94%)', 'hsl(0 0% 14.9%)')};
|
||||
transition: background-color 0.15s ease;
|
||||
gap: 10px;
|
||||
height: 36px;
|
||||
padding: 0 16px;
|
||||
border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 95%)', 'hsl(0 0% 10%)')};
|
||||
transition: background-color 0.15s ease;
|
||||
cursor: context-menu;
|
||||
}
|
||||
|
||||
.detail:hover {
|
||||
background: ${cssManager.bdTheme('hsl(0 0% 97%)', 'hsl(0 0% 7%)')};
|
||||
.detail:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.detail:active {
|
||||
background: ${cssManager.bdTheme('hsl(0 0% 95%)', 'hsl(0 0% 9%)')};
|
||||
.detail:hover {
|
||||
background: ${cssManager.bdTheme('hsl(222.2 47.4% 51.2% / 0.04)', 'hsl(217.2 91.2% 59.8% / 0.06)')};
|
||||
}
|
||||
|
||||
.detail .statusdot {
|
||||
margin: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.detail .detailsText {
|
||||
padding: 12px;
|
||||
word-break: break-all;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.detail .detailsText .label {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
|
||||
margin-bottom: 2px;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.detail .detailsText .value {
|
||||
font-size: 14px;
|
||||
font-family: 'Intel One Mono', 'Geist Mono', monospace;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 90%)')};
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.bottomBar {
|
||||
position: relative;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
|
||||
background: ${cssManager.bdTheme('hsl(0 0% 97%)', 'hsl(0 0% 7%)')};
|
||||
border-top: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
|
||||
height: 28px;
|
||||
font-size: 12px;
|
||||
line-height: 28px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: stretch;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.bottomBar .statusLabel {
|
||||
padding: 0 16px;
|
||||
.detail .detailsText .value {
|
||||
font-size: 13px;
|
||||
font-family: 'Intel One Mono', 'Geist Mono', monospace;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 90%)')};
|
||||
margin-left: auto;
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.bottomBar {
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
|
||||
height: 28px;
|
||||
font-size: 11px;
|
||||
line-height: 28px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.bottomBar .statusLabel {
|
||||
font-weight: 500;
|
||||
}
|
||||
`,
|
||||
@@ -186,15 +187,15 @@ export class DeesDataviewStatusobject extends DeesElement {
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`
|
||||
<div class="mainbox">
|
||||
<div class="heading">
|
||||
<dees-tile>
|
||||
<div slot="header" class="heading">
|
||||
<div class="statusdot ${this.statusObject?.combinedStatus}"></div>
|
||||
<h1>${this.statusObject?.name || 'No status object assigned'}</h1>
|
||||
<div class="copyMain" @click=${this.handleCopyAsJson}>Copy JSON</div>
|
||||
</div>
|
||||
${this.statusObject?.details?.map((detailArg) => {
|
||||
return html`
|
||||
<div
|
||||
<div
|
||||
class="detail"
|
||||
@contextmenu=${(event: MouseEvent) => {
|
||||
event.preventDefault();
|
||||
@@ -224,19 +225,19 @@ export class DeesDataviewStatusobject extends DeesElement {
|
||||
}}
|
||||
>
|
||||
<div class="statusdot ${detailArg.status}"></div>
|
||||
<div class="detailsText">
|
||||
<div class="label">${detailArg.name}</div>
|
||||
<div class="value">${detailArg.value}</div>
|
||||
</div>
|
||||
<span class="detailsText">
|
||||
<span class="label">${detailArg.name}</span>
|
||||
<span class="value">${detailArg.value}</span>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
})}
|
||||
<div class="bottomBar">
|
||||
<div slot="footer" class="bottomBar">
|
||||
<div class="statusLabel">${this.statusObject?.lastUpdated
|
||||
? `Last updated: ${new Date(this.statusObject.lastUpdated).toLocaleString()}`
|
||||
: ''}</div>
|
||||
</div>
|
||||
</div>
|
||||
</dees-tile>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import '../../00group-utility/dees-icon/dees-icon.js';
|
||||
import '../../00group-overlay/dees-contextmenu/dees-contextmenu.js';
|
||||
import '../../00group-button/dees-button/dees-button.js';
|
||||
import { themeDefaultStyles } from '../../00theme.js';
|
||||
import '../../00group-layout/dees-tile/dees-tile.js';
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
@@ -179,22 +180,12 @@ export class DeesStatsGrid extends DeesElement {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Tile Base Styles */
|
||||
.stats-tile {
|
||||
background: ${cssManager.bdTheme('#ffffff', '#09090b')};
|
||||
border: 1px solid ${cssManager.bdTheme('#e0e0e0', '#202020')};
|
||||
border-radius: var(--border-radius);
|
||||
padding: var(--tile-padding);
|
||||
/* Tile Base Styles — frame provided by dees-tile, hover via ::part */
|
||||
.stats-tile::part(outer) {
|
||||
transition: all var(--transition-duration) ease;
|
||||
cursor: default;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.stats-tile:hover {
|
||||
background: ${cssManager.bdTheme('#fafafa', '#0d0d0d')};
|
||||
.stats-tile:hover::part(outer) {
|
||||
border-color: ${cssManager.bdTheme('#d0d0d0', '#2a2a2a')};
|
||||
}
|
||||
|
||||
@@ -202,17 +193,18 @@ export class DeesStatsGrid extends DeesElement {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.stats-tile.clickable:hover {
|
||||
.stats-tile.clickable:hover::part(outer) {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 2px 6px ${cssManager.bdTheme('rgba(0,0,0,0.03)', 'rgba(0,0,0,0.15)')};
|
||||
}
|
||||
|
||||
/* Tile Header */
|
||||
/* Tile Header — slotted into dees-tile header */
|
||||
.tile-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: var(--header-spacing);
|
||||
align-items: center;
|
||||
padding: 0 12px;
|
||||
height: 28px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@@ -232,12 +224,12 @@ export class DeesStatsGrid extends DeesElement {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Tile Content */
|
||||
/* Tile Content — slotted into dees-tile content area */
|
||||
.tile-content {
|
||||
min-height: var(--content-min-height);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
padding: 12px;
|
||||
min-height: var(--content-min-height);
|
||||
}
|
||||
|
||||
.tile-value {
|
||||
@@ -261,9 +253,10 @@ export class DeesStatsGrid extends DeesElement {
|
||||
.tile-description {
|
||||
font-size: var(--label-font-size);
|
||||
color: ${cssManager.bdTheme('hsl(215.4 16.3% 56.9%)', 'hsl(215 20.2% 55.1%)')};
|
||||
margin-top: var(--description-spacing);
|
||||
letter-spacing: -0.01em;
|
||||
flex-shrink: 0;
|
||||
padding: 0 12px;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
/* Gauge Styles */
|
||||
@@ -882,27 +875,27 @@ export class DeesStatsGrid extends DeesElement {
|
||||
const columnSpan = tile.columnSpan && tile.columnSpan > 1 ? tile.columnSpan : undefined;
|
||||
|
||||
return html`
|
||||
<div
|
||||
<dees-tile
|
||||
class="stats-tile ${clickable ? 'clickable' : ''}"
|
||||
style="${columnSpan ? `grid-column: span ${columnSpan}` : ''}"
|
||||
@click=${clickable ? () => this.handleTileAction(tile.actions![0], tile) : undefined}
|
||||
@contextmenu=${hasActions ? (e: MouseEvent) => this.showContextMenu(e, tile) : undefined}
|
||||
>
|
||||
<div class="tile-header">
|
||||
<div slot="header" class="tile-header">
|
||||
<h3 class="tile-title">${tile.title}</h3>
|
||||
${tile.icon ? html`
|
||||
<dees-icon class="tile-icon" .icon=${tile.icon} size="small"></dees-icon>
|
||||
` : ''}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="tile-content">
|
||||
${this.renderTileContent(tile)}
|
||||
</div>
|
||||
|
||||
|
||||
${tile.description && tile.type !== 'trend' ? html`
|
||||
<div class="tile-description">${tile.description}</div>
|
||||
<div slot="footer" class="tile-description">${tile.description}</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</dees-tile>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
} from './data.js';
|
||||
import { compileLucenePredicate } from './lucene.js';
|
||||
import { themeDefaultStyles } from '../../00theme.js';
|
||||
import '../../00group-layout/dees-tile/dees-tile.js';
|
||||
|
||||
export type { Column, ITableAction, ITableActionDataArg, TDisplayFunction } from './types.js';
|
||||
|
||||
@@ -221,9 +222,8 @@ export class DeesTable<T> extends DeesElement {
|
||||
);
|
||||
(this as any)._lastViewData = viewData;
|
||||
return html`
|
||||
<div class="mainbox">
|
||||
<!-- the heading part -->
|
||||
<div class="header">
|
||||
<dees-tile>
|
||||
<div slot="header" class="header">
|
||||
<div class="headingContainer">
|
||||
<div class="heading heading1">${this.label || this.heading1}</div>
|
||||
<div class="heading heading2">${this.heading2}</div>
|
||||
@@ -496,7 +496,7 @@ export class DeesTable<T> extends DeesElement {
|
||||
</div>
|
||||
`
|
||||
: html` <div class="noDataSet">No data set!</div> `}
|
||||
<div class="footer">
|
||||
<div slot="footer" class="footer">
|
||||
<div class="tableStatistics">
|
||||
${this.data.length} ${this.dataName || 'data rows'} (total) |
|
||||
${this.selectedDataRow ? '# ' + `${this.data.indexOf(this.selectedDataRow) + 1}` : `No`}
|
||||
@@ -528,7 +528,7 @@ export class DeesTable<T> extends DeesElement {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</dees-tile>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,17 +12,11 @@ export const tableStyles: CSSResult[] = [
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mainbox {
|
||||
dees-tile {
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 3.9%)', 'hsl(0 0% 98%)')};
|
||||
font-family: ${cssGeistFontFamily};
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
display: block;
|
||||
width: 100%;
|
||||
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%)')};
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
@@ -30,30 +24,31 @@ export const tableStyles: CSSResult[] = [
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 16px 24px;
|
||||
min-height: 64px;
|
||||
border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
|
||||
padding: 0 16px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.headingContainer {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.heading {
|
||||
line-height: 1.5;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.heading1 {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 95%)')};
|
||||
letter-spacing: -0.025em;
|
||||
}
|
||||
|
||||
.heading2 {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 63.9%)')};
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.heading2 {
|
||||
font-size: 12px;
|
||||
color: ${cssManager.bdTheme('hsl(215.4 16.3% 56.9%)', 'hsl(215 20.2% 55.1%)')};
|
||||
margin-top: 2px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.headingSeparation {
|
||||
@@ -70,14 +65,14 @@ export const tableStyles: CSSResult[] = [
|
||||
.headerAction {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 6px 12px;
|
||||
font-size: 14px;
|
||||
gap: 4px;
|
||||
padding: 4px 10px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 45.1%)', 'hsl(0 0% 63.9%)')};
|
||||
background: transparent;
|
||||
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
|
||||
border-radius: 6px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s ease;
|
||||
}
|
||||
@@ -199,7 +194,7 @@ export const tableStyles: CSSResult[] = [
|
||||
}
|
||||
|
||||
tbody tr:hover {
|
||||
background: ${cssManager.bdTheme('hsl(210 40% 96.1% / 0.5)', 'hsl(0 0% 14.9% / 0.5)')};
|
||||
background: ${cssManager.bdTheme('hsl(222.2 47.4% 51.2% / 0.06)', 'hsl(217.2 91.2% 59.8% / 0.08)')};
|
||||
}
|
||||
|
||||
/* Column hover effect for better traceability */
|
||||
@@ -214,7 +209,7 @@ export const tableStyles: CSSResult[] = [
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: ${cssManager.bdTheme('hsl(210 40% 96.1% / 0.3)', 'hsl(0 0% 14.9% / 0.3)')};
|
||||
background: ${cssManager.bdTheme('hsl(222.2 47.4% 51.2% / 0.04)', 'hsl(217.2 91.2% 59.8% / 0.05)')};
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: opacity 0.15s ease;
|
||||
@@ -238,15 +233,19 @@ export const tableStyles: CSSResult[] = [
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
:host([show-grid]) th:first-child,
|
||||
:host([show-grid]) td:first-child {
|
||||
border-left: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
|
||||
}
|
||||
|
||||
:host([show-grid]) tbody tr:first-child td {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
/* Remove edge borders that would double with tile frame */
|
||||
:host([show-grid]) th:last-child,
|
||||
:host([show-grid]) td:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
:host([show-grid]) tbody tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* Sticky Actions column (right pinned) */
|
||||
thead th.actionsCol,
|
||||
tbody td.actionsCol {
|
||||
@@ -261,7 +260,7 @@ export const tableStyles: CSSResult[] = [
|
||||
}
|
||||
|
||||
tbody tr.selected {
|
||||
background: ${cssManager.bdTheme('hsl(210 40% 96.1%)', 'hsl(0 0% 14.9%)')};
|
||||
background: ${cssManager.bdTheme('hsl(222.2 47.4% 51.2% / 0.1)', 'hsl(217.2 91.2% 59.8% / 0.12)')};
|
||||
}
|
||||
|
||||
tbody tr.hasAttachment {
|
||||
@@ -269,10 +268,11 @@ export const tableStyles: CSSResult[] = [
|
||||
}
|
||||
|
||||
th {
|
||||
height: 48px;
|
||||
padding: 12px 24px;
|
||||
height: 36px;
|
||||
padding: 8px 16px;
|
||||
text-align: left;
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
color: ${cssManager.bdTheme('hsl(215.4 16.3% 46.9%)', 'hsl(215 20.2% 65.1%)')};
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
@@ -282,8 +282,9 @@ export const tableStyles: CSSResult[] = [
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 12px 24px;
|
||||
padding: 8px 16px;
|
||||
vertical-align: middle;
|
||||
font-size: 13px;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 3.9%)', 'hsl(0 0% 98%)')};
|
||||
}
|
||||
|
||||
@@ -293,18 +294,23 @@ export const tableStyles: CSSResult[] = [
|
||||
|
||||
th:first-child,
|
||||
td:first-child {
|
||||
padding-left: 24px;
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
th:last-child,
|
||||
td:last-child {
|
||||
padding-right: 24px;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
:host([show-vertical-lines]) th:last-child,
|
||||
:host([show-vertical-lines]) td:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
/* Default bottom border on last row removed — tile frame handles it */
|
||||
:host(:not([show-horizontal-lines])) tbody tr:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.innerCellContainer {
|
||||
position: relative;
|
||||
@@ -389,12 +395,12 @@ export const tableStyles: CSSResult[] = [
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 52px;
|
||||
padding: 0 24px;
|
||||
font-size: 14px;
|
||||
color: ${cssManager.bdTheme('hsl(215.4 16.3% 46.9%)', 'hsl(215 20.2% 65.1%)')};
|
||||
background: ${cssManager.bdTheme('hsl(210 40% 96.1%)', 'hsl(0 0% 9%)')};
|
||||
border-top: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
|
||||
height: 32px;
|
||||
padding: 0 16px;
|
||||
font-size: 11px;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 45%)', 'hsl(0 0% 55%)')};
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tableStatistics {
|
||||
@@ -409,9 +415,10 @@ export const tableStyles: CSSResult[] = [
|
||||
.footerActions .footerAction {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 6px 12px;
|
||||
gap: 4px;
|
||||
padding: 2px 8px;
|
||||
font-weight: 500;
|
||||
font-size: 11px;
|
||||
color: ${cssManager.bdTheme('hsl(215.4 16.3% 46.9%)', 'hsl(215 20.2% 65.1%)')};
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
|
||||
@@ -12,6 +12,7 @@ import { themeDefaultStyles } from '../../00theme.js';
|
||||
import { DeesModal } from '../../00group-overlay/dees-modal/dees-modal.js';
|
||||
import '../../00group-utility/dees-icon/dees-icon.js';
|
||||
import '../../00group-layout/dees-label/dees-label.js';
|
||||
import '../../00group-layout/dees-tile/dees-tile.js';
|
||||
import '../../00group-workspace/dees-workspace-monaco/dees-workspace-monaco.js';
|
||||
import { DeesWorkspaceMonaco } from '../../00group-workspace/dees-workspace-monaco/dees-workspace-monaco.js';
|
||||
|
||||
@@ -105,24 +106,16 @@ export class DeesInputCode extends DeesInputBase<string> {
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.code-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
dees-tile {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 9%)')};
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 8px 12px;
|
||||
background: ${cssManager.bdTheme('hsl(0 0% 97%)', 'hsl(0 0% 7%)')};
|
||||
border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
|
||||
padding: 4px 12px;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
@@ -221,9 +214,8 @@ export class DeesInputCode extends DeesInputBase<string> {
|
||||
}
|
||||
|
||||
.editor-wrapper {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
}
|
||||
|
||||
dees-workspace-monaco {
|
||||
@@ -256,8 +248,8 @@ export class DeesInputCode extends DeesInputBase<string> {
|
||||
</style>
|
||||
<div class="input-wrapper">
|
||||
<dees-label .label=${this.label} .description=${this.description} .required=${this.required}></dees-label>
|
||||
<div class="code-container">
|
||||
<div class="toolbar">
|
||||
<dees-tile>
|
||||
<div slot="header" class="toolbar">
|
||||
<div class="toolbar-left">
|
||||
<div class="language-selector">
|
||||
<button
|
||||
@@ -322,7 +314,7 @@ export class DeesInputCode extends DeesInputBase<string> {
|
||||
@content-change=${this.handleContentChange}
|
||||
></dees-workspace-monaco>
|
||||
</div>
|
||||
</div>
|
||||
</dees-tile>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
|
||||
import type { Editor } from '@tiptap/core';
|
||||
import { DeesServiceLibLoader, type ITiptapBundle } from '../../../services/index.js';
|
||||
import '../../00group-layout/dees-tile/dees-tile.js';
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
@@ -238,6 +239,7 @@ export class DeesInputRichtext extends DeesInputBase<string> {
|
||||
this.editorElement = this.shadowRoot!.querySelector('.editor-content')!;
|
||||
this.linkInputElement = this.shadowRoot!.querySelector('.link-input input')!;
|
||||
this.initializeEditor();
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
private initializeEditor(): void {
|
||||
|
||||
@@ -23,22 +23,15 @@ export const richtextStyles = [
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 93.9%)')};
|
||||
}
|
||||
|
||||
.editor-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: ${cssManager.bdTheme('200px', '200px')};
|
||||
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
|
||||
border-radius: 6px;
|
||||
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 9%)')};
|
||||
overflow: hidden;
|
||||
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
dees-tile {
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.editor-container:hover {
|
||||
dees-tile:hover::part(outer) {
|
||||
border-color: ${cssManager.bdTheme('hsl(0 0% 79.8%)', 'hsl(0 0% 20.9%)')};
|
||||
}
|
||||
|
||||
.editor-container.focused {
|
||||
dees-tile.focused::part(outer) {
|
||||
border-color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 98%)')};
|
||||
box-shadow: 0 0 0 2px ${cssManager.bdTheme('hsl(0 0% 9% / 0.05)', 'hsl(0 0% 98% / 0.05)')};
|
||||
}
|
||||
@@ -47,9 +40,7 @@ export const richtextStyles = [
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 4px;
|
||||
padding: 8px 12px;
|
||||
background: ${cssManager.bdTheme('hsl(210 40% 96.1%)', 'hsl(0 0% 14.9%)')};
|
||||
border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
|
||||
padding: 4px 12px;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
@@ -99,10 +90,10 @@ export const richtextStyles = [
|
||||
}
|
||||
|
||||
.editor-content {
|
||||
flex: 1;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
padding: 16px;
|
||||
overflow-y: auto;
|
||||
min-height: var(--min-height, 200px);
|
||||
}
|
||||
|
||||
.editor-content .ProseMirror {
|
||||
@@ -110,6 +101,8 @@ export const richtextStyles = [
|
||||
line-height: 1.6;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 3.9%)', 'hsl(0 0% 98%)')};
|
||||
min-height: 100%;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.editor-content .ProseMirror p {
|
||||
@@ -199,14 +192,15 @@ export const richtextStyles = [
|
||||
}
|
||||
|
||||
.editor-footer {
|
||||
padding: 8px 12px;
|
||||
background: ${cssManager.bdTheme('hsl(210 40% 96.1%)', 'hsl(0 0% 14.9%)')};
|
||||
border-top: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
|
||||
font-size: 12px;
|
||||
color: ${cssManager.bdTheme('hsl(215.4 16.3% 46.9%)', 'hsl(215 20.2% 65.1%)')};
|
||||
padding: 0 12px;
|
||||
height: 28px;
|
||||
font-size: 11px;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 45%)', 'hsl(0 0% 55%)')};
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.word-count {
|
||||
@@ -289,7 +283,7 @@ export const richtextStyles = [
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
:host([disabled]) .editor-container {
|
||||
:host([disabled]) dees-tile {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ export const renderRichtext = (component: DeesInputRichtext): TemplateResult =>
|
||||
return html`
|
||||
<div class="input-wrapper">
|
||||
${component.label ? html`<label class="label">${component.label}</label>` : ''}
|
||||
<div class="editor-container ${component.editor?.isFocused ? 'focused' : ''}" style="--min-height: ${component.minHeight}px">
|
||||
<div class="editor-toolbar">
|
||||
<dees-tile class="${component.editor?.isFocused ? 'focused' : ''}" style="--min-height: ${component.minHeight}px">
|
||||
<div slot="header" class="editor-toolbar">
|
||||
${component.renderToolbar()}
|
||||
<div class="link-input ${component.showLinkInput ? 'show' : ''}">
|
||||
<input type="url" placeholder="Enter URL..." @keydown=${component.handleLinkInputKeydown} />
|
||||
@@ -20,14 +20,14 @@ export const renderRichtext = (component: DeesInputRichtext): TemplateResult =>
|
||||
<div class="editor-content"></div>
|
||||
${component.showWordCount
|
||||
? html`
|
||||
<div class="editor-footer">
|
||||
<div slot="footer" class="editor-footer">
|
||||
<span class="word-count">${component.wordCount} word${component.wordCount !== 1 ? 's' : ''}</span>
|
||||
</div>
|
||||
`
|
||||
: ''}
|
||||
</div>
|
||||
</dees-tile>
|
||||
${component.description ? html`<div class="description">${component.description}</div>` : ''}
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
||||
};
|
||||
|
||||
67
ts_web/elements/00group-layout/dees-tile/dees-tile.demo.ts
Normal file
67
ts_web/elements/00group-layout/dees-tile/dees-tile.demo.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { html, css, cssManager } from '@design.estate/dees-element';
|
||||
import './dees-tile.js';
|
||||
|
||||
export const demoFunc = () => {
|
||||
return html`
|
||||
<dees-demowrapper>
|
||||
<style>
|
||||
${css`
|
||||
.demoBox {
|
||||
background: ${cssManager.bdTheme('hsl(0 0% 95%)', 'hsl(0 0% 9%)')};
|
||||
padding: 40px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
}
|
||||
.tile-demo-content {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 45%)', 'hsl(0 0% 55%)')};
|
||||
font-size: 13px;
|
||||
}
|
||||
.footer-stats {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
font-size: 11px;
|
||||
width: 100%;
|
||||
}
|
||||
.footer-stats .stat {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
.footer-stats .stat strong {
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 90%)')};
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
<div class="demoBox">
|
||||
<dees-tile heading="Simple Tile" style="height: 200px;">
|
||||
<div class="tile-demo-content">Content area with rounded corners</div>
|
||||
</dees-tile>
|
||||
|
||||
<dees-tile heading="Tile with Footer" style="height: 200px;">
|
||||
<div class="tile-demo-content">Content goes here</div>
|
||||
<div slot="footer" class="footer-stats">
|
||||
<span class="stat">latest <strong>42</strong></span>
|
||||
<span class="stat">min <strong>12</strong></span>
|
||||
<span class="stat">max <strong>87</strong></span>
|
||||
<span class="stat">avg <strong>45.3</strong></span>
|
||||
</div>
|
||||
</dees-tile>
|
||||
|
||||
<dees-tile style="height: 200px;">
|
||||
<div slot="header" style="display:flex;align-items:center;gap:12px;width:100%;">
|
||||
<span style="font-weight:500;">Custom Header</span>
|
||||
<input type="text" placeholder="Search..." style="flex:1;max-width:200px;padding:2px 8px;border:1px solid;border-radius:4px;font-size:12px;background:transparent;color:inherit;border-color:inherit;">
|
||||
</div>
|
||||
<div class="tile-demo-content">Custom header slot with search input</div>
|
||||
</dees-tile>
|
||||
</div>
|
||||
</dees-demowrapper>
|
||||
`;
|
||||
};
|
||||
139
ts_web/elements/00group-layout/dees-tile/dees-tile.ts
Normal file
139
ts_web/elements/00group-layout/dees-tile/dees-tile.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
import {
|
||||
customElement,
|
||||
DeesElement,
|
||||
html,
|
||||
css,
|
||||
cssManager,
|
||||
property,
|
||||
state,
|
||||
type TemplateResult,
|
||||
} from '@design.estate/dees-element';
|
||||
import { demoFunc } from './dees-tile.demo.js';
|
||||
import { cssGeistFontFamily } from '../../00fonts.js';
|
||||
import { themeDefaultStyles } from '../../00theme.js';
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'dees-tile': DeesTile;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dees-tile — the unified "rounded on rounded" tile frame.
|
||||
*
|
||||
* RESPONSIBILITIES (what this component owns):
|
||||
* 1. Outer card — border, border-radius, background, overflow clipping
|
||||
* 2. Flex column layout — stacking header / content / footer vertically
|
||||
* 3. Content inset — the rounded inner area with border-top and border-bottom
|
||||
* 4. Default heading — styled 32px heading text when no slot="header" is provided
|
||||
* 5. Footer visibility — auto-hides footer area when slot="footer" is empty
|
||||
*
|
||||
* NOT RESPONSIBILITIES (what consumer components own):
|
||||
* - Header/footer height, padding, font-size, colors when using custom slots
|
||||
* - Content layout (absolute, flex, grid — consumer decides)
|
||||
* - Any semantic meaning of header/footer content
|
||||
*
|
||||
* The header and footer slots are BARE containers (just flex-shrink: 0).
|
||||
* The slotted content fully controls its own appearance.
|
||||
* Only the default heading fallback (.tile-heading) carries tile-level styling.
|
||||
*/
|
||||
@customElement('dees-tile')
|
||||
export class DeesTile extends DeesElement {
|
||||
public static demo = demoFunc;
|
||||
public static demoGroups = ['Layout'];
|
||||
|
||||
@property({ type: String })
|
||||
accessor heading: string = '';
|
||||
|
||||
@state()
|
||||
accessor hasFooter: boolean = false;
|
||||
|
||||
public static styles = [
|
||||
themeDefaultStyles,
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-family: ${cssGeistFontFamily};
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 3.9%)', 'hsl(0 0% 98%)')};
|
||||
}
|
||||
|
||||
/* --- The frame --- */
|
||||
.tile-outer {
|
||||
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%)')};
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* --- Header: bare container, only the default heading gets styled --- */
|
||||
.tile-header {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tile-heading {
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
padding: 0 16px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
letter-spacing: -0.01em;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 63.9%)')};
|
||||
}
|
||||
|
||||
/* --- Content: the rounded inset --- */
|
||||
.tile-content {
|
||||
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%)')};
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tile-content.no-footer {
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
/* --- Footer: bare container, consumer styles the slotted content --- */
|
||||
.tile-footer {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tile-footer.hidden {
|
||||
display: none;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public render(): TemplateResult {
|
||||
return html`
|
||||
<div class="tile-outer" part="outer">
|
||||
<div class="tile-header" part="header">
|
||||
<slot name="header">
|
||||
<div class="tile-heading">${this.heading}</div>
|
||||
</slot>
|
||||
</div>
|
||||
<div class="tile-content ${!this.hasFooter ? 'no-footer' : ''}" part="content">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div class="tile-footer ${!this.hasFooter ? 'hidden' : ''}" part="footer">
|
||||
<slot name="footer" @slotchange=${this.onFooterSlotChange}></slot>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private onFooterSlotChange(e: Event) {
|
||||
const slot = e.target as HTMLSlotElement;
|
||||
this.hasFooter = slot.assignedNodes({ flatten: true }).length > 0;
|
||||
}
|
||||
}
|
||||
1
ts_web/elements/00group-layout/dees-tile/index.ts
Normal file
1
ts_web/elements/00group-layout/dees-tile/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './dees-tile.js';
|
||||
@@ -6,3 +6,4 @@ export * from './dees-label/index.js';
|
||||
export * from './dees-pagination/index.js';
|
||||
export * from './dees-panel/index.js';
|
||||
export * from './dees-stepper/index.js';
|
||||
export * from './dees-tile/index.js';
|
||||
|
||||
@@ -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 {
|
||||
@@ -54,6 +55,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 +89,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' : ''}">
|
||||
${this.showToolbar ? html`
|
||||
<div class="toolbar">
|
||||
<div slot="header" class="toolbar">
|
||||
<div class="toolbar-group">
|
||||
<button
|
||||
class="toolbar-button"
|
||||
@@ -240,7 +244,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 ? '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 +325,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 +349,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 +733,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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -12,25 +12,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,16 +130,15 @@ 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;
|
||||
@@ -334,5 +355,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: ${cssManager.bdTheme('hsl(0 0% 45%)', 'hsl(0 0% 55%)')};
|
||||
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 ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
`,
|
||||
];
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
import * as domtools from '@design.estate/dees-domtools';
|
||||
import { DeesWindowLayer } from '../dees-windowlayer/dees-windowlayer.js';
|
||||
import '../../00group-utility/dees-icon/dees-icon.js';
|
||||
import '../../00group-layout/dees-tile/dees-tile.js';
|
||||
import { themeDefaultStyles } from '../../00theme.js';
|
||||
|
||||
declare global {
|
||||
@@ -128,8 +129,7 @@ export class DeesModal extends DeesElement {
|
||||
/* TODO: Migrate hardcoded values to --dees-* CSS variables */
|
||||
:host {
|
||||
font-family: ${cssGeistFontFamily};
|
||||
color: ${cssManager.bdTheme('#333', '#fff')};
|
||||
will-change: transform;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 95%)')};
|
||||
}
|
||||
.modalContainer {
|
||||
display: flex;
|
||||
@@ -142,106 +142,112 @@ export class DeesModal extends DeesElement {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.modal {
|
||||
will-change: transform;
|
||||
transform: translateY(0px) scale(0.95);
|
||||
dees-tile {
|
||||
will-change: transform, opacity;
|
||||
transform: translateY(8px) scale(0.98);
|
||||
opacity: 0;
|
||||
min-height: 120px;
|
||||
max-height: calc(100vh - 40px);
|
||||
background: ${cssManager.bdTheme('#ffffff', '#09090b')};
|
||||
border-radius: 6px;
|
||||
border: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
|
||||
transition: all 0.2s ease;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06);
|
||||
margin: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: calc(100vh - 80px);
|
||||
transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.2s ease;
|
||||
margin: 40px;
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
|
||||
dees-tile::part(outer) {
|
||||
box-shadow:
|
||||
0 0 0 1px ${cssManager.bdTheme('hsl(0 0% 0% / 0.03)', 'hsl(0 0% 100% / 0.03)')},
|
||||
0 8px 40px ${cssManager.bdTheme('hsl(0 0% 0% / 0.12)', 'hsl(0 0% 0% / 0.5)')},
|
||||
0 2px 8px ${cssManager.bdTheme('hsl(0 0% 0% / 0.06)', 'hsl(0 0% 0% / 0.25)')};
|
||||
}
|
||||
|
||||
/* Width variations */
|
||||
.modal.width-small {
|
||||
dees-tile.width-small {
|
||||
width: 380px;
|
||||
}
|
||||
|
||||
.modal.width-medium {
|
||||
dees-tile.width-medium {
|
||||
width: 560px;
|
||||
}
|
||||
|
||||
.modal.width-large {
|
||||
dees-tile.width-large {
|
||||
width: 800px;
|
||||
}
|
||||
|
||||
.modal.width-fullscreen {
|
||||
dees-tile.width-fullscreen {
|
||||
width: calc(100vw - 40px);
|
||||
height: calc(100vh - 40px);
|
||||
max-height: calc(100vh - 40px);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.modal {
|
||||
dees-tile {
|
||||
width: calc(100vw - 40px) !important;
|
||||
max-width: none !important;
|
||||
}
|
||||
|
||||
/* Allow full height on mobile when content needs it */
|
||||
|
||||
.modalContainer {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.modal {
|
||||
|
||||
dees-tile {
|
||||
margin: 10px;
|
||||
max-height: calc(100vh - 20px);
|
||||
}
|
||||
|
||||
/* Full screen mode on mobile */
|
||||
.modal.mobile-fullscreen {
|
||||
|
||||
dees-tile.mobile-fullscreen {
|
||||
width: 100vw !important;
|
||||
height: 100vh !important;
|
||||
max-height: 100vh !important;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
dees-tile.mobile-fullscreen::part(outer) {
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.modal.show {
|
||||
dees-tile.show {
|
||||
opacity: 1;
|
||||
transform: translateY(0px) scale(1);
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
|
||||
.modal.show.predestroy {
|
||||
dees-tile.show.predestroy {
|
||||
opacity: 0;
|
||||
transform: translateY(10px) scale(1);
|
||||
transform: translateY(6px) scale(0.98);
|
||||
transition: transform 0.15s ease-in, opacity 0.15s ease-in;
|
||||
}
|
||||
|
||||
.modal .heading {
|
||||
height: 40px;
|
||||
min-height: 40px;
|
||||
font-family: ${cssGeistFontFamily};
|
||||
.heading {
|
||||
height: 36px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 12px;
|
||||
border-bottom: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
|
||||
padding: 0 8px 0 16px;
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.modal .heading .header-buttons {
|
||||
.heading .heading-text {
|
||||
flex: 1;
|
||||
font-weight: 500;
|
||||
font-size: 13px;
|
||||
letter-spacing: -0.01em;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 63.9%)')};
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.heading .header-buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
gap: 2px;
|
||||
flex-shrink: 0;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.modal .heading .header-button {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
.heading .header-button {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -249,89 +255,85 @@ export class DeesModal extends DeesElement {
|
||||
cursor: pointer;
|
||||
transition: all 0.15s ease;
|
||||
background: transparent;
|
||||
color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 55%)', 'hsl(0 0% 45%)')};
|
||||
}
|
||||
|
||||
.modal .heading .header-button:hover {
|
||||
background: ${cssManager.bdTheme('#f4f4f5', '#27272a')};
|
||||
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
|
||||
.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%)')};
|
||||
}
|
||||
|
||||
.modal .heading .header-button:active {
|
||||
background: ${cssManager.bdTheme('#e5e7eb', '#3f3f46')};
|
||||
.heading .header-button:active {
|
||||
background: ${cssManager.bdTheme('hsl(0 0% 90%)', 'hsl(0 0% 15%)')};
|
||||
}
|
||||
|
||||
.modal .heading .header-button dees-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
.heading .header-button dees-icon {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.modal .heading .heading-text {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 40px;
|
||||
padding: 0 40px;
|
||||
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
|
||||
}
|
||||
|
||||
.modal .content {
|
||||
flex: 1;
|
||||
.content {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
overscroll-behavior: contain;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: ${cssManager.bdTheme('hsl(0 0% 85%)', 'hsl(0 0% 20%)')} transparent;
|
||||
}
|
||||
.modal .bottomButtons {
|
||||
.bottomButtons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-top: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
padding: 8px;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
gap: 0;
|
||||
height: 36px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.modal .bottomButtons .bottomButton {
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
line-height: 16px;
|
||||
.bottomButtons .bottomButton {
|
||||
padding: 0 16px;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
transition: all 0.15s ease;
|
||||
background: ${cssManager.bdTheme('#ffffff', '#27272a')};
|
||||
border: 1px solid ${cssManager.bdTheme('#e5e7eb', '#3f3f46')};
|
||||
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
|
||||
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%)')};
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal .bottomButtons .bottomButton:hover {
|
||||
background: ${cssManager.bdTheme('#f4f4f5', '#3f3f46')};
|
||||
border-color: ${cssManager.bdTheme('#d1d5db', '#52525b')};
|
||||
}
|
||||
.modal .bottomButtons .bottomButton:active {
|
||||
background: ${cssManager.bdTheme('#e5e7eb', '#52525b')};
|
||||
}
|
||||
.modal .bottomButtons .bottomButton:last-child {
|
||||
border-right: none;
|
||||
.bottomButtons .bottomButton:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.modal .bottomButtons .bottomButton.primary {
|
||||
background: ${cssManager.bdTheme('#3b82f6', '#3b82f6')};
|
||||
border-color: ${cssManager.bdTheme('#3b82f6', '#3b82f6')};
|
||||
color: #ffffff;
|
||||
.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%)')};
|
||||
}
|
||||
.modal .bottomButtons .bottomButton.primary:hover {
|
||||
background: ${cssManager.bdTheme('#2563eb', '#2563eb')};
|
||||
border-color: ${cssManager.bdTheme('#2563eb', '#2563eb')};
|
||||
|
||||
.bottomButtons .bottomButton:active {
|
||||
background: ${cssManager.bdTheme('hsl(0 0% 92%)', 'hsl(0 0% 13%)')};
|
||||
}
|
||||
.modal .bottomButtons .bottomButton.primary:active {
|
||||
background: ${cssManager.bdTheme('#1d4ed8', '#1d4ed8')};
|
||||
border-color: ${cssManager.bdTheme('#1d4ed8', '#1d4ed8')};
|
||||
|
||||
.bottomButtons .bottomButton.primary {
|
||||
color: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8%)', 'hsl(213.1 93.9% 67.8%)')};
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.bottomButtons .bottomButton.primary:hover {
|
||||
background: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8% / 0.08)', 'hsl(213.1 93.9% 67.8% / 0.08)')};
|
||||
color: ${cssManager.bdTheme('hsl(217.2 91.2% 50%)', 'hsl(213.1 93.9% 75%)')};
|
||||
}
|
||||
|
||||
.bottomButtons .bottomButton.primary:active {
|
||||
background: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8% / 0.12)', 'hsl(213.1 93.9% 67.8% / 0.12)')};
|
||||
}
|
||||
`,
|
||||
];
|
||||
@@ -345,13 +347,13 @@ export class DeesModal extends DeesElement {
|
||||
|
||||
return html`
|
||||
<style>
|
||||
${customWidth ? `.modal { width: ${customWidth}; }` : ''}
|
||||
${maxWidthStyle ? `.modal { max-width: ${maxWidthStyle}; }` : ''}
|
||||
${minWidthStyle ? `.modal { min-width: ${minWidthStyle}; }` : ''}
|
||||
${customWidth ? `dees-tile { width: ${customWidth}; }` : ''}
|
||||
${maxWidthStyle ? `dees-tile { max-width: ${maxWidthStyle}; }` : ''}
|
||||
${minWidthStyle ? `dees-tile { min-width: ${minWidthStyle}; }` : ''}
|
||||
</style>
|
||||
<div class="modalContainer" @click=${this.handleOutsideClick} style="z-index: ${this.modalZIndex}">
|
||||
<div class="modal ${widthClass} ${mobileFullscreenClass}">
|
||||
<div class="heading">
|
||||
<dees-tile class="${widthClass} ${mobileFullscreenClass}">
|
||||
<div slot="header" class="heading">
|
||||
<div class="heading-text">${this.heading}</div>
|
||||
<div class="header-buttons">
|
||||
${this.showHelpButton ? html`
|
||||
@@ -368,7 +370,7 @@ export class DeesModal extends DeesElement {
|
||||
</div>
|
||||
<div class="content" style="padding: ${this.contentPadding}px;">${this.content}</div>
|
||||
${this.menuOptions.length > 0 ? html`
|
||||
<div class="bottomButtons">
|
||||
<div slot="footer" class="bottomButtons">
|
||||
${this.menuOptions.map(
|
||||
(actionArg, index) => html`
|
||||
<div class="bottomButton ${index === this.menuOptions.length - 1 ? 'primary' : ''} ${actionArg.name === 'OK' ? 'ok' : ''}" @click=${() => {
|
||||
@@ -378,7 +380,7 @@ export class DeesModal extends DeesElement {
|
||||
)}
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</dees-tile>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
@@ -388,8 +390,8 @@ export class DeesModal extends DeesElement {
|
||||
super.firstUpdated(_changedProperties);
|
||||
const domtools = await this.domtoolsPromise;
|
||||
await domtools.convenience.smartdelay.delayFor(30);
|
||||
const modal = this.shadowRoot!.querySelector('.modal');
|
||||
modal!.classList.add('show');
|
||||
const tile = this.shadowRoot!.querySelector('dees-tile');
|
||||
tile!.classList.add('show');
|
||||
}
|
||||
|
||||
public async handleOutsideClick(eventArg: MouseEvent) {
|
||||
@@ -402,8 +404,8 @@ export class DeesModal extends DeesElement {
|
||||
|
||||
public async destroy() {
|
||||
const domtools = await this.domtoolsPromise;
|
||||
const modal = this.shadowRoot!.querySelector('.modal');
|
||||
modal!.classList.add('predestroy');
|
||||
const tile = this.shadowRoot!.querySelector('dees-tile');
|
||||
tile!.classList.add('predestroy');
|
||||
await domtools.convenience.smartdelay.delayFor(200);
|
||||
document.body.removeChild(this);
|
||||
await this.windowLayer.destroy();
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
} from '@design.estate/dees-element';
|
||||
import { demoFunc } from './dees-shopping-productcard.demo.js';
|
||||
import { themeDefaultStyles } from '../../00theme.js';
|
||||
import '../../00group-layout/dees-tile/dees-tile.js';
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
@@ -61,28 +62,20 @@ export class DeesShoppingProductcard extends DeesElement {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.product-card {
|
||||
background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(215 20.2% 11.8%)')};
|
||||
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
transition: all 0.2s ease;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
dees-tile {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.product-card:hover {
|
||||
dees-tile:hover::part(outer) {
|
||||
border-color: ${cssManager.bdTheme('hsl(0 0% 79.8%)', 'hsl(0 0% 20.9%)')};
|
||||
box-shadow: 0 4px 6px -1px hsl(0 0% 0% / 0.1), 0 2px 4px -2px hsl(0 0% 0% / 0.1);
|
||||
}
|
||||
|
||||
.product-card.selectable {
|
||||
dees-tile.selectable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.product-card.selected {
|
||||
dees-tile.selected::part(outer) {
|
||||
border-color: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8%)', 'hsl(213.1 93.9% 67.8%)')};
|
||||
box-shadow: 0 0 0 3px ${cssManager.bdTheme('hsl(217.2 91.2% 59.8% / 0.1)', 'hsl(213.1 93.9% 67.8% / 0.1)')};
|
||||
}
|
||||
@@ -143,36 +136,48 @@ export class DeesShoppingProductcard extends DeesElement {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.product-content {
|
||||
padding: 16px;
|
||||
.product-header-bar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 32px;
|
||||
padding: 0 16px;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.product-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
|
||||
.product-name {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 63.9%)')};
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.product-category {
|
||||
font-size: 12px;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
color: ${cssManager.bdTheme('hsl(215.4 16.3% 56.9%)', 'hsl(215 20.2% 55.1%)')};
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.product-name {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 95%)')};
|
||||
line-height: 1.4;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.product-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.product-content {
|
||||
padding: 12px 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.product-description {
|
||||
font-size: 13px;
|
||||
color: ${cssManager.bdTheme('hsl(215.4 16.3% 46.9%)', 'hsl(215 20.2% 65.1%)')};
|
||||
@@ -185,8 +190,9 @@ export class DeesShoppingProductcard extends DeesElement {
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
|
||||
padding: 12px 16px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.product-price {
|
||||
@@ -248,66 +254,68 @@ export class DeesShoppingProductcard extends DeesElement {
|
||||
};
|
||||
|
||||
return html`
|
||||
<div
|
||||
class="product-card ${this.selectable ? 'selectable' : ''} ${this.selected ? 'selected' : ''}"
|
||||
<dees-tile
|
||||
class="${this.selectable ? 'selectable' : ''} ${this.selected ? 'selected' : ''}"
|
||||
@click=${this.handleCardClick}
|
||||
>
|
||||
<div class="product-image">
|
||||
${imageUrl ? html`
|
||||
<img src="${imageUrl}" alt="${name}">
|
||||
` : html`
|
||||
<dees-icon .icon=${iconName}></dees-icon>
|
||||
`}
|
||||
${this.selectable ? html`
|
||||
<div
|
||||
class="selection-checkbox ${this.selected ? 'checked' : ''}"
|
||||
@click=${(e: Event) => {
|
||||
e.stopPropagation();
|
||||
this.handleSelectionToggle();
|
||||
}}
|
||||
>
|
||||
<dees-icon .icon=${'lucide:check'}></dees-icon>
|
||||
</div>
|
||||
` : ''}
|
||||
<div slot="header" class="product-header-bar">
|
||||
<span class="product-name">${name}</span>
|
||||
${category ? html`<span class="product-category">${category}</span>` : ''}
|
||||
</div>
|
||||
<div class="product-content">
|
||||
<div class="product-header">
|
||||
${category ? html`<div class="product-category">${category}</div>` : ''}
|
||||
<div class="product-name">${name}</div>
|
||||
</div>
|
||||
${description ? html`
|
||||
<div class="product-description">${description}</div>
|
||||
` : ''}
|
||||
<div class="stock-status ${inStock ? 'in-stock' : 'out-of-stock'}">
|
||||
<dees-icon .icon=${inStock ? 'lucide:check-circle' : 'lucide:x-circle'}></dees-icon>
|
||||
${stockText}
|
||||
</div>
|
||||
<div class="product-footer">
|
||||
<div class="product-price">
|
||||
<span class="price-current">${formatPrice(price)}</span>
|
||||
${originalPrice && originalPrice > price ? html`
|
||||
<span class="price-original">${formatPrice(originalPrice)}</span>
|
||||
` : ''}
|
||||
</div>
|
||||
${this.showQuantitySelector ? html`
|
||||
<dees-input-quantityselector
|
||||
.value=${this.quantity}
|
||||
@changeSubject=${(e: CustomEvent) => {
|
||||
this.quantity = e.detail.getValue();
|
||||
this.dispatchEvent(new CustomEvent('quantityChange', {
|
||||
detail: {
|
||||
quantity: this.quantity,
|
||||
productData: this.productData
|
||||
},
|
||||
bubbles: true,
|
||||
composed: true
|
||||
}));
|
||||
<div class="product-body">
|
||||
<div class="product-image">
|
||||
${imageUrl ? html`
|
||||
<img src="${imageUrl}" alt="${name}">
|
||||
` : html`
|
||||
<dees-icon .icon=${iconName}></dees-icon>
|
||||
`}
|
||||
${this.selectable ? html`
|
||||
<div
|
||||
class="selection-checkbox ${this.selected ? 'checked' : ''}"
|
||||
@click=${(e: Event) => {
|
||||
e.stopPropagation();
|
||||
this.handleSelectionToggle();
|
||||
}}
|
||||
></dees-input-quantityselector>
|
||||
>
|
||||
<dees-icon .icon=${'lucide:check'}></dees-icon>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
<div class="product-content">
|
||||
${description ? html`
|
||||
<div class="product-description">${description}</div>
|
||||
` : ''}
|
||||
<div class="stock-status ${inStock ? 'in-stock' : 'out-of-stock'}">
|
||||
<dees-icon .icon=${inStock ? 'lucide:check-circle' : 'lucide:x-circle'}></dees-icon>
|
||||
${stockText}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="footer" class="product-footer">
|
||||
<div class="product-price">
|
||||
<span class="price-current">${formatPrice(price)}</span>
|
||||
${originalPrice && originalPrice > price ? html`
|
||||
<span class="price-original">${formatPrice(originalPrice)}</span>
|
||||
` : ''}
|
||||
</div>
|
||||
${this.showQuantitySelector ? html`
|
||||
<dees-input-quantityselector
|
||||
.value=${this.quantity}
|
||||
@changeSubject=${(e: CustomEvent) => {
|
||||
this.quantity = e.detail.getValue();
|
||||
this.dispatchEvent(new CustomEvent('quantityChange', {
|
||||
detail: {
|
||||
quantity: this.quantity,
|
||||
productData: this.productData
|
||||
},
|
||||
bubbles: true,
|
||||
composed: true
|
||||
}));
|
||||
}}
|
||||
></dees-input-quantityselector>
|
||||
` : ''}
|
||||
</div>
|
||||
</dees-tile>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -110,6 +110,48 @@ class DemoViewDashboard extends DeesElement {
|
||||
console.log('Tile action:', e.detail);
|
||||
}}
|
||||
></dees-statsgrid>
|
||||
|
||||
<h2 style="margin-top: 40px;">Recent Activity</h2>
|
||||
<p>Below is a log of recent system events and user activity to demonstrate scrollable content.</p>
|
||||
|
||||
${[
|
||||
{ time: '2 min ago', event: 'User john@example.com logged in from 192.168.1.42', type: 'info' },
|
||||
{ time: '5 min ago', event: 'Deployment v3.52.1 completed successfully on production', type: 'success' },
|
||||
{ time: '12 min ago', event: 'Database backup finished — 2.4 GB compressed', type: 'info' },
|
||||
{ time: '18 min ago', event: 'SSL certificate renewed for api.example.com (expires 2027-04-03)', type: 'success' },
|
||||
{ time: '25 min ago', event: 'Memory usage spike on worker-03 (92%) — auto-scaled to 4 instances', type: 'warning' },
|
||||
{ time: '31 min ago', event: 'New user registration: sarah@company.io', type: 'info' },
|
||||
{ time: '45 min ago', event: 'Scheduled job "cleanup-temp-files" completed — removed 1,247 files', type: 'info' },
|
||||
{ time: '1 hour ago', event: 'API rate limit reached for client app-mobile-ios (429 responses)', type: 'warning' },
|
||||
{ time: '1.5 hours ago', event: 'CDN cache purged for /assets/* — 340 objects invalidated', type: 'info' },
|
||||
{ time: '2 hours ago', event: 'Failed login attempt for admin@example.com from 203.0.113.50 (blocked)', type: 'error' },
|
||||
{ time: '2.5 hours ago', event: 'Webhook delivery to https://hooks.slack.com succeeded (200 OK)', type: 'info' },
|
||||
{ time: '3 hours ago', event: 'Cron job "generate-reports" started — processing Q1 2026 data', type: 'info' },
|
||||
{ time: '3.5 hours ago', event: 'Load balancer health check: all 8 nodes healthy', type: 'success' },
|
||||
{ time: '4 hours ago', event: 'DNS propagation complete for new subdomain staging.example.com', type: 'success' },
|
||||
].map(item => html`
|
||||
<div style="
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 12px;
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 90%)', 'hsl(0 0% 12%)')};
|
||||
font-size: 13px;
|
||||
">
|
||||
<span style="
|
||||
flex-shrink: 0;
|
||||
width: 100px;
|
||||
font-size: 11px;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 55%)', 'hsl(0 0% 45%)')};
|
||||
">${item.time}</span>
|
||||
<span style="
|
||||
color: ${item.type === 'error' ? cssManager.bdTheme('hsl(0 72% 50%)', 'hsl(0 72% 65%)') :
|
||||
item.type === 'warning' ? cssManager.bdTheme('hsl(25 95% 50%)', 'hsl(25 95% 63%)') :
|
||||
item.type === 'success' ? cssManager.bdTheme('hsl(142 70% 40%)', 'hsl(142 70% 55%)') :
|
||||
cssManager.bdTheme('hsl(0 0% 30%)', 'hsl(0 0% 75%)')};
|
||||
">${item.event}</span>
|
||||
</div>
|
||||
`)}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,15 +299,51 @@ export class DeesSimpleAppDash extends DeesElement {
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
|
||||
.appcontent::before {
|
||||
content: '';
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: block;
|
||||
height: 8px;
|
||||
margin-bottom: -8px;
|
||||
z-index: 10;
|
||||
pointer-events: none;
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
.controlbar::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
left: 240px;
|
||||
right: 0;
|
||||
height: 8px;
|
||||
pointer-events: none;
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
.controlbar {
|
||||
color: #fff;
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 45%)', 'hsl(0 0% 55%)')};
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: 24px;
|
||||
background: ${cssManager.bdTheme('hsl(220 13% 18%)', 'hsl(220 13% 12%)')};
|
||||
z-index: 2;
|
||||
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%)')};
|
||||
z-index: 11;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
@@ -325,9 +361,10 @@ export class DeesSimpleAppDash extends DeesElement {
|
||||
height: 100%;
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
color: hsl(0 0% 70%);
|
||||
color: ${cssManager.bdTheme('hsl(0 0% 55%)', 'hsl(0 0% 50%)')};
|
||||
transition: all 0.15s ease;
|
||||
border-left: 1px solid hsl(0 0% 100% / 0.08);
|
||||
border-left: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
|
||||
|
||||
}
|
||||
|
||||
.control:first-child {
|
||||
@@ -335,8 +372,8 @@ export class DeesSimpleAppDash extends DeesElement {
|
||||
}
|
||||
|
||||
.control:hover {
|
||||
background: hsl(0 0% 100% / 0.06);
|
||||
color: hsl(0 0% 95%);
|
||||
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%)')};
|
||||
}
|
||||
|
||||
.control dees-icon {
|
||||
|
||||
@@ -11,6 +11,7 @@ import type { Terminal } from 'xterm';
|
||||
import type { FitAddon } from 'xterm-addon-fit';
|
||||
import { themeDefaultStyles } from '../../00theme.js';
|
||||
import { DeesServiceLibLoader } from '../../../services/index.js';
|
||||
import '../../00group-layout/dees-tile/dees-tile.js';
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
@@ -68,27 +69,19 @@ export class DeesWorkspaceTerminalPreview extends DeesElement {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.terminal-preview {
|
||||
dees-tile {
|
||||
height: 100%;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
background: ${cssManager.bdTheme('#ffffff', '#000000')};
|
||||
border: 1px solid ${cssManager.bdTheme('hsl(0 0% 85%)', 'hsl(0 0% 20%)')};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.terminal-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 12px;
|
||||
background: ${cssManager.bdTheme('hsl(0 0% 96%)', 'hsl(0 0% 10%)')};
|
||||
padding: 0 12px;
|
||||
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%)')};
|
||||
border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 85%)', 'hsl(0 0% 20%)')};
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.terminal-header-icon {
|
||||
@@ -101,8 +94,8 @@ export class DeesWorkspaceTerminalPreview extends DeesElement {
|
||||
}
|
||||
|
||||
.terminal-container {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
@@ -262,15 +255,15 @@ export class DeesWorkspaceTerminalPreview extends DeesElement {
|
||||
|
||||
public render(): TemplateResult {
|
||||
return html`
|
||||
<div class="terminal-preview">
|
||||
<div class="terminal-header">
|
||||
<dees-tile>
|
||||
<div slot="header" class="terminal-header">
|
||||
<span class="terminal-header-icon">$</span>
|
||||
<span class="terminal-header-command">${this.command || 'Waiting...'}</span>
|
||||
</div>
|
||||
<div class="terminal-container">
|
||||
<div id="xterm-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
</dees-tile>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -310,23 +310,16 @@ body > div[style*="top: -50000px"][style*="width: 50000px"] {
|
||||
}
|
||||
|
||||
this.tiptapLoadingPromise = (async () => {
|
||||
const version = CDN_VERSIONS.tiptap;
|
||||
|
||||
// Load all Tiptap modules in parallel
|
||||
const [
|
||||
coreModule,
|
||||
starterKitModule,
|
||||
underlineModule,
|
||||
textAlignModule,
|
||||
linkModule,
|
||||
typographyModule,
|
||||
] = await Promise.all([
|
||||
import(/* @vite-ignore */ `${CDN_BASE}/@tiptap/core@${version}/+esm`),
|
||||
import(/* @vite-ignore */ `${CDN_BASE}/@tiptap/starter-kit@${version}/+esm`),
|
||||
import(/* @vite-ignore */ `${CDN_BASE}/@tiptap/extension-underline@${version}/+esm`),
|
||||
import(/* @vite-ignore */ `${CDN_BASE}/@tiptap/extension-text-align@${version}/+esm`),
|
||||
import(/* @vite-ignore */ `${CDN_BASE}/@tiptap/extension-link@${version}/+esm`),
|
||||
import(/* @vite-ignore */ `${CDN_BASE}/@tiptap/extension-typography@${version}/+esm`),
|
||||
// Import directly from npm packages — bundled by esbuild into a single
|
||||
// module graph. CDN loading caused duplicate ProseMirror instances because
|
||||
// jsdelivr resolves each package's dependencies independently.
|
||||
const [coreModule, starterKitModule, underlineModule, textAlignModule, linkModule, typographyModule] = await Promise.all([
|
||||
import('@tiptap/core'),
|
||||
import('@tiptap/starter-kit'),
|
||||
import('@tiptap/extension-underline'),
|
||||
import('@tiptap/extension-text-align'),
|
||||
import('@tiptap/extension-link'),
|
||||
import('@tiptap/extension-typography'),
|
||||
]);
|
||||
|
||||
this.tiptapLib = {
|
||||
|
||||
Reference in New Issue
Block a user