UNPKG

@bernierllc/email-ui

Version:

React UI components for email management, templates, scheduling, and analytics

108 lines (106 loc) 6.65 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; /* Copyright (c) 2025 Bernier LLC This file is licensed to the client under a limited-use license. The client may use and modify this code *only within the scope of the project it was delivered for*. Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC. */ import { useState, useEffect } from 'react'; // Integration detection helpers const detectLogger = () => { try { // Try to detect logger in various contexts if (globalThis.__BERNIER_LOGGER__) { return globalThis.__BERNIER_LOGGER__; } return null; } catch { return null; } }; const detectNeverHub = () => { try { if (globalThis.__NEVERHUB_ADAPTER__) { return globalThis.__NEVERHUB_ADAPTER__; } return null; } catch { return null; } }; export const TemplateEditor = ({ template, onSave, onCancel, isLoading = false, className = '', style, }) => { const [formData, setFormData] = useState({ name: template?.name || '', subject: template?.subject || '', content: template?.content || '', category: template?.category || '', tags: template?.tags || [], }); const [previewMode, setPreviewMode] = useState(false); // Integration state const [logger] = useState(() => detectLogger()); const [neverhub] = useState(() => detectNeverHub()); // Component lifecycle logging useEffect(() => { logger?.info('TemplateEditor mounted', { templateId: template?.id, hasIntegrations: { logger: !!logger, neverhub: !!neverhub } }); return () => { logger?.debug('TemplateEditor unmounting'); }; }, [logger, neverhub, template?.id]); const extractVariables = (text) => { const matches = text.match(/\{\{(\w+)\}\}/g); return matches ? [...new Set(matches.map(m => m.slice(2, -2)))] : []; }; const handleSubmit = async (e) => { e.preventDefault(); try { logger?.info('Template save initiated', { templateId: template?.id, templateName: formData.name }); const extractedVariables = [ ...extractVariables(formData.subject), ...extractVariables(formData.content), ]; const templateData = { ...formData, variables: extractedVariables, }; await onSave(templateData); // Log success and publish NeverHub event logger?.info('Template saved successfully', { templateId: template?.id, variableCount: extractedVariables.length }); if (neverhub) { await neverhub.publishEvent({ type: 'email.template.saved', data: { templateId: template?.id, templateName: formData.name, variableCount: extractedVariables.length, isUpdate: !!template?.id } }).catch(err => { logger?.error('Failed to publish template saved event', err); }); } } catch (error) { logger?.error('Template save failed', error); throw error; // Re-throw to allow parent components to handle } }; const handleInputChange = (field, value) => { setFormData(prev => ({ ...prev, [field]: value })); }; return (_jsxs("div", { className: `template-editor ${className}`, style: style, children: [_jsxs("div", { className: "template-editor__header", children: [_jsx("h2", { className: "template-editor__title", children: template?.id ? 'Edit Template' : 'Create Template' }), _jsx("div", { className: "template-editor__actions", children: _jsx("button", { type: "button", onClick: () => setPreviewMode(!previewMode), className: "btn btn--secondary", children: previewMode ? 'Edit' : 'Preview' }) })] }), _jsxs("form", { onSubmit: handleSubmit, className: "template-editor__form", children: [_jsxs("div", { className: "form-group", children: [_jsx("label", { htmlFor: "name", className: "form-label", children: "Template Name" }), _jsx("input", { id: "name", type: "text", value: formData.name, onChange: (e) => handleInputChange('name', e.target.value), className: "form-input", placeholder: "Enter template name", required: true })] }), _jsxs("div", { className: "form-group", children: [_jsx("label", { htmlFor: "subject", className: "form-label", children: "Subject Line" }), _jsx("input", { id: "subject", type: "text", value: formData.subject, onChange: (e) => handleInputChange('subject', e.target.value), className: "form-input", placeholder: "Enter email subject", required: true })] }), _jsxs("div", { className: "form-group", children: [_jsx("label", { htmlFor: "category", className: "form-label", children: "Category" }), _jsx("input", { id: "category", type: "text", value: formData.category, onChange: (e) => handleInputChange('category', e.target.value), className: "form-input", placeholder: "Template category (optional)" })] }), _jsxs("div", { className: "form-group", children: [_jsx("label", { htmlFor: "content", className: "form-label", children: "Email Content" }), previewMode ? (_jsx("div", { className: "template-preview", children: _jsx("div", { dangerouslySetInnerHTML: { __html: formData.content } }) })) : (_jsx("textarea", { id: "content", rows: 12, value: formData.content, onChange: (e) => handleInputChange('content', e.target.value), className: "form-textarea", placeholder: "Enter email content. Use {{variable}} for dynamic content.", required: true }))] }), extractVariables(formData.content).length > 0 && (_jsxs("div", { className: "template-editor__variables", children: [_jsx("h3", { children: "Detected Variables:" }), _jsx("div", { className: "variable-tags", children: extractVariables(formData.content).map((variable) => (_jsx("span", { className: "variable-tag", children: variable }, variable))) })] })), _jsxs("div", { className: "template-editor__footer", children: [onCancel && (_jsx("button", { type: "button", onClick: onCancel, className: "btn btn--secondary", disabled: isLoading, children: "Cancel" })), _jsx("button", { type: "submit", className: "btn btn--primary", disabled: isLoading, children: isLoading ? 'Saving...' : 'Save Template' })] })] })] })); };