# Архитектура системы элементов ## Обзор Система была переработана для обеспечения универсальности и расширяемости. Теперь все элементы регистрируются в едином реестре, что позволяет легко добавлять новые типы элементов без изменения основного кода. ## Структура ### 1. Реестр элементов (`src/lib/element-registry.ts`) Центральный реестр, который содержит все определения элементов: ```typescript export interface ElementDefinition { type: ElementType; // Уникальный тип элемента label: string; // Человекочитаемое имя icon: ReactNode; // Иконка для UI Editor: React.FC<{ config: Config; onChange(c: Config): void }>; Preview: React.FC<{ config: Config }>; Render: React.FC<{ config: Config; value: Value; onChange?(v: Value): void }>; defaultConfig: Config; // Конфигурация по умолчанию mapToCells?(config: Config): CellTarget[]; // Маппинг на ячейки Excel } ``` ### 2. Базовые элементы (`src/components/BasicElements/`) Стандартные элементы формы: - `TextElement.tsx` - текстовое поле - `SelectElement.tsx` - выпадающий список - `NumberElement.tsx` - числовое поле - `DateElement.tsx` - поле даты - `TextareaElement.tsx` - многострочный текст - `CheckboxElement.tsx` - чекбокс - `RadioElement.tsx` - радиокнопки ### 3. Специальные элементы (`src/components/StandardsElement/`) Сложные элементы с собственной логикой: - `StandardsDialog.tsx` - диалог выбора эталонов - `StandardsEditor.tsx` - редактор настроек - `StandardsPreview.tsx` - превью элемента - `definition.tsx` - определение элемента ## Как добавить новый элемент ### 1. Создать компоненты ```typescript // MyElement/MyElementEditor.tsx export const MyElementEditor: React.FC<{ config: MyConfig; onChange: (config: MyConfig) => void }> = ({ config, onChange }) => { // Логика редактирования }; // MyElement/MyElementPreview.tsx export const MyElementPreview: React.FC<{ config: MyConfig }> = ({ config }) => { // Логика превью }; // MyElement/MyElementRender.tsx export const MyElementRender: React.FC<{ config: MyConfig; value: string; onChange?: (value: string) => void }> = ({ config, value, onChange }) => { // Логика рендеринга }; ``` ### 2. Создать определение ```typescript // MyElement/definition.tsx export const myElementDefinition: ElementDefinition = { type: "my_element", label: "Мой элемент", icon: , defaultConfig: { // конфигурация по умолчанию }, Editor: MyElementEditor, Preview: MyElementPreview, Render: MyElementRender, mapToCells: (config) => { // логика маппинга на ячейки Excel return []; }, }; ``` ### 3. Зарегистрировать в реестре ```typescript // src/lib/element-registry-init.ts import { myElementDefinition } from "@/components/MyElement/definition"; export function initializeElementRegistry() { // ... существующие элементы registerElement("my_element", myElementDefinition); } ``` ### 4. Добавить тип в types/template.ts ```typescript export type ElementType = | 'text' | 'select' | 'radio' | 'checkbox' | 'number' | 'textarea' | 'date' | 'standards' | 'my_element'; // <-- новый тип ``` ## Особенности элемента "Измерительные эталоны" ### Конфигурация ```typescript interface StandardsConfig { registryNumber: string; // ГРСИ sheet: string; // Лист Excel startCell: string; // Первая ячейка (например "A10") maxItems: number; // Обычно 7 targetCells: CellTarget[]; } ``` ### Логика маппинга Элемент автоматически генерирует ячейки для записи выбранных эталонов: ```typescript mapToCells: (cfg) => { const res: CellTarget[] = []; const parsed = parseCellAddress(cfg.startCell); if (!parsed) return res; const { column, row } = parsed; // Генерируем ячейки вертикально (A1, A2, A3...) for (let i = 0; i < cfg.maxItems; i++) { res.push({ sheet: cfg.sheet, cell: `${column}${row + i}`, displayName: `Эталон ${i + 1}`, }); } return res; } ``` ### Ограничения - Максимум 7 эталонов (настраивается) - Автоматическое заполнение только выбранных позиций - Оставшиеся ячейки остаются пустыми ## Преимущества новой архитектуры 1. **Расширяемость**: Добавление новых элементов требует минимальных изменений 2. **Универсальность**: Единый интерфейс для всех элементов 3. **Типобезопасность**: TypeScript обеспечивает корректность типов 4. **Модульность**: Каждый элемент самодостаточен 5. **Переиспользование**: Компоненты можно использовать в разных контекстах ## Миграция Старые элементы продолжают работать через fallback-логику в `ElementConstructor.tsx`. Для полной миграции рекомендуется перевести все элементы на новую архитектуру.