import { DeesElement, customElement, html, css, cssManager, property, type TemplateResult, } from '@design.estate/dees-element'; import type { ISgRepository, ISgPackage } from '../interfaces.js'; import './sg-protocol-badge.js'; declare global { interface HTMLElementTagNameMap { 'sg-repository-detail-view': SgRepositoryDetailView; } } @customElement('sg-repository-detail-view') export class SgRepositoryDetailView extends DeesElement { public static demo = () => html`
`; public static demoGroups = ['Repositories']; @property({ type: Object }) public accessor repository: ISgRepository = { id: '', organizationId: '', name: '', protocol: 'npm', visibility: 'public', isPublic: true, packageCount: 0, createdAt: '', }; @property({ type: Array }) public accessor packages: ISgPackage[] = []; public static styles = [ cssManager.defaultStyles, css` :host { display: block; color: ${cssManager.bdTheme('#111', '#fff')}; } .container { display: flex; flex-direction: column; gap: 24px; } .back-btn { display: inline-flex; align-items: center; gap: 6px; padding: 0; background: transparent; border: none; font-size: 13px; color: ${cssManager.bdTheme('#666', '#999')}; cursor: pointer; transition: color 150ms ease; } .back-btn:hover { color: ${cssManager.bdTheme('#111', '#fff')}; } /* Repo header */ .repo-header { display: flex; flex-direction: column; gap: 12px; padding: 24px; background: ${cssManager.bdTheme('#fff', '#111')}; border: 1px solid ${cssManager.bdTheme('#e5e5e5', '#333')}; } .repo-title-row { display: flex; align-items: center; gap: 12px; } .repo-name { font-size: 22px; font-weight: 700; font-family: 'JetBrains Mono', monospace; letter-spacing: -0.01em; } .repo-description { font-size: 14px; color: ${cssManager.bdTheme('#666', '#aaa')}; line-height: 1.5; } .repo-meta { display: flex; gap: 16px; font-size: 13px; color: ${cssManager.bdTheme('#888', '#777')}; flex-wrap: wrap; } .visibility-tag { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; padding: 2px 8px; } .visibility-tag.public { background: rgba(34, 197, 94, 0.15); color: #22c55e; } .visibility-tag.private { background: rgba(239, 68, 68, 0.15); color: #ef4444; } .visibility-tag.internal { background: rgba(59, 130, 246, 0.15); color: #3b82f6; } /* Package list */ .packages-section { display: flex; flex-direction: column; gap: 12px; } .section-title { font-size: 16px; font-weight: 600; } .package-list { display: flex; flex-direction: column; border: 1px solid ${cssManager.bdTheme('#e5e5e5', '#333')}; } .package-row { display: flex; align-items: center; justify-content: space-between; padding: 14px 16px; background: ${cssManager.bdTheme('#fff', '#111')}; border-bottom: 1px solid ${cssManager.bdTheme('#e5e5e5', '#333')}; cursor: pointer; transition: background 100ms ease; } .package-row:last-child { border-bottom: none; } .package-row:hover { background: ${cssManager.bdTheme('#fafafa', '#1a1a1a')}; } .package-info { display: flex; flex-direction: column; gap: 4px; min-width: 0; } .package-name { font-size: 14px; font-weight: 600; font-family: 'JetBrains Mono', monospace; color: ${cssManager.bdTheme('#111', '#fff')}; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .package-description { font-size: 13px; color: ${cssManager.bdTheme('#666', '#aaa')}; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .package-right { display: flex; align-items: center; gap: 12px; flex-shrink: 0; } .version-tag { font-size: 12px; font-family: 'JetBrains Mono', monospace; color: ${cssManager.bdTheme('#666', '#999')}; background: ${cssManager.bdTheme('#f5f5f5', '#1a1a1a')}; padding: 2px 8px; border: 1px solid ${cssManager.bdTheme('#e5e5e5', '#333')}; } .download-count { font-size: 12px; color: ${cssManager.bdTheme('#888', '#777')}; font-family: 'JetBrains Mono', monospace; } .private-badge { font-size: 10px; font-weight: 600; text-transform: uppercase; padding: 1px 5px; background: rgba(239, 68, 68, 0.15); color: #ef4444; } .empty-state { text-align: center; padding: 48px 32px; font-size: 14px; color: ${cssManager.bdTheme('#888', '#777')}; border: 1px solid ${cssManager.bdTheme('#e5e5e5', '#333')}; background: ${cssManager.bdTheme('#fff', '#111')}; } `, ]; public render(): TemplateResult { return html`
${this.repository.name} ${this.repository.visibility}
${this.repository.description ? html`
${this.repository.description}
` : ''}
${this.repository.packageCount} package${this.repository.packageCount !== 1 ? 's' : ''} Protocol: ${this.repository.protocol.toUpperCase()} Created: ${this.formatDate(this.repository.createdAt)}
Packages
${this.packages.length > 0 ? html`
${this.packages.map( (pkg) => html`
this.emitEvent('select-package', { packageId: pkg.id })}>
${pkg.name}
${pkg.description ? html`
${pkg.description}
` : ''}
${pkg.isPrivate ? html`Private` : ''} ${pkg.latestVersion ? html`${pkg.latestVersion}` : ''} ${this.formatNumber(pkg.downloadCount)} pulls
` )}
` : html`
No packages published to this repository yet.
`}
`; } private formatNumber(n: number): string { if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`; if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`; return n.toString(); } private formatDate(dateStr: string): string { if (!dateStr) return ''; try { return new Date(dateStr).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' }); } catch { return dateStr; } } private emitEvent(name: string, detail: Record) { this.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true })); } }