polyv-live-cli
Version:
CLI tool for managing PolyV live streaming services.
458 lines • 16.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CustomThemeBuilder = void 0;
const events_1 = require("events");
const config_validator_1 = require("./config-validator");
const errors_1 = require("../utils/errors");
class CustomThemeBuilder extends events_1.EventEmitter {
constructor(options = {}) {
super();
this.currentTheme = {};
this.colorPalettes = new Map();
this.templates = new Map();
this.validationErrors = [];
this.validationWarnings = [];
this.options = {
enablePreview: options.enablePreview ?? true,
autoValidate: options.autoValidate ?? true,
strictMode: options.strictMode ?? false,
};
this.loadBuiltInColorPalettes();
this.loadBuiltInTemplates();
this.initializeTheme();
}
startNew(baseTemplate) {
if (baseTemplate && this.templates.has(baseTemplate)) {
const template = this.templates.get(baseTemplate);
this.currentTheme = JSON.parse(JSON.stringify(template.baseTheme));
}
else {
this.initializeTheme();
}
this.emit('theme:started', this.currentTheme);
return this;
}
loadTheme(theme) {
this.currentTheme = JSON.parse(JSON.stringify(theme));
if (this.options.autoValidate) {
this.validateCurrentTheme();
}
this.emit('theme:loaded', this.currentTheme);
return this;
}
setThemeInfo(info) {
this.currentTheme.id = info.id;
this.currentTheme.name = info.name;
if (info.description !== undefined) {
this.currentTheme.description = info.description;
}
if (info.author !== undefined) {
this.currentTheme.author = info.author;
}
this.currentTheme.version = info.version || '1.0.0';
this.currentTheme.isBuiltIn = false;
this.validateAndEmit('theme:info-updated');
return this;
}
setColors(colors) {
if (typeof colors === 'string') {
const palette = this.colorPalettes.get(colors);
if (!palette) {
throw new errors_1.ConfigurationError(`Color palette '${colors}' not found`);
}
this.currentTheme.colors = this.paletteToColorScheme(palette);
}
else {
this.currentTheme.colors = {
...this.getDefaultColors(),
...this.currentTheme.colors,
...colors,
};
}
this.validateAndEmit('theme:colors-updated');
return this;
}
setColor(colorName, colorValue) {
if (!this.currentTheme.colors) {
this.currentTheme.colors = this.getDefaultColors();
}
this.currentTheme.colors[colorName] = colorValue;
this.validateAndEmit('theme:color-updated', { colorName, colorValue });
return this;
}
setFonts(fonts) {
this.currentTheme.fonts = {
...this.getDefaultFonts(),
...this.currentTheme.fonts,
...fonts,
};
this.validateAndEmit('theme:fonts-updated');
return this;
}
setBorders(borders) {
this.currentTheme.borders = {
...this.getDefaultBorders(),
...this.currentTheme.borders,
...borders,
};
this.validateAndEmit('theme:borders-updated');
return this;
}
setComponentStyles(componentStyles) {
this.currentTheme.components = {
...this.getDefaultComponentStyles(),
...this.currentTheme.components,
...componentStyles,
};
this.validateAndEmit('theme:components-updated');
return this;
}
setComponentStyle(componentName, style) {
if (!this.currentTheme.components) {
this.currentTheme.components = this.getDefaultComponentStyles();
}
this.currentTheme.components[componentName] = {
...this.currentTheme.components[componentName],
...style,
};
this.validateAndEmit('theme:component-style-updated', { componentName, style });
return this;
}
transformColors(transformation) {
if (!this.currentTheme.colors) {
this.currentTheme.colors = this.getDefaultColors();
}
const transformedColors = {};
for (const [key, value] of Object.entries(this.currentTheme.colors)) {
transformedColors[key] = transformation(value);
}
this.currentTheme.colors = {
...this.currentTheme.colors,
...transformedColors,
};
this.validateAndEmit('theme:colors-transformed');
return this;
}
adjustBrightness(factor) {
return this.transformColors(color => this.adjustColorBrightness(color, factor));
}
adjustSaturation(factor) {
return this.transformColors(color => this.adjustColorSaturation(color, factor));
}
generateComplementaryScheme(baseColor) {
const complementaryColors = this.generateComplementaryColors(baseColor);
return this.setColors(complementaryColors);
}
validateCurrentTheme() {
try {
const completeTheme = this.buildCompleteTheme();
const validation = config_validator_1.ConfigValidator.validateThemeConfig(completeTheme);
this.validationErrors = [...validation.errors, ...validation.critical];
this.validationWarnings = validation.warnings;
return {
valid: validation.valid,
errors: this.validationErrors,
warnings: this.validationWarnings,
};
}
catch (error) {
this.validationErrors = [error instanceof Error ? error.message : String(error)];
this.validationWarnings = [];
return {
valid: false,
errors: this.validationErrors,
warnings: this.validationWarnings,
};
}
}
getValidationErrors() {
return [...this.validationErrors];
}
getValidationWarnings() {
return [...this.validationWarnings];
}
build() {
const validation = this.validateCurrentTheme();
if (!validation.valid) {
if (this.options.strictMode) {
throw new errors_1.ConfigurationError(`Cannot build invalid theme: ${validation.errors.join(', ')}`);
}
else {
console.warn('Building theme with validation errors:', validation.errors);
}
}
const completeTheme = this.buildCompleteTheme();
this.emit('theme:built', completeTheme);
return completeTheme;
}
getProgress() {
const requiredFields = [
'id', 'name', 'colors', 'fonts', 'borders', 'components'
];
const completed = requiredFields.filter(field => this.currentTheme[field] !== undefined);
const missing = requiredFields.filter(field => this.currentTheme[field] === undefined);
return {
completed,
missing,
percentage: (completed.length / requiredFields.length) * 100,
};
}
getCurrentTheme() {
return JSON.parse(JSON.stringify(this.currentTheme));
}
getAvailableColorPalettes() {
return Array.from(this.colorPalettes.keys());
}
getColorPalette(name) {
return this.colorPalettes.get(name);
}
addColorPalette(palette) {
this.colorPalettes.set(palette.name, palette);
this.emit('palette:added', palette);
return this;
}
getAvailableTemplates() {
return Array.from(this.templates.keys());
}
getTemplate(id) {
return this.templates.get(id);
}
addTemplate(template) {
this.templates.set(template.id, template);
this.emit('template:added', template);
return this;
}
reset() {
this.initializeTheme();
this.validationErrors = [];
this.validationWarnings = [];
this.emit('theme:reset');
return this;
}
initializeTheme() {
this.currentTheme = {
id: '',
name: '',
isBuiltIn: false,
colors: this.getDefaultColors(),
fonts: this.getDefaultFonts(),
borders: this.getDefaultBorders(),
components: this.getDefaultComponentStyles(),
};
}
validateAndEmit(eventName, data) {
if (this.options.autoValidate) {
this.validateCurrentTheme();
}
this.emit(eventName, data);
}
buildCompleteTheme() {
return {
id: this.currentTheme.id || 'custom-theme',
name: this.currentTheme.name || 'Custom Theme',
...(this.currentTheme.description !== undefined && { description: this.currentTheme.description }),
...(this.currentTheme.author !== undefined && { author: this.currentTheme.author }),
version: this.currentTheme.version || '1.0.0',
isBuiltIn: false,
colors: {
...this.getDefaultColors(),
...this.currentTheme.colors,
},
fonts: {
...this.getDefaultFonts(),
...this.currentTheme.fonts,
},
borders: {
...this.getDefaultBorders(),
...this.currentTheme.borders,
},
components: {
...this.getDefaultComponentStyles(),
...this.currentTheme.components,
},
};
}
getDefaultColors() {
return {
primary: '#0066cc',
secondary: '#6c757d',
background: '#000000',
foreground: '#ffffff',
accent: '#17a2b8',
error: '#dc3545',
warning: '#ffc107',
success: '#28a745',
info: '#17a2b8',
muted: '#6c757d',
highlight: '#ffff00',
border: '#666666',
selection: '#0066cc',
};
}
getDefaultFonts() {
return {
family: 'monospace',
size: 12,
weight: 'normal',
style: 'normal',
};
}
getDefaultBorders() {
return {
type: 'line',
style: 'solid',
color: '#666666',
};
}
getDefaultComponentStyles() {
return {
header: { fg: '#ffffff', bg: '#0066cc', bold: true },
content: { fg: '#ffffff', bg: '#000000' },
status: { fg: '#17a2b8', bg: '#000000' },
border: { fg: '#666666' },
scrollbar: { fg: '#666666', bg: '#333333' },
selection: { fg: '#ffffff', bg: '#0066cc' },
};
}
paletteToColorScheme(palette) {
const colors = palette.colors;
return {
primary: colors[0] || '#0066cc',
secondary: colors[1] || '#6c757d',
background: colors[2] || '#000000',
foreground: colors[3] || '#ffffff',
accent: colors[4] || '#17a2b8',
error: colors[5] || '#dc3545',
warning: colors[6] || '#ffc107',
success: colors[7] || '#28a745',
info: colors[8] || '#17a2b8',
muted: colors[9] || '#6c757d',
highlight: colors[10] || '#ffff00',
border: colors[11] || '#666666',
selection: colors[12] || '#0066cc',
};
}
adjustColorBrightness(color, factor) {
if (color.startsWith('#')) {
const hex = color.slice(1);
const r = parseInt(hex.slice(0, 2), 16);
const g = parseInt(hex.slice(2, 4), 16);
const b = parseInt(hex.slice(4, 6), 16);
const adjust = (c) => {
const adjusted = c + (factor > 0 ? (255 - c) * factor : c * factor);
return Math.max(0, Math.min(255, Math.round(adjusted)));
};
const newR = adjust(r).toString(16).padStart(2, '0');
const newG = adjust(g).toString(16).padStart(2, '0');
const newB = adjust(b).toString(16).padStart(2, '0');
return `#${newR}${newG}${newB}`;
}
return color;
}
adjustColorSaturation(color, factor) {
return this.adjustColorBrightness(color, factor * 0.3);
}
generateComplementaryColors(baseColor) {
return {
primary: baseColor,
secondary: this.adjustColorBrightness(baseColor, -0.3),
accent: this.adjustColorBrightness(baseColor, 0.2),
selection: this.adjustColorBrightness(baseColor, 0.1),
};
}
loadBuiltInColorPalettes() {
const palettes = [
{
name: 'modern-dark',
description: 'Modern dark color palette',
colors: [
'#007acc', '#6c7b7f', '#1e1e1e', '#d4d4d4', '#4fc1ff',
'#f44747', '#ffcc02', '#89d185', '#4fc1ff', '#808080',
'#ffff00', '#3c3c3c', '#007acc'
],
},
{
name: 'vibrant-light',
description: 'Vibrant light color palette',
colors: [
'#0066cc', '#6c757d', '#ffffff', '#000000', '#e83e8c',
'#dc3545', '#fd7e14', '#28a745', '#17a2b8', '#6c757d',
'#fff3cd', '#dee2e6', '#0066cc'
],
},
{
name: 'high-contrast',
description: 'High contrast accessibility palette',
colors: [
'#ffff00', '#ffffff', '#000000', '#ffffff', '#00ffff',
'#ff0000', '#ffff00', '#00ff00', '#00ffff', '#808080',
'#ffff00', '#ffffff', '#ffff00'
],
},
];
palettes.forEach(palette => {
this.colorPalettes.set(palette.name, palette);
});
}
loadBuiltInTemplates() {
const templates = [
{
id: 'minimal-dark',
name: 'Minimal Dark',
description: 'Clean and minimal dark theme',
category: 'dark',
baseTheme: {
colors: {
primary: '#007acc',
secondary: '#6c7b7f',
background: '#1e1e1e',
foreground: '#d4d4d4',
accent: '#4fc1ff',
error: '#f44747',
warning: '#ffcc02',
success: '#89d185',
info: '#4fc1ff',
muted: '#808080',
highlight: '#ffff00',
border: '#3c3c3c',
selection: '#007acc',
},
fonts: {
family: 'monospace',
size: 12,
weight: 'normal',
style: 'normal',
},
},
},
{
id: 'clean-light',
name: 'Clean Light',
description: 'Clean and bright light theme',
category: 'light',
baseTheme: {
colors: {
primary: '#0066cc',
secondary: '#6c757d',
background: '#ffffff',
foreground: '#212529',
accent: '#6f42c1',
error: '#dc3545',
warning: '#fd7e14',
success: '#198754',
info: '#0dcaf0',
muted: '#6c757d',
highlight: '#fff3cd',
border: '#dee2e6',
selection: '#0066cc',
},
},
},
];
templates.forEach(template => {
this.templates.set(template.id, template);
});
}
}
exports.CustomThemeBuilder = CustomThemeBuilder;
//# sourceMappingURL=custom-theme-builder.js.map