UNPKG

polyv-live-cli

Version:

CLI tool for managing PolyV live streaming services.

346 lines 10.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseComponent = void 0; const monitoring_1 = require("../types/monitoring"); class BaseComponent extends monitoring_1.Component { constructor(config, eventBus) { super(config, eventBus); this.isDestroyed = false; this.lastRenderTime = 0; this.renderThrottleMs = 16; this.focusState = { focused: false, focusable: true, tabIndex: 0, showFocusRing: true, }; this.initializeComponent(); } initializeComponent() { this.state.status = 'initializing'; this.setupEventListeners(); this.createWidget(); this.state.status = 'running'; this.state.lastUpdate = new Date(); } setupEventListeners() { this.subscribe('terminal:resize', this.handleTerminalResize.bind(this)); this.subscribe('theme:change', this.handleThemeChange.bind(this)); this.subscribe('component:update', this.handleComponentUpdate.bind(this)); } throttledRender() { const now = Date.now(); if (now - this.lastRenderTime >= this.renderThrottleMs) { this.render(); this.lastRenderTime = now; } } handleTerminalResize(data) { if (this.isDestroyed) return; const newSize = { minWidth: Math.max(this.config.size.minWidth, data.width * 0.1), minHeight: Math.max(this.config.size.minHeight, data.height * 0.1), maxWidth: data.width, maxHeight: data.height, }; this.resize(newSize); } handleThemeChange(data) { if (this.isDestroyed) return; this.applyTheme(data.theme); this.throttledRender(); } handleComponentUpdate(data) { if (this.isDestroyed) return; if (data.source === this.state.id) return; this.update(data); } applyTheme(_theme) { } startRefresh(intervalMs) { this.stopRefresh(); this.refreshInterval = setInterval(() => { if (!this.isDestroyed) { this.requestUpdate(); } }, intervalMs); } stopRefresh() { if (this.refreshInterval) { clearInterval(this.refreshInterval); this.refreshInterval = undefined; } } requestUpdate() { this.emit('component:requestUpdate', { componentId: this.state.id, type: this.config.type, timestamp: new Date(), }); } updateState(updates) { this.state = { ...this.state, ...updates, lastUpdate: new Date() }; } handleError(error) { this.state.status = 'error'; this.state.error = error; this.emit('component:error', { componentId: this.state.id, type: this.config.type, error: error.message, timestamp: new Date(), }); } resize(size) { if (this.isDestroyed || !this.widget) return; try { this.widget.width = size.maxWidth || size.minWidth; this.widget.height = size.maxHeight || size.minHeight; this.widget.screen?.render(); } catch (error) { this.handleError(error instanceof Error ? error : new Error('Unknown resize error')); } } show() { if (this.widget && !this.isDestroyed) { this.widget.show(); this.widget.screen?.render(); } } hide() { if (this.widget && !this.isDestroyed) { this.widget.hide(); this.widget.screen?.render(); } } destroy() { if (this.isDestroyed) return; this.isDestroyed = true; this.state.status = 'destroyed'; this.stopRefresh(); if (this.focusState.focused) { this.blur(); } if (this.widget) { this.widget.destroy(); } this.emit('component:destroyed', { componentId: this.state.id, type: this.config.type, timestamp: new Date(), }); } getId() { return this.state.id; } getType() { return this.config.type; } canFocus() { return this.focusState.focusable && !this.isDestroyed && this.widget; } focus() { if (!this.canFocus()) return; this.focusState.focused = true; if (this.widget && this.widget.focus) { this.widget.focus(); } this.updateFocusVisuals(); this.emit('component:focused', { componentId: this.state.id, type: this.config.type, timestamp: new Date(), }); } blur() { if (!this.focusState.focused) return; this.focusState.focused = false; this.updateFocusVisuals(); this.emit('component:blurred', { componentId: this.state.id, type: this.config.type, timestamp: new Date(), }); } getFocusState() { return { ...this.focusState }; } handleKeyboard(event) { switch (event.key) { case 'enter': this.handleEnterKey(event); return true; case 'escape': this.handleEscapeKey(event); return true; case 'space': this.handleSpaceKey(event); return true; default: return this.handleCustomKeyboard(event); } } handleMouse(event) { if (!this.isMouseEventInBounds(event)) { return false; } switch (event.action) { case 'mousedown': if (event.button === 'left') { this.handleMouseClick(event); return true; } else if (event.button === 'right') { this.handleRightClick(event); return true; } break; case 'wheelup': case 'wheeldown': this.handleMouseWheel(event); return true; case 'mousemove': this.handleMouseMove(event); return true; } return false; } setTabIndex(index) { this.focusState.tabIndex = index; } setFocusable(focusable) { this.focusState.focusable = focusable; if (!focusable && this.focusState.focused) { this.blur(); } } setShowFocusRing(show) { this.focusState.showFocusRing = show; this.updateFocusVisuals(); } updateFocusVisuals() { if (!this.widget) return; if (this.focusState.focused && this.focusState.showFocusRing) { if (this.widget.style) { this.widget.style.border = this.widget.style.border || {}; this.widget.style.border.fg = 'cyan'; this.widget.style.border.bold = true; } } else { if (this.widget.style && this.widget.style.border) { this.widget.style.border.fg = this.widget.style.border.fg === 'cyan' ? 'white' : this.widget.style.border.fg; this.widget.style.border.bold = false; } } this.throttledRender(); } handleEnterKey(event) { this.emit('component:activated', { componentId: this.state.id, type: this.config.type, event, timestamp: new Date(), }); } handleEscapeKey(event) { this.emit('component:cancelled', { componentId: this.state.id, type: this.config.type, event, timestamp: new Date(), }); } handleSpaceKey(event) { this.handleEnterKey(event); } handleCustomKeyboard(_event) { return false; } handleMouseClick(event) { this.emit('component:clicked', { componentId: this.state.id, type: this.config.type, event, timestamp: new Date(), }); } handleRightClick(event) { this.emit('component:contextmenu', { componentId: this.state.id, type: this.config.type, event, timestamp: new Date(), }); } handleMouseWheel(event) { this.emit('component:scroll', { componentId: this.state.id, type: this.config.type, event, direction: event.action === 'wheelup' ? 'up' : 'down', timestamp: new Date(), }); } handleMouseMove(event) { this.emit('component:hover', { componentId: this.state.id, type: this.config.type, event, timestamp: new Date(), }); } isMouseEventInBounds(event) { if (!this.widget) return false; const bounds = this.getComponentBounds(); if (!bounds) return false; return event.x >= bounds.left && event.x <= bounds.right && event.y >= bounds.top && event.y <= bounds.bottom; } getComponentBounds() { if (!this.widget) return null; if (typeof this.widget.aleft === 'number' && typeof this.widget.atop === 'number') { const left = this.widget.aleft; const top = this.widget.atop; const width = this.widget.width || 0; const height = this.widget.height || 0; return { left, top, right: left + width - 1, bottom: top + height - 1, }; } const left = this.widget.left || 0; const top = this.widget.top || 0; const width = this.widget.width || 0; const height = this.widget.height || 0; let parentLeft = 0; let parentTop = 0; if (this.widget.parent) { parentLeft = this.widget.parent.aleft || 0; parentTop = this.widget.parent.atop || 0; } return { left: parentLeft + left, top: parentTop + top, right: parentLeft + left + width - 1, bottom: parentTop + top + height - 1, }; } } exports.BaseComponent = BaseComponent; //# sourceMappingURL=base.component.js.map