/** * ds-esre-editor.js * Editor for ESRE (Explicit Style Requirements and Expectations) * QA Team Tool #2 */ import { createEditorView, setupEditorHandlers } from '../../utils/tool-templates.js'; import { ComponentHelpers } from '../../utils/component-helpers.js'; import contextStore from '../../stores/context-store.js'; class DSESREEditor extends HTMLElement { constructor() { super(); this.esreContent = ''; this.isSaving = false; } async connectedCallback() { this.render(); await this.loadESRE(); } async loadESRE() { try { const context = contextStore.getMCPContext(); if (!context.project_id) { throw new Error('No project selected'); } // Load ESRE from project configuration const response = await fetch(`/api/projects/${context.project_id}/esre`); if (response.ok) { const result = await response.json(); this.esreContent = result.content || ''; this.renderEditor(); } else { // No ESRE yet, start with template this.esreContent = this.getESRETemplate(); this.renderEditor(); } } catch (error) { console.error('[DSESREEditor] Failed to load ESRE:', error); this.esreContent = this.getESRETemplate(); this.renderEditor(); } } getESRETemplate() { return `# Explicit Style Requirements and Expectations (ESRE) ## Project: ${contextStore.get('projectId') || 'Design System'} ### Color Requirements - Primary colors must match Figma specifications exactly - Accessibility: All text must meet WCAG 2.1 AA contrast ratios - Color tokens must be used instead of hardcoded hex values ### Typography Requirements - Font families: [Specify approved fonts] - Font sizes must use design system scale - Line heights must maintain readability - Letter spacing should follow design specifications ### Spacing Requirements - All spacing must use design system spacing scale - Margins and padding should be consistent across components - Grid system: [Specify grid specifications] ### Component Requirements - All components must be built from design system primitives - Component variants must match Figma component variants - Props should follow naming conventions ### Responsive Requirements - Breakpoints: [Specify breakpoints] - Mobile-first approach required - Touch targets must be at least 44x44px ### Accessibility Requirements - All interactive elements must be keyboard accessible - ARIA labels required for icon-only buttons - Focus indicators must be visible - Screen reader testing required ### Performance Requirements - Initial load time: [Specify target] - Time to Interactive: [Specify target] - Bundle size limits: [Specify limits] ### Browser Support - Chrome: Latest 2 versions - Firefox: Latest 2 versions - Safari: Latest 2 versions - Edge: Latest 2 versions --- ## Validation Checklist ### Pre-Deployment - [ ] All colors match Figma specifications - [ ] Typography follows design system scale - [ ] Spacing uses design tokens - [ ] Components match design system library - [ ] Responsive behavior validated - [ ] Accessibility audit passed - [ ] Performance metrics met - [ ] Cross-browser testing completed ### QA Testing - [ ] Visual comparison with Figma - [ ] Keyboard navigation tested - [ ] Screen reader compatibility verified - [ ] Mobile devices tested - [ ] Edge cases validated --- Last updated: ${new Date().toISOString().split('T')[0]} `; } renderEditor() { const container = this.querySelector('#editor-container'); if (!container) return; const config = { title: 'ESRE Editor', content: this.esreContent, language: 'markdown', onSave: (content) => this.saveESRE(content), onExport: (content) => this.exportESRE(content) }; container.innerHTML = createEditorView(config); setupEditorHandlers(container, config); } async saveESRE(content) { this.isSaving = true; const saveBtn = document.querySelector('#editor-save-btn'); if (saveBtn) { saveBtn.disabled = true; saveBtn.textContent = '⏳ Saving...'; } try { const context = contextStore.getMCPContext(); if (!context.project_id) { throw new Error('No project selected'); } // Save ESRE via API const response = await fetch('/api/esre/save', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ projectId: context.project_id, content }) }); if (!response.ok) { throw new Error(`Save failed: ${response.statusText}`); } this.esreContent = content; ComponentHelpers.showToast?.('ESRE saved successfully', 'success'); } catch (error) { console.error('[DSESREEditor] Save failed:', error); ComponentHelpers.showToast?.(`Save failed: ${error.message}`, 'error'); } finally { this.isSaving = false; if (saveBtn) { saveBtn.disabled = false; saveBtn.textContent = '💾 Save'; } } } exportESRE(content) { const blob = new Blob([content], { type: 'text/markdown' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); const projectId = contextStore.get('projectId') || 'project'; a.href = url; a.download = `${projectId}-esre.md`; a.click(); URL.revokeObjectURL(url); ComponentHelpers.showToast?.('ESRE exported', 'success'); } render() { this.innerHTML = `
📋
ESRE: Explicit Style Requirements and Expectations
Define clear specifications for design implementation and QA validation
${createEditorView({ title: 'ESRE Editor', content: this.esreContent, language: 'markdown', onSave: (content) => this.saveESRE(content), onExport: (content) => this.exportESRE(content) })}
💡 Tip: Use Markdown formatting for clear documentation. Save changes before closing.
`; } } customElements.define('ds-esre-editor', DSESREEditor); export default DSESREEditor;