# Компонент ModalWindow - Полная документация

## Назначение компонента

`ModalWindow` - универсальный компонент для создания модальных окон (диалоговых окон) в приложении. Предоставляет функциональность для отображения контента поверх основного интерфейса с затемнением фона, анимациями и управлением через глобальную шину событий.

## git репозитарий
https://gogs.osvoj.ru/s5l.ru/borbad.s5l.ru/src/master/vue/app/shared/ModalWindow/

## Архитектура компонента

### Структура файлов
```
app/shared/ModalWindow/
├── index.coffee    # Логика компонента
├── index.pug       # Шаблон
└── index.styl      # Стили
```

## Импорт и регистрация

```coffee
# В основном файле приложения (app/temp.coffee)
components:
    'modal-window': require 'app/shared/ModalWindow'
```

## Базовое использование

### 1. Простое модальное окно
```pug
modal-window(
    :is-visible="showModal"
    @close="showModal = false"
)
    template([body])
        h2(class="text-xl font-bold mb-4") Заголовок
        p Содержимое модального окна
```

### 2. С кнопками действий
```pug
modal-window(
    :is-visible="showModal"
    @close="showModal = false"
    @confirm="handleConfirm"
)
    template([body])
        h2(class="text-xl font-bold mb-4") Подтверждение
        p Вы уверены, что хотите выполнить это действие?
    
    template([footer])
        button(@click="$emit('close')" class="btn-secondary") Отмена
        button(@click="$emit('confirm')" class="btn-primary") Подтвердить
```

## Полный список props

### `isVisible` (обязательный)
- **Тип:** `Boolean`
- **Описание:** Управляет видимостью модального окна
- **Пример:**
  ```pug
  modal-window(:is-visible="isModalOpen")
  ```

### `title` (опциональный)
- **Тип:** `String`
- **По умолчанию:** `''`
- **Описание:** Заголовок модального окна
- **Пример:**
  ```pug
  modal-window(:is-visible="showModal" title="Заголовок окна")
  ```

### `size` (опциональный)
- **Тип:** `String`
- **По умолчанию:** `'md'`
- **Допустимые значения:** `'sm'`, `'md'`, `'lg'`, `'xl'`, `'full'`
- **Описание:** Размер модального окна
- **Пример:**
  ```pug
  modal-window(:is-visible="showModal" size="lg")
  ```

### `closeOnBackdrop` (опциональный)
- **Тип:** `Boolean`
- **По умолчанию:** `true`
- **Описание:** Закрывать ли окно при клике на подложку
- **Пример:**
  ```pug
  modal-window(:is-visible="showModal" :close-on-backdrop="false")
  ```

### `closeOnEscape` (опциональный)
- **Тип:** `Boolean`
- **По умолчанию:** `true`
- **Описание:** Закрывать ли окно при нажатии Escape
- **Пример:**
  ```pug
  modal-window(:is-visible="showModal" :close-on-escape="false")
  ```

### `showCloseButton` (опциональный)
- **Тип:** `Boolean`
- **По умолчанию:** `true`
- **Описание:** Показывать ли кнопку закрытия
- **Пример:**
  ```pug
  modal-window(:is-visible="showModal" :show-close-button="false")
  ```

### `overlayClass` (опциональный)
- **Тип:** `String`
- **По умолчанию:** `''`
- **Описание:** Дополнительные классы для подложки
- **Пример:**
  ```pug
  modal-window(:is-visible="showModal" overlay-class="bg-opacity-80")
  ```

### `contentClass` (опциональный)
- **Тип:** `String`
- **По умолчанию:** `''`
- **Описание:** Дополнительные классы для контента
- **Пример:**
  ```pug
  modal-window(:is-visible="showModal" content-class="custom-modal-style")
  ```

## События (Events)

### `@close`
- **Описание:** Событие закрытия модального окна
- **Payload:** `null`
- **Пример:**
  ```pug
  modal-window(:is-visible="showModal" @close="handleModalClose")
  ```

### `@confirm` (опциональный)
- **Описание:** Событие подтверждения действия
- **Payload:** `null`
- **Пример:**
  ```pug
  modal-window(:is-visible="showModal" @confirm="handleConfirm")
  ```

### `@opened`
- **Описание:** Событие полного открытия модального окна (после анимации)
- **Payload:** `null`
- **Пример:**
  ```pug
  modal-window(:is-visible="showModal" @opened="handleModalOpened")
  ```

### `@closed`
- **Описание:** Событие полного закрытия модального окна (после анимации)
- **Payload:** `null`
- **Пример:**
  ```pug
  modal-window(:is-visible="showModal" @closed="handleModalClosed")
  ```

## Слоты (Slots)

### `[body]` (основной слот)
- **Описание:** Основное содержимое модального окна
- **Пример:**
  ```pug
  modal-window(:is-visible="showModal")
      template([body])
          h2 Заголовок
          p Основной контент
          form
              input(type="text" placeholder="Введите данные")
              button(type="submit") Отправить
  ```

### `[header]` (опциональный)
- **Описание:** Заголовочная область модального окна
- **Пример:**
  ```pug
  modal-window(:is-visible="showModal")
      template([header])
          div(class="flex items-center justify-between")
              h2(class="text-xl font-bold") Пользовательский заголовок
              custom-close-button(@click="$emit('close')")
  
      template([body])
          p Содержимое модального окна
  ```

### `[footer]` (опциональный)
- **Описание:** Нижняя область модального окна (обычно для кнопок)
- **Пример:**
  ```pug
  modal-window(:is-visible="showModal")
      template([body])
          p Вы уверены, что хотите удалить этот элемент?
  
      template([footer])
          div(class="flex justify-end space-x-3")
              button(@click="$emit('close')" class="btn-secondary") Отмена
              button(@click="$emit('confirm')" class="btn-danger") Удалить
  ```

## Размеры модальных окон

### Доступные размеры
```pug
//- Маленькое (sm)
modal-window(:is-visible="showModal" size="sm")

//- Среднее (md) - по умолчанию
modal-window(:is-visible="showModal" size="md")

//- Большое (lg)
modal-window(:is-visible="showModal" size="lg")

//- Очень большое (xl)
modal-window(:is-visible="showModal" size="xl")

//- На весь экран (full)
modal-window(:is-visible="showModal" size="full")
```

## Стили и CSS классы

### Базовые классы
- `.modal-overlay` - класс подложки
- `.modal-container` - класс контейнера
- `.modal-content` - класс контента

### Модификаторы размера
- `.modal--sm` - маленький размер
- `.modal--md` - средний размер (по умолчанию)
- `.modal--lg` - большой размер
- `.modal--xl` - очень большой размер
- `.modal--full` - на весь экран

### Состояния анимации
- `.modal-enter-active` - анимация появления
- `.modal-leave-active` - анимация исчезновения

## Примеры использования в различных сценариях

### 1. Простая информационная модалка
```pug
modal-window(
    :is-visible="showInfoModal"
    @close="showInfoModal = false"
    title="Информация"
)
    template([body])
        p(class="mb-4") Это информационное модальное окно с простым текстом.
        p Вы можете закрыть его, нажав на крестик или кликнув вне окна.
```

### 2. Модалка подтверждения действия
```pug
modal-window(
    :is-visible="showConfirmModal"
    @close="showConfirmModal = false"
    @confirm="handleDeleteConfirm"
    title="Подтверждение удаления"
    size="sm"
)
    template([body])
        p Вы уверены, что хотите удалить "{{ itemName }}"? Это действие нельзя отменить.

    template([footer])
        div(class="flex justify-end space-x-3")
            button(
                @click="$emit('close')"
                class="px-4 py-2 text-gray-600 hover:text-gray-800 transition-colors"
            ) Отмена
            button(
                @click="$emit('confirm')"
                class="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700 transition-colors"
            ) Удалить
```

### 3. Форма в модальном окне
```pug
modal-window(
    :is-visible="showFormModal"
    @close="closeFormModal"
    title="Добавить мероприятие"
    size="lg"
    :close-on-backdrop="false"
)
    template([body])
        form(@submit.prevent="submitEventForm")
            div(class="space-y-4")
                div
                    label(for="title" class="block text-sm font-medium text-gray-700") Название
                    input(
                        id="title"
                        v-model="form.title"
                        type="text"
                        class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
                        required
                    )
                
                div
                    label(for="description" class="block text-sm font-medium text-gray-700") Описание
                    textarea(
                        id="description"
                        v-model="form.description"
                        rows="4"
                        class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
                    )
    
    template([footer])
        div(class="flex justify-end space-x-3")
            button(
                type="button"
                @click="$emit('close')"
                class="px-4 py-2 text-gray-600 hover:text-gray-800 transition-colors"
            ) Отмена
            button(
                type="submit"
                class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors"
            ) Сохранить
```

### 4. Модалка с кастомным заголовком
```pug
modal-window(
    :is-visible="showCustomModal"
    @close="showCustomModal = false"
    :show-close-button="false"
)
    template([header])
        div(class="bg-gradient-to-r from-blue-500 to-purple-600 text-white p-6")
            div(class="flex items-center justify-between")
                div
                    h2(class="text-2xl font-bold") Премиум функции
                    p(class="text-blue-100") Доступно только для премиум пользователей
                button(
                    @click="$emit('close')"
                    class="text-white hover:text-blue-200 transition-colors"
                )
                    icon(name="close" class="w-6 h-6")
    
    template([body])
        div(class="p-6")
            ul(class="space-y-3")
                li(class="flex items-center")
                    icon(name="check" class="w-5 h-5 text-green-500 mr-3")
                    span Расширенная аналитика
                li(class="flex items-center")
                    icon(name="check" class="w-5 h-5 text-green-500 mr-3")
                    span Приоритетная поддержка
                li(class="flex items-center")
                    icon(name="check" class="w-5 h-5 text-green-500 mr-3")
                    span Кастомные домены
    
    template([footer])
        div(class="bg-gray-50 px-6 py-4 flex justify-between items-center")
            span(class="text-gray-600") Всего 999 TJS/месяц
            button(
                @click="subscribePremium"
                class="px-6 py-2 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-lg hover:from-blue-600 hover:to-purple-700 transition-colors"
            ) Подписаться
```

### 5. Модалка с загрузкой контента
```pug
modal-window(
    :is-visible="showLoadingModal"
    @close="cancelLoading"
    title="Загрузка"
    :close-on-escape="false"
    :close-on-backdrop="false"
    :show-close-button="false"
)
    template([body])
        div(class="text-center py-8")
            div(class="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4")
            p Загрузка данных, пожалуйста подождите...
```

### 6. Модалка с вкладками
```pug
modal-window(
    :is-visible="showTabsModal"
    @close="showTabsModal = false"
    title="Настройки"
    size="lg"
)
    template([body])
        div
            div(class="border-b border-gray-200")
                nav(class="-mb-px flex space-x-8")
                    button(
                        v-for="tab in tabs"
                        :key="tab.id"
                        @click="currentTab = tab.id"
                        :class="{
                            'border-blue-500 text-blue-600': currentTab === tab.id,
                            'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300': currentTab !== tab.id
                        }"
                        class="whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
                    ) {{ tab.name }}
            
            div(class="py-4")
                div(v-if="currentTab === 'general'")
                    h3(class="text-lg font-medium mb-4") Основные настройки
                    //- Контент вкладки
                
                div(v-else-if="currentTab === 'security'")
                    h3(class="text-lg font-medium mb-4") Безопасность
                    //- Контент вкладки
```

## Управление через глобальную шину событий

### Открытие модального окна
```coffee
# В любом компоненте
EventBus.emit('open_modal', {
    component: require('app/components/CustomModal'),
    props: {
        title: 'Кастомное окно',
        data: someData
    }
})
```

### Закрытие модального окна
```coffee
# Закрытие текущего модального окна
EventBus.emit('close_modal')

# Закрытие всех модальных окон
EventBus.emit('close_all_modals')
```

## Интеграция с глобальным состоянием

### Использование с appState
```coffee
# В основном приложении
appState:
    modalState:
        isVisible: false
        component: null
        props: {}

# Открытие модалки
openModal: (component, props = {}) ->
    @appState.modalState.component = component
    @appState.modalState.props = props
    @appState.modalState.isVisible = true

# В шаблоне
modal-window(
    :is-visible="appState.modalState.isVisible"
    @close="closeModal"
    v-if="appState.modalState.component"
)
    component(
        :is="appState.modalState.component"
        v-bind="appState.modalState.props"
        @close="closeModal"
    )
```

## Анимации и переходы

### Кастомные анимации
```styl
// В стилях компонента
.modal-custom-enter-active
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1)
    
    .modal-container
        transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1)
        transform: scale(0.95) translateY(-10px)
        opacity: 0

.modal-custom-enter-to
    .modal-container
        transform: scale(1) translateY(0)
        opacity: 1
```

## Best Practices

### 1. Управление состоянием
```coffee
# Правильно - реактивное управление
data: ->
    return
        showModal: false

methods:
    openModal: ->
        @showModal = true
    
    closeModal: ->
        @showModal = false
```

### 2. Обработка подтверждений
```coffee
methods:
    handleConfirm: ->
        try
            await this.performAction()
            this.showModal = false
            this.showSuccessMessage()
        catch error
            this.showErrorMessage(error)
```

### 3. Доступность
```pug
//- Добавляйте aria-атрибуты для доступности
modal-window(
    :is-visible="showModal"
    @close="closeModal"
    role="dialog"
    aria-labelledby="modal-title"
)
    template([header])
        h2(id="modal-title") Заголовок модалки
```

### 4. Управление фокусом
```coffee
# Автоматически фокусироваться на первом интерактивном элементе
mounted: ->
    this.$nextTick(() ->
        const firstInput = this.$el.querySelector('input, button, textarea')
        if firstInput
            firstInput.focus()
    )
```

## Отладка и разработка

### Логирование событий
```coffee
# Отслеживание событий модального окна
EventBus.on('modal_opened', (data) ->
    debug.log "Модальное окно открыто: "+data.component?.name
)

EventBus.on('modal_closed', (data) ->
    debug.log "Модальное окно закрыто"
)
```

### Проверка доступности
```coffee
# Проверка управления фокусом
checkFocusManagement: ->
    if this.isVisible
        const activeElement = document.activeElement
        const modalContent = this.$el.querySelector('.modal-content')
        
        if modalContent and !modalContent.contains(activeElement)
            debug.log "Фокус вне модального окна!"
```

Компонент ModalWindow предоставляет мощный и гибкий инструмент для создания модальных окон с поддержкой анимаций, управления через события, кастомизацией и соблюдением лучших практик доступности.
