# Form Builder Technical Guide This document provides comprehensive technical implementation details for developers working with the Form Builder system, including the new smart collapsible panel, enhanced grid system, and advanced UX features. > For user documentation and usage guidelines, see the [User Guide](USER_GUIDE.md) ## Architecture Overview ### Technology Stack - **Frontend Framework**: Nuxt 3 / Vue 3 - **State Management**: Pinia - **Form Library**: FormKit - **UI Framework**: Tailwind CSS + Custom Components - **Icons**: Heroicons - **Drag & Drop**: vuedraggable - **Grid System**: CSS Grid (12-column) ### Key Dependencies ```json { "@formkit/nuxt": "^1.0.0", "@pinia/nuxt": "^0.4.11", "vuedraggable": "^4.1.0", "@vueuse/core": "^10.1.2", "tailwindcss": "^3.3.2", "@heroicons/vue": "^2.0.18" } ``` ## Project Structure ``` pages/ ├── form-builder/ │ ├── index.vue # Main builder interface with collapsible panel │ └── manage.vue # Form management components/ ├── FormBuilderComponents.vue # Enhanced component library ├── FormBuilderCanvas.vue # Grid-based canvas with resize handles ├── FormBuilderFieldSettingsModal.vue # Full settings modal with visual grid ├── ComponentPreview.vue # Improved component rendering └── RsCollapseItem.vue # Collapsible components stores/ ├── formBuilder.js # Enhanced state management with grid logic └── toast.js # Toast notifications composables/ └── useToast.js # Toast composition types/ └── form-builder.d.ts # TypeScript definitions server/ └── api/ └── forms/ ├── index.js # Form API endpoints └── [id].js # Form by ID endpoints docs/ └── grid-system.md # Grid system documentation ``` ## Enhanced UI Architecture ### Smart Collapsible Panel System The right panel system provides two interaction modes: #### Panel States ```vue ``` #### Quick Settings Implementation ```vue ``` ### Enhanced Grid System #### CSS Grid Implementation ```css .grid-container { display: grid; grid-template-columns: repeat(12, 1fr); grid-auto-flow: row dense; /* Enables automatic gap filling */ column-gap: 16px; row-gap: 16px; width: 100%; } .form-component { grid-column: span 12; /* Default to full width */ width: 100% !important; /* Force width within grid cell */ transition: all 0.2s ease; } ``` #### Grid Column Mapping ```javascript // Precise percentage to grid column mapping const widthToGridColumns = { 25: 3, // 3/12 = 25% 33: 4, // 4/12 = 33.33% 50: 6, // 6/12 = 50% 66: 8, // 8/12 = 66.67% 75: 9, // 9/12 = 75% 100: 12 // 12/12 = 100% } const setComponentWidth = (percentage, gridColumns) => { configModel.value.width = `${percentage}%` configModel.value.gridColumn = `span ${gridColumns}` } ``` #### Smart Grid Placement Algorithm ```javascript // Optimal grid placement for new components findOptimalGridPlacement() { if (this.formComponents.length === 0) { return { gridColumn: 'span 12', rowIndex: 0, width: '100%' } } // Group components by rows and find available space const rows = [] let currentRowSpace = 12 this.formComponents.forEach(component => { const spanMatch = component.props.gridColumn?.match(/span\s+(\d+)/) || [] const columnSpan = parseInt(spanMatch[1]) || 12 if (columnSpan <= currentRowSpace) { // Add to current row currentRowSpace -= columnSpan } else { // Start new row currentRowSpace = 12 - columnSpan } }) // Return optimal placement return { gridColumn: `span ${Math.min(currentRowSpace, 12)}`, width: `${Math.round((currentRowSpace / 12) * 100)}%` } } ``` ## Component Architecture ### Enhanced FormBuilderFieldSettingsModal The modal now includes visual grid selection: ```vue {{ option.name }} Recommended {{ option.description }} {{ option.useCase }} ``` ### Enhanced Canvas with Resize Handles ```vue ``` ## State Management Enhancements ### Enhanced Pinia Store ```typescript interface FormState { formComponents: FormComponent[] selectedComponentId: string | null formName: string formDescription: string formId: string | null formUUID: string | null isDraggingOver: boolean savedForms: SavedForm[] showFieldSettingsPanel: boolean // New panel state } export const useFormBuilderStore = defineStore('formBuilder', { state: (): FormState => ({ formComponents: [], selectedComponentId: null, formName: 'New Form', formDescription: '', formId: null, formUUID: null, isDraggingOver: false, savedForms: [], showFieldSettingsPanel: true }), getters: { selectedComponent: (state) => { if (!state.selectedComponentId) return null return state.formComponents.find(c => c.id === state.selectedComponentId) }, formConfig: (state) => ({ id: state.formId, uuid: state.formUUID, name: state.formName, description: state.formDescription, components: state.formComponents }) }, actions: { // Enhanced component addition with smart grid placement addComponent(component: FormComponent) { const { gridColumn, rowIndex, width } = this.findOptimalGridPlacement() const newComponent = { ...component, id: component.id || uuidv4(), props: { ...component.defaultProps, width: width, gridColumn: gridColumn, name: component.defaultProps?.name || `${component.type}_${this.formComponents.length + 1}`, label: component.defaultProps?.label || `${component.name} ${this.formComponents.length + 1}` } } this.formComponents.push(newComponent) this.selectComponent(newComponent.id) }, // Grid layout optimization optimizeGridLayout() { const rows = this.groupComponentsByRows() rows.forEach(row => { if (row.remainingSpace > 0) { this.distributeRemainingSpace(row) } }) }, // Helper methods for grid management groupComponentsByRows() { const rows = [] let currentRowSpace = 12 this.formComponents.forEach(component => { const spanMatch = component.props.gridColumn?.match(/span\s+(\d+)/) || [] const columnSpan = parseInt(spanMatch[1]) || 12 if (columnSpan <= currentRowSpace) { currentRowSpace -= columnSpan if (!rows[rows.length - 1]) { rows.push({ components: [], remainingSpace: 0 }) } rows[rows.length - 1].components.push(component) rows[rows.length - 1].remainingSpace = currentRowSpace } else { rows.push({ components: [component], remainingSpace: 12 - columnSpan }) currentRowSpace = 12 - columnSpan } }) return rows } } }) ``` ## Component Type System ### Enhanced Component Definitions ```javascript const availableComponents = [ { type: 'text', name: 'Text Field', category: 'Basic Inputs', icon: 'heroicons:document-text', recommendedWidth: 'small', // New recommendation system defaultProps: { type: 'text', label: 'Text Field', name: '', placeholder: '', help: '', validation: '', width: '33%', // Smart default gridColumn: 'span 4' } }, { type: 'textarea', name: 'Text Area', category: 'Basic Inputs', icon: 'heroicons:document-text', recommendedWidth: 'full', defaultProps: { type: 'textarea', label: 'Text Area', name: '', placeholder: '', help: '', rows: 4, validation: '', width: '100%', gridColumn: 'span 12' } }, // ... additional components with smart defaults ] ``` ### Component Icon and Name Helpers ```javascript const getComponentIcon = (type) => { const iconMap = { text: 'heroicons:document-text', textarea: 'heroicons:document-text', number: 'heroicons:hashtag', email: 'heroicons:envelope', password: 'heroicons:key', url: 'heroicons:link', tel: 'heroicons:device-phone-mobile', mask: 'heroicons:pencil-square', hidden: 'heroicons:eye-slash', select: 'heroicons:chevron-down', checkbox: 'heroicons:check-badge', radio: 'heroicons:radio', switch: 'material-symbols:toggle-on', date: 'heroicons:calendar-days', time: 'heroicons:clock', 'datetime-local': 'heroicons:calendar', range: 'heroicons:adjustments-horizontal', color: 'heroicons:swatch', file: 'heroicons:document-arrow-up', otp: 'heroicons:key', dropzone: 'heroicons:cloud-arrow-up', button: 'heroicons:cursor-arrow-rays', heading: 'heroicons:h1', paragraph: 'heroicons:document-text', divider: 'heroicons:minus', 'info-display': 'heroicons:information-circle' } return iconMap[type] || 'heroicons:square-3-stack-3d' } // Short names for collapsed panel const getComponentTypeShort = (type) => { const shortNames = { text: 'TXT', textarea: 'TXT', number: 'NUM', email: 'EML', password: 'PWD', url: 'URL', tel: 'TEL', mask: 'MSK', hidden: 'HID', select: 'SEL', checkbox: 'CHK', radio: 'RAD', switch: 'SWT', date: 'DTE', time: 'TME', 'datetime-local': 'DTM', range: 'RNG', color: 'CLR', file: 'FIL', otp: 'OTP', dropzone: 'DRP', button: 'BTN', heading: 'H' + (component?.props?.level || '2'), paragraph: 'TXT', divider: 'DIV', 'info-display': 'INF' } return shortNames[type] || 'FLD' } ``` ## CSS Architecture ### Panel System Styles ```css /* Field Settings Panel */ .field-settings-panel { @apply relative bg-white border-l border-gray-200 flex flex-col overflow-hidden transition-all duration-300 ease-in-out; } .panel-expanded { @apply w-80; /* 320px expanded */ } .panel-collapsed { @apply w-12; /* 48px collapsed */ } /* Panel content areas */ .panel-content { @apply flex-1 flex flex-col overflow-hidden; } .panel-header { @apply px-4 py-3 border-b border-gray-200 bg-gray-50; } .panel-body { @apply flex-1 overflow-y-auto; } /* Collapsed state */ .collapsed-info { @apply h-full flex flex-col px-2 py-3; } .collapsed-header { @apply mb-4 flex justify-center; } .collapsed-content { @apply text-center w-full flex-1 flex flex-col justify-center items-center; } ``` ### Grid System Styles ```css /* Grid container */ .grid-container { display: grid; grid-template-columns: repeat(12, 1fr); grid-auto-flow: row dense; column-gap: 16px; row-gap: 16px; width: 100%; padding: 0; box-sizing: border-box; } /* Grid preview in modal */ .grid-container-mini { @apply grid grid-cols-12 gap-1 w-32; } .grid-cell { @apply h-2 rounded-sm transition-colors duration-200; } .grid-cell.active { @apply bg-blue-500; } .grid-cell.inactive { @apply bg-gray-200; } /* Width selection */ .width-option { @apply border border-gray-200 rounded-lg p-4 transition-all duration-200 hover:border-blue-300 hover:bg-blue-50 cursor-pointer flex items-center space-x-4; } .width-option.selected { @apply border-blue-500 bg-blue-50 ring-2 ring-blue-200; } .width-option.recommended { @apply ring-2 ring-green-200 border-green-300; } .width-option.selected.recommended { @apply border-green-500 bg-green-50 ring-2 ring-green-200; } ``` ### Quick Settings Styles ```css /* Compact width buttons */ .width-selector-compact { @apply flex space-x-1; } .width-btn { @apply flex-1 px-2 py-1.5 text-xs font-medium text-center rounded-md border border-gray-200 bg-white hover:border-blue-300 hover:bg-blue-50 transition-colors duration-200; } .width-btn.active { @apply border-blue-500 bg-blue-50 text-blue-700 ring-1 ring-blue-200; } /* Toggle switches */ .setting-toggle { @apply flex items-center cursor-pointer; } .toggle-slider { @apply relative inline-block w-8 h-4 mr-2 bg-gray-200 rounded-full transition-colors duration-200 ease-in-out; } .setting-toggle input:checked + .toggle-slider { @apply bg-blue-600; } .toggle-slider::before { @apply absolute top-0.5 left-0.5 w-3 h-3 bg-white rounded-full transition-transform duration-200 ease-in-out; content: ''; } .setting-toggle input:checked + .toggle-slider::before { @apply transform translate-x-4; } ``` ## API Integration ### Form Data Structure ```typescript interface FormComponent { id: string type: string name: string category: string icon: string defaultProps: Record props: { label?: string name?: string placeholder?: string help?: string validation?: string width: string // e.g., "50%" gridColumn: string // e.g., "span 6" [key: string]: any } } interface FormConfig { id: string | null uuid: string | null name: string description: string components: FormComponent[] settings: { submitUrl?: string successMessage?: string errorMessage?: string redirectUrl?: string } } ``` ### Save/Load Operations ```javascript // Enhanced save with grid validation const saveForm = async (formConfig) => { // Validate grid layout const validatedComponents = formConfig.components.map(component => ({ ...component, props: { ...component.props, // Ensure grid properties are valid width: component.props.width || '100%', gridColumn: component.props.gridColumn || 'span 12' } })) const validatedForm = { ...formConfig, components: validatedComponents } try { const response = await $fetch('/api/forms', { method: 'POST', body: validatedForm }) return response } catch (error) { throw new Error(`Save failed: ${error.message}`) } } // Load with grid property migration const loadForm = async (formId) => { try { const form = await $fetch(`/api/forms/${formId}`) // Migrate old forms without grid properties const migratedComponents = form.components.map(component => ({ ...component, props: { ...component.props, width: component.props.width || '100%', gridColumn: component.props.gridColumn || 'span 12' } })) return { ...form, components: migratedComponents } } catch (error) { throw new Error(`Load failed: ${error.message}`) } } ``` ## Performance Optimizations ### Component Rendering ```vue ``` ### Grid Layout Optimization ```javascript // Efficient grid layout calculation const optimizeGridLayout = () => { // Use requestAnimationFrame for smooth updates requestAnimationFrame(() => { const rows = groupComponentsByRows() rows.forEach(row => { if (row.remainingSpace > 3) { // Only optimize significant gaps distributeSpace(row) } }) }) } // Virtual scrolling for large forms const useVirtualScrolling = (components, containerHeight) => { const itemHeight = 120 // Average component height const visibleCount = Math.ceil(containerHeight / itemHeight) + 2 return computed(() => { const startIndex = Math.max(0, scrollTop.value / itemHeight - 1) const endIndex = Math.min(components.length, startIndex + visibleCount) return components.slice(startIndex, endIndex) }) } ``` ## JavaScript Execution Engine (FormScriptEngine) ### Architecture Overview The FormScriptEngine component provides real-time JavaScript execution for dynamic form behavior, calculations, and conditional logic. It monitors form data changes and executes user-defined event handlers to create interactive forms. #### Core Components ``` components/ ├── FormScriptEngine.vue # Main execution engine └── FormBuilderCanvas.vue # Integration point for script execution pages/ └── form-builder/ └── index.vue # Form data handling and script triggering ``` ### FormScriptEngine.vue Implementation ```vue Script Engine Status: {{ isInitialized ? 'Active' : 'Initializing' }} ``` ### Integration with Form Builder #### Form Builder Canvas Integration ```vue ``` #### Main Form Builder Integration ```vue ``` ### Event Handler API Reference #### onLoad Handler Executes once when the form loads. Use for initialization. ```javascript onLoad: function() { // Initialize default values setField('status', 'active'); setField('created_date', new Date().toISOString().split('T')[0]); // Perform initial calculations calculateInitialValues(); } ``` #### onFieldChange Handler Executes when any field value changes. ```javascript onFieldChange: function(fieldName, value) { console.log('Field changed:', fieldName, 'New value:', value); // Handle specific field changes switch(fieldName) { case 'quantity': case 'price': updateTotal(); break; case 'country': updateTaxRate(value); break; } } ``` ### Error Handling and Debugging #### Script Execution Errors ```javascript // Comprehensive error handling in script execution const executeHandler = async (handler, ...args) => { try { if (typeof handler === 'function') { const result = await handler(...args) return { success: true, result } } return { success: false, error: 'Handler is not a function' } } catch (error) { console.error('Script execution error:', error) // Emit error event for debugging emit('scriptError', { error: error.message, stack: error.stack, handler: handler.name || 'anonymous', args }) return { success: false, error: error.message } } } ``` #### Debug Mode Features ```javascript // Enhanced logging in development mode const debugLog = (message, data) => { if (isDev) { console.log(`[FormScriptEngine Debug] ${message}`, data) } } // Field change tracing const traceFieldChange = (fieldName, oldValue, newValue) => { if (isDev) { console.group(`Field Change: ${fieldName}`) console.log('Old Value:', oldValue) console.log('New Value:', newValue) console.log('Timestamp:', new Date().toISOString()) console.groupEnd() } } ``` ### Performance Optimization #### Change Detection Optimization ```javascript // Efficient change detection using shallow comparison const hasDataChanged = (newData, oldData) => { const newKeys = Object.keys(newData) const oldKeys = Object.keys(oldData) // Quick length check if (newKeys.length !== oldKeys.length) return true // Value comparison return newKeys.some(key => newData[key] !== oldData[key]) } // Debounced change detection for rapid updates const debouncedChangeDetection = useDebounceFn( triggerFieldChangeDetection, 100 // 100ms debounce ) ``` #### Memory Management ```javascript // Cleanup when component unmounts onUnmounted(() => { console.log('FormScriptEngine: Cleaning up...') // Clear references handlers.value = null scriptContext.value = null previousFormData.value = null // Remove event listeners if any cleanupEventListeners() }) ``` ### Security Considerations #### Script Sandboxing ```javascript // Restricted execution context - only safe functions exposed const createSecureContext = () => { return { // Form manipulation functions setField, getField, // Safe global functions console: { log: console.log, warn: console.warn, error: console.error }, // Math and date functions Math, Date, parseFloat, parseInt, isNaN, // String functions String, // No access to: // - window object // - document object // - eval function // - Function constructor // - import/require } } ``` #### Input Validation ```javascript // Validate script before execution const validateScript = (script) => { const dangerousPatterns = [ /eval\s*\(/, /Function\s*\(/, /window\./, /document\./, /import\s+/, /require\s*\(/, /fetch\s*\(/, /XMLHttpRequest/ ] return !dangerousPatterns.some(pattern => pattern.test(script)) } ``` ## Testing Strategy ### JavaScript Engine Tests ```javascript // FormScriptEngine unit tests describe('FormScriptEngine', () => { let wrapper let mockFormData beforeEach(() => { mockFormData = ref({ quantity: 0, price: 0, total: 0 }) wrapper = mount(FormScriptEngine, { props: { formData: mockFormData.value, script: ` onLoad: function() { setField('quantity', 1); setField('price', 10); } onFieldChange: function(fieldName, value) { if (fieldName === 'quantity' || fieldName === 'price') { const total = getField('quantity') * getField('price'); setField('total', total); } } ` } }) }) test('should initialize script and execute onLoad', async () => { await nextTick() expect(mockFormData.value.quantity).toBe(1) expect(mockFormData.value.price).toBe(10) }) test('should execute onFieldChange when data changes', async () => { await nextTick() // Simulate field change mockFormData.value.quantity = 5 await nextTick() expect(mockFormData.value.total).toBe(50) }) test('should handle script errors gracefully', async () => { const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation() const wrapper = mount(FormScriptEngine, { props: { formData: mockFormData.value, script: ` onLoad: function() { // Intentional error undefinedFunction(); } ` } }) await nextTick() expect(consoleErrorSpy).toHaveBeenCalled() consoleErrorSpy.mockRestore() }) test('should validate and sanitize script input', () => { const dangerousScript = ` onLoad: function() { eval('alert("XSS")'); window.location = 'http://malicious.com'; } ` const isValid = wrapper.vm.validateScript(dangerousScript) expect(isValid).toBe(false) }) }) // Real-time calculation tests describe('Real-time Calculations', () => { test('should update total when quantity changes', async () => { const formData = ref({ quantity: 2, price: 15.99, total: 0 }) const wrapper = mount(TestFormWithScript, { props: { initialData: formData.value } }) // Change quantity await wrapper.find('input[name="quantity"]').setValue('3') await nextTick() expect(formData.value.total).toBe(47.97) }) test('should handle edge cases in calculations', async () => { const formData = ref({ quantity: '', price: 'invalid', total: 0 }) const wrapper = mount(TestFormWithScript, { props: { initialData: formData.value } }) // Should handle invalid inputs gracefully await nextTick() expect(formData.value.total).toBe(0) }) }) // Performance tests describe('FormScriptEngine Performance', () => { test('should not trigger excessive re-renders', async () => { const executeHandlerSpy = jest.spyOn(FormScriptEngine.methods, 'executeOnFieldChange') const wrapper = mount(FormScriptEngine, { props: { formData: { field1: '', field2: '', field3: '' }, script: ` onFieldChange: function(fieldName, value) { console.log('Changed:', fieldName); } ` } }) // Make multiple rapid changes for (let i = 0; i < 10; i++) { wrapper.setProps({ formData: { field1: `value${i}`, field2: '', field3: '' } }) await nextTick() } // Should be debounced/optimized expect(executeHandlerSpy.mock.calls.length).toBeLessThan(10) }) }) ``` ### Integration Tests ```javascript // Full form workflow tests with JavaScript describe('Form Builder with JavaScript Integration', () => { test('should execute calculations in preview mode', async () => { const wrapper = mount(FormBuilder) // Add form components await wrapper.find('[data-component="number"]').trigger('click') await wrapper.find('[data-component="number"]').trigger('click') await wrapper.find('[data-component="number"]').trigger('click') // Configure fields const components = wrapper.vm.formStore.formComponents components[0].props.name = 'quantity' components[1].props.name = 'price' components[2].props.name = 'total' // Add JavaScript wrapper.vm.formStore.currentForm.script = ` onFieldChange: function(fieldName, value) { if (fieldName === 'quantity' || fieldName === 'price') { const quantity = parseFloat(getField('quantity')) || 0; const price = parseFloat(getField('price')) || 0; setField('total', quantity * price); } } ` // Switch to preview mode await wrapper.find('[data-testid="preview-toggle"]').trigger('click') // Input values await wrapper.find('input[name="quantity"]').setValue('5') await wrapper.find('input[name="price"]').setValue('19.99') await nextTick() // Check calculated total const totalField = wrapper.find('input[name="total"]') expect(totalField.element.value).toBe('99.95') }) test('should handle form builder to preview data flow', async () => { const wrapper = mount(FormBuilder) // Build form with JavaScript await addFormComponents(wrapper) await addJavaScriptLogic(wrapper) // Test preview functionality await wrapper.find('[data-testid="preview-button"]').trigger('click') // Verify script execution expect(wrapper.find('.script-engine').exists()).toBe(true) expect(wrapper.vm.isPreviewMode).toBe(true) // Test field interactions await simulateUserInput(wrapper) await verifyCalculations(wrapper) }) }) ``` ### Unit Tests ```javascript // Grid system tests describe('Grid System', () => { test('should calculate optimal placement', () => { const store = useFormBuilderStore() store.formComponents = [ { id: '1', props: { gridColumn: 'span 6' } }, { id: '2', props: { gridColumn: 'span 4' } } ] const placement = store.findOptimalGridPlacement() expect(placement.gridColumn).toBe('span 2') expect(placement.width).toBe('17%') // Approximately 2/12 }) test('should optimize layout correctly', () => { const store = useFormBuilderStore() store.formComponents = [ { id: '1', props: { gridColumn: 'span 6' } }, { id: '2', props: { gridColumn: 'span 3' } } ] store.optimizeGridLayout() expect(store.formComponents[1].props.gridColumn).toBe('span 6') }) }) // Panel system tests describe('Collapsible Panel', () => { test('should auto-open when component selected', async () => { const wrapper = mount(FormBuilder) const store = useFormBuilderStore() store.selectComponent('test-id') await nextTick() expect(wrapper.find('.panel-expanded').exists()).toBe(true) }) }) ``` ### Integration Tests ```javascript // Full workflow tests describe('Form Builder Workflow', () => { test('should complete full component lifecycle', async () => { const wrapper = mount(FormBuilder) // Add component await wrapper.find('[data-component="text"]').trigger('click') // Should auto-select and open panel expect(wrapper.find('.panel-expanded').exists()).toBe(true) // Update quick settings await wrapper.find('.width-btn[data-width="50"]').trigger('click') // Verify component updated const component = wrapper.vm.formStore.selectedComponent expect(component.props.width).toBe('50%') expect(component.props.gridColumn).toBe('span 6') }) }) ``` ## Browser Compatibility ### Supported Features - **CSS Grid**: Supported in all modern browsers (IE11+ with autoprefixer) - **Vue 3**: Modern browser requirements - **Drag & Drop**: HTML5 drag/drop with fallbacks ### Polyfills Required ```javascript // For older browsers import 'core-js/stable' import 'regenerator-runtime/runtime' // CSS Grid polyfill for IE11 import 'css-grid-polyfill' ``` ## Security Considerations ### Input Validation ```javascript // Sanitize component props const sanitizeProps = (props) => { const sanitized = {} Object.keys(props).forEach(key => { if (allowedProps.includes(key)) { sanitized[key] = sanitizeHtml(props[key]) } }) return sanitized } // Validate grid values const validateGridColumn = (gridColumn) => { const spanMatch = gridColumn?.match(/^span\s+([1-9]|1[0-2])$/) return spanMatch ? gridColumn : 'span 12' } ``` ### XSS Prevention ```javascript // Escape user input in labels and help text const escapeHtml = (text) => { const div = document.createElement('div') div.textContent = text return div.innerHTML } ``` ## Future Enhancements ### Planned Features 1. **Advanced Grid Controls**: Custom grid templates, responsive breakpoints 2. **Component Templates**: Reusable component groups 3. **Theme System**: Multiple visual themes for forms 4. **Advanced Validation**: Cross-field validation, async validation 5. **Collaboration**: Real-time multi-user editing 6. **Version Control**: Form versioning and rollback 7. **Analytics**: Form usage and completion analytics ### Technical Debt Items 1. **TypeScript Migration**: Complete TypeScript coverage 2. **Test Coverage**: Increase to 90%+ coverage 3. **Performance**: Virtual scrolling for large forms 4. **Accessibility**: Full WCAG 2.1 AA compliance --- *This documentation reflects the current implementation including all enhanced features: smart collapsible panel system, visual grid selection, intelligent width recommendations, and comprehensive UX improvements.* Last updated: December 2024