import { NostrService } from '../../common/nostr-service'; import { Theme } from '../../common/types'; export declare enum NCStatus { Idle = 0,// 0 Loading = 1,// 1 Ready = 2,// 2 Error = 3 } /** * NostrBaseComponent * ================== * Foundation for all Nostr web components in this library. * * Overview * - Manages relay connectivity via a shared `NostrService`. * - Parses common attributes (`theme`, `relays`) and applies theme. * - Provides a generic status management logic, that is extensible by derived classes. * - Offers small utilities useful to subclasses (event delegation, error snippet). * * Observed attributes * - `data-theme` — "light" | "dark" * - `relays` — CSV of relay URLs * * Events * - `nc:status` — from base, reflects connection and user/profile loading status * * TODO: Is this class doing too much work? Time to split into smaller components? */ export declare abstract class NostrBaseComponent extends HTMLElement { protected nostrService: NostrService; protected theme: Theme; protected errorMessage: string; protected nostrReady: Promise; protected nostrReadyResolve?: () => void; protected nostrReadyReject?: (e: unknown) => void; protected conn: { set: (s: NCStatus, e?: string) => void; get: () => NCStatus; }; private _statuses; private _overall; private connectSeq; private _delegatedListeners; constructor(shadow?: boolean); /** Lifecycle methods */ static get observedAttributes(): string[]; connectedCallback(): void; disconnectedCallback(): void; attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void; /** Status map API */ protected setStatusFor(key: string, next: NCStatus, error?: string): void; protected getStatusFor(key: string): NCStatus; protected snapshotStatuses(): Record; /** Overall status change hook */ protected onStatusChange(_overall: NCStatus): void; /** Hook for subclasses to react when relays are connected */ protected onNostrRelaysConnected(): void; protected computeOverall(): NCStatus; /** * Before first channel.set(), the map won't be set and hence get() will return `idle`. * In some cases (or maybe in all cases), this is not ideal. * In UserComponent, 'user' not set and hence returning `idle`, while * 'connect' switched between idle -> loading -> ready * and then * 'user' switches to loading -> ready, * results in loading -> ready -> loading -> ready in profile-badge onStatusChange. * * To avoid this, this function is called from UserComponent constructor, * to set default value as 'loading' without emitting onStatusChange event. * * Makes sense? * Try commenting this function call in UserComponent() * and add a log in ProfileBadge :: onStatusChange. You will get it. */ protected initChannelStatus(key: string, status: NCStatus, opts?: { reflectOverall: boolean; }): void; protected channel(key: string): { set: (s: NCStatus, e?: string) => void; get: () => NCStatus; }; /** Protected methods */ protected validateInputs(): boolean; protected connectToNostr(): Promise; protected ensureNostrConnected(): Promise; protected getRelays(): string[]; protected getTheme(): void; /** * Delegate events within shadow DOM. * Example: this.delegateEvent('click', '#npub-copy', (e) => this.copyNpub(e)); * * Note: Listeners are automatically cleaned up in disconnectedCallback() to prevent memory leaks. */ protected delegateEvent(type: K, selector: string, handler: (event: HTMLElementEventMap[K]) => void): void; protected addDelegatedListener(type: K, selector: string, handler: (event: HTMLElementEventMap[K]) => void): void; protected renderError(errorMessage: string): string; /** * Updates host element classes based on component status * This is a common pattern used by all components */ protected updateHostClasses(): void; /** * Base render method that handles common render logic * Subclasses should override renderContent() instead of render() */ protected render(): void; /** * Handles click events with njump.me default action * Creates custom event, dispatches it, and opens njump.me if not prevented */ protected handleNjumpClick(eventType: string, detail: any, njumpPath: string): void; /** * Abstract method for component-specific rendering * Must be implemented by subclasses */ protected abstract renderContent(): void; /** Private methods */ private resetNostrReadyBarrier; }