import { DeesElement, property, html, customElement, type TemplateResult, css } from '@design.estate/dees-element';
import { demoDocuments, icon, type IDocumentRow, type TDensity, type TWorkspaceTheme, type TWorkspaceView } from './sdig-workspace.shared.js';
import './sdig-workspace-inbox.js';
import './sdig-workspace-compose.js';
import './sdig-workspace-sign.js';
import './sdig-workspace-audit.js';
import './sdig-workspace-developers.js';
import './sdig-workspace-placeholder.js';
declare global {
interface HTMLElementTagNameMap {
'sdig-workspace': SdigWorkspace;
}
}
@customElement('sdig-workspace')
export class SdigWorkspace extends DeesElement {
public static demo = () => html``;
public static demoGroups = ['Signature Digital Workspace'];
@property({ type: String }) public accessor accent: string = '#3b82f6';
@property({ type: String }) public accessor density: TDensity = 'comfortable';
@property({ type: String, reflect: true }) public accessor theme: TWorkspaceTheme = 'dark';
@property({ type: String }) public accessor initialView: TWorkspaceView = 'inbox';
@property({ type: String, reflect: true }) public accessor view: TWorkspaceView = 'inbox';
@property({ attribute: false }) public accessor documents: IDocumentRow[] = demoDocuments;
public connectedCallback = async () => {
await super.connectedCallback();
if (this.view === 'inbox' && this.initialView !== 'inbox') {
this.view = this.initialView;
}
this.addEventListener('workspace-view-request', this.handleViewRequest as EventListener);
};
public disconnectedCallback = async () => {
this.removeEventListener('workspace-view-request', this.handleViewRequest as EventListener);
await super.disconnectedCallback();
};
public static styles = css`
:host {
display: block;
width: 100%;
height: 100%;
min-height: 720px;
--accent: #3b82f6;
--bg: hsl(0 0% 3.9%);
--bg-el: hsl(0 0% 6%);
--bg-card: hsl(0 0% 7%);
--bg-input: hsl(0 0% 9%);
--border: hsl(0 0% 14.9%);
--border-subtle: hsl(0 0% 11%);
--border-strong: hsl(0 0% 20%);
--text: hsl(0 0% 98%);
--text-sec: hsl(0 0% 63.9%);
--text-muted: hsl(0 0% 48%);
--text-dim: hsl(0 0% 32%);
--hover: rgba(255,255,255,0.06);
--hover-subtle: rgba(255,255,255,0.03);
--row-hover: rgba(255,255,255,0.025);
--success: #22c55e;
--warning: #f59e0b;
--error: #ef4444;
font-family: Geist, Inter, Roboto, -apple-system, BlinkMacSystemFont, sans-serif;
}
:host([theme='light']) {
--bg: hsl(0 0% 99%);
--bg-el: hsl(0 0% 97%);
--bg-card: hsl(0 0% 100%);
--bg-input: hsl(0 0% 98%);
--border: hsl(0 0% 90%);
--border-subtle: hsl(0 0% 93%);
--border-strong: hsl(0 0% 80%);
--text: hsl(0 0% 9%);
--text-sec: hsl(0 0% 32%);
--text-muted: hsl(0 0% 45%);
--text-dim: hsl(0 0% 62%);
--hover: rgba(0,0,0,0.04);
--hover-subtle: rgba(0,0,0,0.02);
--row-hover: rgba(0,0,0,0.02);
--success: #16a34a;
--warning: #d97706;
--error: #dc2626;
}
* { box-sizing: border-box; }
button { font: inherit; border: 0; cursor: pointer; }
.workspace { display: flex; height: 100%; min-height: 720px; background: var(--bg); color: var(--text); overflow: hidden; }
.sidebar { width: 220px; background: var(--bg); border-right: 1px solid var(--border-subtle); display: flex; flex-direction: column; flex-shrink: 0; height: 100%; }
.brand { padding: 14px 16px 12px; display: flex; align-items: center; gap: 8px; }
.logomark { width: 26px; height: 26px; border-radius: 6px; background: var(--bg-el); border: 1px solid var(--border-strong); display: inline-flex; align-items: center; justify-content: center; font-family: 'Plus Jakarta Sans', Inter, sans-serif; font-size: 13px; font-weight: 700; position: relative; }
.logomark::after, .wordmark::after { content: ''; display: inline-block; border-radius: 50%; background: var(--accent); }
.logomark::after { width: 4px; height: 4px; position: absolute; right: 5px; bottom: 5px; }
.wordmark { font-size: 13px; font-weight: 500; letter-spacing: -0.02em; white-space: nowrap; }
.wordmark .dot { color: var(--text-muted); }
.wordmark::after { width: 4px; height: 4px; margin-left: 3px; transform: translateY(-1px); }
.workspace-card { margin: 0 12px 8px; padding: 7px 10px; background: var(--bg-el); border: 1px solid var(--border-subtle); border-radius: 6px; display: flex; align-items: center; gap: 8px; }
.workspace-badge { width: 18px; height: 18px; border-radius: 4px; background: linear-gradient(135deg, var(--accent), hsl(280 70% 60%)); color: white; font-size: 10px; font-weight: 700; display: flex; align-items: center; justify-content: center; }
.workspace-name { font-size: 12px; font-weight: 500; line-height: 1.2; }
.workspace-plan { font-size: 10px; color: var(--text-muted); }
.nav-block { padding: 4px 0; }
.nav-item { display: flex; align-items: center; gap: 10px; padding: 7px 10px; margin: 1px 8px; border-radius: 6px; color: var(--text-muted); background: transparent; transition: all 0.1s ease; font-size: 13px; position: relative; width: calc(100% - 16px); text-align: left; }
.compact .nav-item { padding: 5px 10px; }
.nav-item:hover { background: var(--hover-subtle); color: var(--text-sec); }
.nav-item.active { background: var(--hover); color: var(--text); font-weight: 500; }
.nav-item.active::before { content: ''; position: absolute; left: -8px; width: 2px; height: 14px; border-radius: 2px; background: var(--accent); }
.nav-count { margin-left: auto; min-width: 18px; padding: 1px 6px; border-radius: 999px; background: var(--bg-el); color: var(--text-muted); font-size: 10px; text-align: center; }
.github-card { margin: 8px 12px; padding: 10px; border: 1px solid var(--border-subtle); border-radius: 6px; background: var(--bg-el); }
.sparkline { margin-top: 8px; display: flex; gap: 2px; align-items: flex-end; height: 18px; }
.sparkline span { flex: 1; background: var(--border-strong); border-radius: 1px; }
.sparkline span:nth-last-child(-n+4) { background: var(--accent); }
.user-card { padding: 8px 12px; border-top: 1px solid var(--border-subtle); display: flex; align-items: center; gap: 10px; }
.avatar { width: 26px; height: 26px; border-radius: 50%; background: var(--accent); color: white; font-size: 11px; font-weight: 700; display: flex; align-items: center; justify-content: center; }
.main { flex: 1; min-width: 0; display: flex; flex-direction: column; overflow: hidden; }
.view-host { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.statusbar { height: 24px; flex-shrink: 0; border-top: 1px solid var(--border-subtle); background: var(--bg); display: flex; align-items: center; padding: 0 16px; gap: 16px; font-size: 10px; color: var(--text-dim); font-family: 'Intel One Mono', ui-monospace, SFMono-Regular, Menlo, monospace; }
@media (max-width: 920px) { .workspace { flex-direction: column; min-height: 100vh; } .sidebar { width: 100%; height: auto; border-right: 0; border-bottom: 1px solid var(--border-subtle); } .brand, .workspace-card, .github-card, .user-card { display: none; } .nav-block { display: flex; overflow-x: auto; padding: 8px; } .nav-item { width: auto; margin: 0 2px; } .statusbar { display: none; } }
`;
private handleViewRequest = (event: CustomEvent<{ view: TWorkspaceView }>) => {
this.setView(event.detail.view);
};
private setView(viewArg: TWorkspaceView) {
this.view = viewArg;
this.dispatchEvent(new CustomEvent('view-change', { detail: { view: viewArg }, bubbles: true, composed: true }));
}
private navButton(item: { id: TWorkspaceView; label: string; icon: string; count?: number }): TemplateResult {
return html``;
}
private renderSidebar(): TemplateResult {
const navItems = [
{ id: 'inbox', label: 'Inbox', icon: 'inbox', count: this.documents.length },
{ id: 'compose', label: 'Compose', icon: 'plus' },
{ id: 'templates', label: 'Templates', icon: 'folder', count: 12 },
{ id: 'audit', label: 'Audit Trail', icon: 'shield' },
{ id: 'developers', label: 'Developers', icon: 'code' },
] as Array<{ id: TWorkspaceView; label: string; icon: string; count?: number }>;
const lowerItems = [
{ id: 'team', label: 'Team', icon: 'user' },
{ id: 'settings', label: 'Settings', icon: 'settings' },
] as Array<{ id: TWorkspaceView; label: string; icon: string }>;
return html`
`;
}
private renderView(): TemplateResult {
switch (this.view) {
case 'inbox': return html``;
case 'compose': return html``;
case 'sign': return html``;
case 'audit': return html``;
case 'developers': return html``;
case 'templates': return html``;
case 'team': return html``;
case 'settings': return html``;
default: return html``;
}
}
public render(): TemplateResult {
return html`
${this.renderSidebar()}
${this.renderView()}api.signature.digitaleu-central-14 sigs queuedOpen Source · MITv0.42.1${icon('git', 11)} main `;
}
}