svarog-ui-core
Version:
Core components of Svarog UI without themes
157 lines (130 loc) • 4.26 kB
JavaScript
// src/components/Form/FormSection.js
import {
createComponent,
createElement,
appendChildren,
} from '../../utils/componentFactory.js';
import { createBaseComponent } from '../../utils/baseComponent.js';
import { validateRequiredProps } from '../../utils/validation.js';
// CSS injection imports
import { createStyleInjector } from '../../utils/styleInjection.js';
import { formStyles } from './Form.styles.js';
// Create style injector for FormSection component (uses form styles)
const injectFormStyles = createStyleInjector('Form');
/**
* Creates a FormSection component for grouping related form fields
* @param {Object} props - FormSection properties
* @returns {Object} FormSection component API
*/
const createFormSection = (props) => {
// Inject styles on component creation
injectFormStyles(formStyles);
// Migrate legacy props to standardized props
const migrateLegacyProps = (props) => {
const migrated = { ...props };
// Example for future migrations if needed
// if ('sectionTitle' in props && !('title' in props)) {
// console.warn('[FormSection] sectionTitle is deprecated, use title instead');
// migrated.title = props.sectionTitle;
// delete migrated.sectionTitle;
// }
return migrated;
};
// Normalize props - but keep original props for validation
const normalizedProps = migrateLegacyProps(props);
// Validate required props - use original props to maintain backward compatibility with tests
validateRequiredProps(
props,
{
children: { required: true },
title: { required: false, type: 'string' },
description: { required: false, type: 'string' },
},
'FormSection'
);
// Initialize state from normalized props with defaults
const state = {
children: normalizedProps.children,
title: normalizedProps.title,
description: normalizedProps.description,
className: normalizedProps.className || '',
};
// Create base component with render function
const component = createBaseComponent((componentState) => {
return createSectionElement(componentState);
})(state);
/**
* Creates the section element
* @private
* @param {Object} state - Current state
* @returns {HTMLElement} The section element
*/
function createSectionElement(state) {
const { title, description, className, children } = state;
// Create section element
const section = createElement('div', {
classes: ['form-section', className],
});
// Add title if provided
if (title) {
const titleElement = createElement('h3', {
classes: ['form-section__title'],
text: title,
});
section.appendChild(titleElement);
}
// Add description if provided
if (description) {
const descriptionElement = createElement('p', {
classes: ['form-section__description'],
text: description,
});
section.appendChild(descriptionElement);
}
// Create content container
const content = createElement('div', {
classes: ['form-section__content'],
});
// Add content
appendChildren(content, children);
section.appendChild(content);
return section;
}
// Get the section element
const sectionElement = component.getElement();
// Public API
return {
/**
* Gets the section element
* @returns {HTMLElement} The section element
*/
getElement() {
return sectionElement;
},
/**
* Updates component with new props
* @param {Object} newProps - New properties
* @returns {Object} FormSection component for chaining
*/
update(newProps) {
// Apply prop standardization to new props
const normalizedNewProps = migrateLegacyProps(newProps);
// Update state
Object.assign(state, normalizedNewProps);
// Update component
component.update(state);
return this;
},
/**
* Clean up resources
*/
destroy() {
// Call base component's destroy
component.destroy();
},
};
};
// Define required props for validation
createFormSection.requiredProps = ['children'];
// Export as a component factory
export default createComponent('FormSection', createFormSection);