diff --git a/packages/css_designer/seed/styles.json b/packages/css_designer/seed/styles.json new file mode 100644 index 000000000..3a7d1ef18 --- /dev/null +++ b/packages/css_designer/seed/styles.json @@ -0,0 +1,74 @@ +[ + { + "id": "css_designer_layout", + "type": "component", + "category": "layout", + "className": "css-designer-layout", + "description": "Main layout for CSS Designer package", + "css": ".css-designer-layout {\n display: grid;\n grid-template-columns: 300px 1fr 400px;\n gap: 1rem;\n height: 100vh;\n padding: 1rem;\n background: var(--background);\n}\n\n@media (max-width: 1024px) {\n .css-designer-layout {\n grid-template-columns: 1fr;\n overflow-y: auto;\n }\n}" + }, + { + "id": "css_editor_panel", + "type": "component", + "category": "panel", + "className": "css-editor-panel", + "description": "CSS code editor panel styling", + "css": ".css-editor-panel {\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: var(--radius);\n padding: 1.5rem;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.css-editor-panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 1rem;\n padding-bottom: 1rem;\n border-bottom: 1px solid var(--border);\n}\n\n.css-editor-panel-title {\n font-weight: 600;\n font-size: 1rem;\n color: var(--foreground);\n}\n\n.css-editor-panel-actions {\n display: flex;\n gap: 0.5rem;\n}" + }, + { + "id": "css_color_picker", + "type": "component", + "category": "form-control", + "className": "css-color-picker", + "description": "Color picker component styling", + "css": ".css-color-picker {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n margin-bottom: 1rem;\n}\n\n.css-color-picker-label {\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--foreground);\n}\n\n.css-color-picker-input {\n display: flex;\n gap: 0.75rem;\n align-items: center;\n}\n\n.css-color-picker-swatch {\n width: 40px;\n height: 40px;\n border-radius: var(--radius-md);\n border: 2px solid var(--border);\n cursor: pointer;\n transition: transform 0.2s ease-in-out;\n}\n\n.css-color-picker-swatch:hover {\n transform: scale(1.05);\n}\n\n.css-color-picker-value {\n flex: 1;\n padding: 0.5rem 0.75rem;\n border: 1px solid var(--border);\n border-radius: var(--radius-md);\n font-family: var(--font-mono, monospace);\n font-size: 0.875rem;\n background: var(--background);\n}" + }, + { + "id": "css_style_preview", + "type": "component", + "category": "preview", + "className": "css-style-preview", + "description": "Live preview panel for CSS changes", + "css": ".css-style-preview {\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: var(--radius);\n padding: 1.5rem;\n overflow-y: auto;\n}\n\n.css-style-preview-header {\n margin-bottom: 1.5rem;\n padding-bottom: 1rem;\n border-bottom: 1px solid var(--border);\n}\n\n.css-style-preview-content {\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n}\n\n.preview-section {\n padding: 1.5rem;\n border: 1px dashed var(--border);\n border-radius: var(--radius-md);\n background: var(--background);\n}" + }, + { + "id": "css_property_group", + "type": "component", + "category": "form-group", + "className": "css-property-group", + "description": "Grouped CSS property editor", + "css": ".css-property-group {\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: var(--radius);\n padding: 1rem;\n margin-bottom: 1rem;\n}\n\n.css-property-group-header {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n margin-bottom: 1rem;\n cursor: pointer;\n user-select: none;\n}\n\n.css-property-group-icon {\n width: 24px;\n height: 24px;\n color: var(--primary);\n}\n\n.css-property-group-title {\n font-weight: 600;\n font-size: 0.875rem;\n color: var(--foreground);\n flex: 1;\n}\n\n.css-property-group-toggle {\n color: var(--muted-foreground);\n transition: transform 0.2s ease-in-out;\n}\n\n.css-property-group-toggle.expanded {\n transform: rotate(180deg);\n}\n\n.css-property-group-content {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}" + }, + { + "id": "css_slider_control", + "type": "component", + "category": "form-control", + "className": "css-slider-control", + "description": "Slider control for numeric CSS values", + "css": ".css-slider-control {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.css-slider-control-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.css-slider-control-label {\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--foreground);\n}\n\n.css-slider-control-value {\n font-size: 0.875rem;\n font-family: var(--font-mono, monospace);\n color: var(--primary);\n font-weight: 600;\n}\n\n.css-slider-control-input {\n width: 100%;\n height: 4px;\n background: var(--muted);\n border-radius: 2px;\n outline: none;\n cursor: pointer;\n}\n\n.css-slider-control-input::-webkit-slider-thumb {\n appearance: none;\n width: 16px;\n height: 16px;\n background: var(--primary);\n border-radius: 50%;\n cursor: pointer;\n transition: transform 0.2s ease-in-out;\n}\n\n.css-slider-control-input::-webkit-slider-thumb:hover {\n transform: scale(1.2);\n}\n\n.css-slider-control-input::-moz-range-thumb {\n width: 16px;\n height: 16px;\n background: var(--primary);\n border: none;\n border-radius: 50%;\n cursor: pointer;\n transition: transform 0.2s ease-in-out;\n}\n\n.css-slider-control-input::-moz-range-thumb:hover {\n transform: scale(1.2);\n}" + }, + { + "id": "css_export_panel", + "type": "component", + "category": "panel", + "className": "css-export-panel", + "description": "CSS export options panel", + "css": ".css-export-panel {\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: var(--radius);\n padding: 1.5rem;\n margin-top: 1rem;\n}\n\n.css-export-options {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n margin-bottom: 1.5rem;\n}\n\n.css-export-option {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 1rem;\n border: 1px solid var(--border);\n border-radius: var(--radius-md);\n cursor: pointer;\n transition: all 0.2s ease-in-out;\n}\n\n.css-export-option:hover {\n border-color: var(--primary);\n background: var(--muted);\n}\n\n.css-export-option.selected {\n border-color: var(--primary);\n background: var(--accent);\n}\n\n.css-export-button {\n width: 100%;\n padding: 0.75rem;\n background: var(--primary);\n color: var(--primary-foreground);\n border: none;\n border-radius: var(--radius-md);\n font-weight: 600;\n cursor: pointer;\n transition: opacity 0.2s ease-in-out;\n}\n\n.css-export-button:hover {\n opacity: 0.9;\n}" + }, + { + "id": "css_code_output", + "type": "component", + "category": "code", + "className": "css-code-output", + "description": "Generated CSS code output display", + "css": ".css-code-output {\n background: var(--muted);\n border: 1px solid var(--border);\n border-radius: var(--radius);\n padding: 1rem;\n font-family: var(--font-mono, monospace);\n font-size: 0.875rem;\n line-height: 1.6;\n overflow-x: auto;\n max-height: 400px;\n overflow-y: auto;\n}\n\n.css-code-output pre {\n margin: 0;\n color: var(--foreground);\n}\n\n.css-code-output code {\n font-family: inherit;\n}" + }, + { + "id": "css_database_indicator", + "type": "component", + "category": "status", + "className": "css-db-indicator", + "description": "Database sync status indicator", + "css": ".css-db-indicator {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 0.75rem;\n background: var(--muted);\n border-radius: var(--radius-md);\n font-size: 0.75rem;\n color: var(--muted-foreground);\n}\n\n.css-db-indicator-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--muted-foreground);\n}\n\n.css-db-indicator.synced .css-db-indicator-dot {\n background: var(--success, #22c55e);\n animation: pulse 2s infinite;\n}\n\n.css-db-indicator.error .css-db-indicator-dot {\n background: var(--destructive);\n}\n\n@keyframes pulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n}" + } +] diff --git a/packages/shared/seed/CSS_DATABASE_SCHEMA.md b/packages/shared/seed/CSS_DATABASE_SCHEMA.md new file mode 100644 index 000000000..bc805196c --- /dev/null +++ b/packages/shared/seed/CSS_DATABASE_SCHEMA.md @@ -0,0 +1,227 @@ +# CSS Database Schema + +This document describes how CSS/SCSS styling is structured for database storage in the MetaBuilder system. + +## Overview + +The MetaBuilder system allows CSS to be stored in the database and edited through the CSS Designer package. This enables dynamic theming and real-time style updates without redeployment. + +## Styles JSON Structure + +Each package can include a `seed/styles.json` file containing CSS rules that will be loaded into the database. + +### Style Entry Format + +```json +{ + "id": "unique_style_id", + "type": "global|component|utility|animation", + "category": "descriptive-category", + "className": "css-class-name", + "description": "Human-readable description", + "priority": 1, + "css": "actual CSS code here" +} +``` + +### Field Descriptions + +- **id**: Unique identifier for the style entry +- **type**: Style type classification + - `global`: Global styles (theme variables, resets, base styles) + - `component`: Component-specific styles + - `utility`: Reusable utility classes + - `animation`: Animation keyframes and classes +- **category**: Categorization for organization (e.g., "theme-variables", "layout", "typography") +- **className**: Optional CSS class name for component/utility styles +- **description**: Human-readable description of the style's purpose +- **priority**: Optional numeric priority for style loading order (lower = earlier) +- **css**: The actual CSS code as a string + +## Database Schema + +### Table: `styles` + +```sql +CREATE TABLE styles ( + id VARCHAR(255) PRIMARY KEY, + package_id VARCHAR(255) NOT NULL, + type ENUM('global', 'component', 'utility', 'animation') NOT NULL, + category VARCHAR(100), + class_name VARCHAR(255), + description TEXT, + priority INT DEFAULT 100, + css TEXT NOT NULL, + compiled_css TEXT, + enabled BOOLEAN DEFAULT true, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + FOREIGN KEY (package_id) REFERENCES packages(id) ON DELETE CASCADE, + INDEX idx_package_type (package_id, type), + INDEX idx_enabled (enabled), + INDEX idx_priority (priority) +); +``` + +### Table: `style_variables` + +Stores CSS custom properties that can be edited through the CSS Designer. + +```sql +CREATE TABLE style_variables ( + id VARCHAR(255) PRIMARY KEY, + name VARCHAR(255) NOT NULL, + value VARCHAR(500) NOT NULL, + type ENUM('color', 'size', 'font', 'number', 'string') NOT NULL, + category VARCHAR(100), + description TEXT, + default_value VARCHAR(500), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + UNIQUE KEY uk_name (name), + INDEX idx_category (category) +); +``` + +## Loading Styles + +### Priority-Based Loading + +Styles are loaded in priority order: +1. Global theme variables (priority 1-10) +2. Global base styles (priority 11-50) +3. Component styles (priority 51-100) +4. Utility classes (priority 101-150) +5. Animations (priority 151-200) + +### Runtime Loading + +```javascript +// Example: Load styles from database +async function loadStyles(packageId) { + const styles = await db.query(` + SELECT css FROM styles + WHERE package_id = ? AND enabled = true + ORDER BY priority ASC, id ASC + `, [packageId]); + + const styleSheet = styles.map(s => s.css).join('\n\n'); + return styleSheet; +} +``` + +### Live CSS Injection + +```javascript +// Inject styles into the page +function injectStyles(styleId, css) { + let styleEl = document.getElementById(styleId); + if (!styleEl) { + styleEl = document.createElement('style'); + styleEl.id = styleId; + document.head.appendChild(styleEl); + } + styleEl.textContent = css; +} +``` + +## CSS Designer Integration + +The CSS Designer package allows editing CSS through a GUI: + +1. **Color Palette Editor**: Edit CSS custom properties for colors +2. **Typography Editor**: Modify font families and sizes +3. **Spacing Editor**: Adjust spacing and sizing variables +4. **Live Preview**: Real-time preview of changes +5. **Export Options**: + - Save to database + - Export as CSS file + - Export as SCSS file + - Export as CSS-in-JS + +### Workflow + +``` +User edits in CSS Designer + → Changes saved to style_variables table + → CSS regenerated from template + variables + → Updated in styles table + → Live-injected into running application + → Optional: Export to static files +``` + +## Example: Theme Customization + +### 1. Edit Color Variable + +```javascript +// Update a color variable +await db.query(` + UPDATE style_variables + SET value = ? + WHERE name = '--primary' +`, ['oklch(0.55 0.20 270)']); +``` + +### 2. Regenerate CSS + +```javascript +// Template with variables +const cssTemplate = ` +:root { + --primary: {{primary}}; + --background: {{background}}; +} +`; + +// Substitute variables +const variables = await db.query('SELECT name, value FROM style_variables'); +let css = cssTemplate; +variables.forEach(v => { + css = css.replace(`{{${v.name.replace('--', '')}}}`, v.value); +}); +``` + +### 3. Update and Inject + +```javascript +// Update database +await db.query(` + UPDATE styles + SET css = ?, compiled_css = ? + WHERE id = 'global_theme' +`, [css, css]); + +// Inject into page +injectStyles('global-theme', css); +``` + +## Migration from Static CSS + +To migrate existing CSS files to the database: + +1. Parse CSS file +2. Split into logical chunks (global, component, utility) +3. Generate style entries with appropriate metadata +4. Insert into database via seed files +5. Verify styles load correctly +6. Optional: Remove static CSS files + +## Best Practices + +1. **Modular Styles**: Keep styles focused and modular +2. **Use Variables**: Use CSS custom properties for values that might change +3. **Descriptive IDs**: Use clear, descriptive IDs for style entries +4. **Categories**: Properly categorize styles for easy management +5. **Priority Management**: Set appropriate priorities for load order +6. **Performance**: Consider bundling related styles +7. **Versioning**: Track style changes for rollback capability + +## Future Enhancements + +- **Style Versioning**: Track changes and allow rollback +- **Theme Presets**: Save complete theme configurations +- **A/B Testing**: Test different styles with different user groups +- **CSS Preprocessing**: Support SCSS/LESS compilation +- **CSS Minification**: Automatic minification for production +- **Hot Reload**: Real-time style updates in development