import { DeesElement, customElement, html, css, cssManager, property, state, type TemplateResult, } from '@design.estate/dees-element'; import type { ISgOrganization } from '../interfaces.js'; declare global { interface HTMLElementTagNameMap { 'sg-organizations-list-view': SgOrganizationsListView; } } @customElement('sg-organizations-list-view') export class SgOrganizationsListView extends DeesElement { public static demo = () => html`
`; public static demoGroups = ['Organizations']; @property({ type: Array }) public accessor organizations: ISgOrganization[] = []; @state() accessor showCreateForm: boolean = false; @state() accessor createName: string = ''; @state() accessor createDisplayName: string = ''; @state() accessor createDescription: string = ''; public static styles = [ cssManager.defaultStyles, css` :host { display: block; color: ${cssManager.bdTheme('#111', '#fff')}; } .container { display: flex; flex-direction: column; gap: 24px; } .header { display: flex; justify-content: space-between; align-items: center; } .page-title { font-size: 24px; font-weight: 700; letter-spacing: -0.02em; } .create-btn { display: inline-flex; align-items: center; gap: 6px; padding: 8px 16px; background: ${cssManager.bdTheme('#111', '#fff')}; border: none; font-size: 13px; font-weight: 600; color: ${cssManager.bdTheme('#fff', '#111')}; cursor: pointer; transition: opacity 150ms ease; } .create-btn:hover { opacity: 0.85; } .create-btn svg { width: 14px; height: 14px; } .orgs-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 1px; background: ${cssManager.bdTheme('#e5e5e5', '#333')}; border: 1px solid ${cssManager.bdTheme('#e5e5e5', '#333')}; } .org-card { background: ${cssManager.bdTheme('#fff', '#111')}; padding: 20px; cursor: pointer; transition: background 100ms ease; display: flex; flex-direction: column; gap: 8px; } .org-card:hover { background: ${cssManager.bdTheme('#fafafa', '#1a1a1a')}; } .org-header { display: flex; align-items: center; gap: 12px; } .org-avatar { width: 40px; height: 40px; background: ${cssManager.bdTheme('#e5e5e5', '#333')}; display: flex; align-items: center; justify-content: center; font-size: 18px; font-weight: 700; color: ${cssManager.bdTheme('#666', '#999')}; flex-shrink: 0; } .org-titles { min-width: 0; } .org-name { font-size: 16px; font-weight: 600; color: ${cssManager.bdTheme('#111', '#fff')}; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .org-handle { font-size: 12px; font-family: 'JetBrains Mono', monospace; color: ${cssManager.bdTheme('#888', '#777')}; } .org-description { font-size: 13px; color: ${cssManager.bdTheme('#666', '#aaa')}; line-height: 1.4; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .org-footer { display: flex; gap: 16px; font-size: 12px; color: ${cssManager.bdTheme('#888', '#777')}; margin-top: 4px; } .visibility-badge { display: inline-flex; align-items: center; padding: 1px 6px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; } .visibility-badge.public { background: rgba(34, 197, 94, 0.15); color: #22c55e; } .visibility-badge.private { background: rgba(239, 68, 68, 0.15); color: #ef4444; } .empty-state { text-align: center; padding: 64px 32px; border: 1px solid ${cssManager.bdTheme('#e5e5e5', '#333')}; background: ${cssManager.bdTheme('#fff', '#111')}; } .empty-title { font-size: 16px; font-weight: 600; color: ${cssManager.bdTheme('#111', '#fff')}; margin-bottom: 8px; } .empty-text { font-size: 14px; color: ${cssManager.bdTheme('#888', '#777')}; margin-bottom: 20px; } /* Create form */ .create-form { background: ${cssManager.bdTheme('#fff', '#111')}; border: 1px solid ${cssManager.bdTheme('#e5e5e5', '#333')}; padding: 24px; display: flex; flex-direction: column; gap: 16px; } .create-form-title { font-size: 16px; font-weight: 600; } .form-group { display: flex; flex-direction: column; gap: 6px; } .form-label { font-size: 13px; font-weight: 600; color: ${cssManager.bdTheme('#111', '#ddd')}; text-transform: uppercase; letter-spacing: 0.04em; } .form-input, .form-textarea { padding: 10px 12px; background: ${cssManager.bdTheme('#fff', '#0a0a0a')}; border: 1px solid ${cssManager.bdTheme('#ddd', '#333')}; font-size: 14px; color: ${cssManager.bdTheme('#111', '#fff')}; outline: none; font-family: inherit; max-width: 400px; } .form-input:focus, .form-textarea:focus { border-color: ${cssManager.bdTheme('#111', '#fff')}; } .form-textarea { resize: vertical; min-height: 60px; max-width: 400px; } .form-hint { font-size: 12px; color: ${cssManager.bdTheme('#aaa', '#666')}; } .form-actions { display: flex; gap: 8px; margin-top: 4px; } .submit-btn { padding: 8px 20px; background: ${cssManager.bdTheme('#111', '#fff')}; border: none; font-size: 13px; font-weight: 600; color: ${cssManager.bdTheme('#fff', '#111')}; cursor: pointer; transition: opacity 150ms ease; } .submit-btn:hover { opacity: 0.85; } .cancel-btn { padding: 8px 20px; background: transparent; border: 1px solid ${cssManager.bdTheme('#ddd', '#333')}; font-size: 13px; font-weight: 500; color: ${cssManager.bdTheme('#333', '#ddd')}; cursor: pointer; transition: all 150ms ease; } .cancel-btn:hover { border-color: ${cssManager.bdTheme('#111', '#fff')}; color: ${cssManager.bdTheme('#111', '#fff')}; } `, ]; public render(): TemplateResult { return html`
Organizations
${this.showCreateForm ? html`
Create Organization
{ this.createName = (e.target as HTMLInputElement).value; }} placeholder="my-org" > Lowercase letters, numbers, and dashes only
{ this.createDisplayName = (e.target as HTMLInputElement).value; }} placeholder="My Organization" >
` : ''} ${this.organizations.length > 0 ? html`
${this.organizations.map( (org) => html`
this.handleSelect(org.id)}>
${(org.displayName || org.name).charAt(0).toUpperCase()}
${org.displayName || org.name}
@${org.name}
${org.description ? html`
${org.description}
` : ''}
` )}
` : html`
No organizations yet
Create an organization to start publishing packages.
`}
`; } private handleCreate() { this.showCreateForm = true; } private handleCreateSubmit() { if (!this.createName.trim()) return; this.dispatchEvent( new CustomEvent('create', { detail: { name: this.createName.trim(), displayName: this.createDisplayName.trim(), description: this.createDescription.trim(), }, bubbles: true, composed: true, }) ); this.createName = ''; this.createDisplayName = ''; this.createDescription = ''; this.showCreateForm = false; } private handleCreateCancel() { this.createName = ''; this.createDisplayName = ''; this.createDescription = ''; this.showCreateForm = false; } private handleSelect(organizationId: string) { this.dispatchEvent( new CustomEvent('select', { detail: { organizationId }, bubbles: true, composed: true, }) ); } }