+          import {
+  createSelected,
+  customStyles,
+  getFormatItem,
+  customStylesFormat,
+} from './components/utils';
+import { createBreadcrumb } from './components/create-element';
+
+/**
+ * @class Описание класса DropDown
+ * @description Этот класс реализовывает функционал кастомного селекта, с возможностями кастомизации.
+ *@author Овсяников Максим
+ */
+export class DropDown {
+  /**
+   * Созданный HTML елемент
+   * @type {HTMLElement}
+   */
+  #element;
+  /**
+   * Созданный список(ul), с классом list
+   * @type {HTMLElement}
+   */
+  #list;
+  /**
+   * Настройки селекта передаваемые при создании экземпляра класса
+   * @type {object}
+   */
+  #options;
+  /**
+   * Переменная для управления каретки
+   * @type {HTMLElement}
+   */
+  #caret;
+  /**
+   * Массив переданных элементов
+   * @type {object[]}
+   */
+  #items;
+  /**
+   * Переданные категории
+   * @type {string}
+   */
+  #category;
+  /**
+   * Выбранный или массив выбранных элементов из списка
+   * @type {object[] | object}
+   */
+  #selectedItems;
+  /**
+   * Массив индексов выбранных элементов
+   * @type {number[]}
+   */
+  #indexes = [];
+
+  /**
+   * Метод экземпляра класса DropDown
+   * @returns {string[] | string | null} Возвращает выбранные элемент(ы) в виде массива/элемента/null
+   * @description Геттер возвращающий выбранные элемент(ы) селекта
+   */
+  get value() {
+    return this.#selectedItems ?? null;
+  }
+
+  /**
+   * Метод экземпляра класса DropDown
+   * @returns {number | number[]}Возвращает индексы выбранных элемента(ов) в виде массива/пустой массив
+   * @description Геттер возвращающий индексы выбранных элемента(ов) селекта
+   */
+  get indexes() {
+    return this.#indexes ?? [];
+  }
+
+  /**
+   *
+   * @param {object} options Объект принимающий настройки селекта
+   * @constructor Конструктор класса DropDown
+   * @description  Конструктор принимает объект и рендерит селект.
+   * @example
+   * options = {
+   *  selector: 'Уникальный селектор',
+      selected: 'Выбранный элемент',
+      placeholder: '...',
+      items: [string|number|object],
+      styles: {
+        head: {
+          background: '...',
+        },
+        list: {...},
+        chips: {...},
+        caret: {...},
+        placeholder: {...},
+      },
+      event: '...',
+      url: 'http/...',
+      multiselect: true/false,
+      multiselectTag: true/false,
+   * }
+     
+   */
+  constructor(options = {}) {
+    this.#init(options);
+    this.#render();
+    this.#initEvent();
+  }
+
+  /**
+   * Метод экземпляра класса DropDown
+   * @param {string | object} item добавляемый елемент
+   * @description добавляет переданный элемент в конец списка и перерисовывает список. Не может использоваться при передачи элементов с категорями
+   * @method addItem
+   */
+  addItem(item) {
+    if (this.#category) {
+      console.log('can`t add item to category');
+      return;
+    }
+
+    if (!item) {
+      return false;
+    }
+
+    const index = this.#items.length;
+
+    this.#items.push(getFormatItem(item, index));
+    this.#render();
+  }
+
+  /**
+   * Метод экземпляра класса DropDown
+   * @param {number} index индекс удаляемого элемента
+   * @description удаляет елемент по индексу из списка и перерисовывает его. Не может использоваться при передачи элементов с категорями.
+   * @method deleteItem
+   */
+  deleteItem(index) {
+    if (this.#category) {
+      console.log('can`t add item to category');
+      return;
+    }
+
+    const item = this.#items[index];
+
+    this.#items.splice(index, 1);
+    this.#render();
+  }
+
+  /**
+   * Метод экземпляра класса DropDown
+   * @description удаляет все елементы из списка и перерисовывает его.
+   * @method deleteItemAll
+   */
+  deleteItemAll() {
+    this.#items.splice(0, this.#items.length);
+    this.#render();
+  }
+
+  /**
+   * Метод экземпляра класса DropDown
+   * @param {number} index индекс выбранного элемента
+   * @description  выбирает элемент который будет изначально отрисовываться в селекте
+   * @method selectIndex
+   */
+  selectIndex(index) {
+    if (this.#category) {
+      console.log('can`t add item to category');
+      return;
+    }
+
+    const options = this.#element.querySelectorAll('.list__item');
+
+    if (index > options.length) {
+      return;
+    }
+
+    const select = options[index].innerText;
+    this.#render(select);
+  }
+
+  /**
+   * Метод экземпляра класса DropDown
+   * @param {number} numberItem номер возвращаемого элемента
+   * @returns {HTMLElement} возвращает ссылку на выбранный HTML элемент
+   * @method getElement
+   */
+  getElement(numberItem) {
+    if (numberItem > this.#items.length) {
+      return;
+    }
+    return this.#items[numberItem];
+  }
+
+  /**
+   * Метод экземпляра класса DropDown
+   * @param {boolean} value - Передаваемый параметр для добавления атрибута disabled;
+   * @description Метод позволяющий переключать состояние селекта disabled,
+   * @method disabled
+   */
+  disabled(value) {
+    if (typeof value !== 'boolean') {
+      return;
+    }
+
+    const select = this.#element.querySelector('.cg-select');
+    if (value === true) {
+      this.#element.setAttribute('disabled', true);
+      select.classList.add('disabled');
+    } else {
+      this.#element.removeAttribute('disabled');
+      select.classList.remove('disabled');
+    }
+  }
+
+  /**
+   * Метод экземпляра класса DropDown
+   * @param {HTMLInputElement} button - HTML кнопка
+   * @param {string} method - метод открытия open/close
+   * @description Метод позволяющий открывать/закрывать селект с помощью кнопок
+   * @method buttonControl
+   */
+  buttonControl(button, method) {
+    button.addEventListener('click', () => {
+      if (method === 'open') {
+        this.#open(true);
+      } else if (method === 'close') {
+        this.#close();
+      } else {
+        return;
+      }
+    });
+  }
+
+  /**
+   * Приватный метод инициализации экземпляра класса DropDown
+   * @method #init
+   * @member
+   * @protected
+   * @param {object} options передаваемые настройки селекта
+   * @description Приватный метод. Общая инициализация селекта. Получение настоек и преобразвание элементов селекта.
+   * @example
+   *  {
+        selector: '.cg-dropdown_one',
+        placeholder: 'Выберите авто',
+        items: [
+          'BMW',
+          {
+            id: '213sade',
+            title: 'Opel',
+            value: 1,
+          },
+          'Mersedes',
+          'MAN',
+          'max',
+        ],
+        multiselect: true,
+        multiselectTag: true,
+      }
+   */
+  #init(options) {
+    this.#options = options;
+    const { items, multiselect, url } = this.#options;
+
+    const elem = document.querySelector(options.selector);
+
+    if (!elem) {
+      throw new Error(`Element with selector ${options.selector}`);
+    }
+
+    this.#element = elem;
+
+    this.#element.addEventListener('click', () => {
+      this.#open();
+    });
+
+    this.#items = [];
+
+    if (multiselect) {
+      this.#selectedItems = [];
+    }
+
+    if (!items && url) {
+      this.#renderUrl();
+      return;
+    }
+
+    items.forEach((dataItem, index) => {
+      if (dataItem.category && dataItem.categoryItems) {
+        this.#category = dataItem.category;
+
+        this.#items.push(this.#category);
+        dataItem.categoryItems.forEach((categoryItem, indexCategory) => {
+          this.#items.push(getFormatItem(categoryItem, indexCategory));
+        });
+      } else {
+        this.#items.push(getFormatItem(dataItem, index));
+      }
+    });
+  }
+
+  /**
+   * Привaтный метод экземпляра класса DropDown
+   *
+   * @method #initSelected
+   * @param {string} select необязательный елемент. Используется в методе selectIndex
+   * @description Отрисовывает и стилизует селект
+   * @protected
+   */
+  #initSelected(select) {
+    const { styles, selected, placeholder } = this.#options;
+
+    if (selected) {
+      createSelected(this.#element, selected);
+    } else if (placeholder) {
+      createSelected(this.#element, placeholder);
+    } else {
+      createSelected(this.#element, 'Select...');
+    }
+
+    if (styles) {
+      customStyles(this.#element, styles);
+    }
+
+    if (select) {
+      createSelected(this.#element, select, styles);
+    }
+  }
+
+  /**
+   * Приватный метод рендера экземпляра класса DropDown
+   *@protected
+   * @method #render
+   * @param {string} select  необязательный елемент. Передаеться в метод initSelected
+   * @description Рендер елементов в селекте.
+   */
+  #render(select) {
+    const { styles, multiselect } = this.#options;
+
+    if (select || (select && styles)) {
+      this.#initSelected(select);
+      customStyles(this.#element, styles);
+    } else {
+      this.#initSelected();
+    }
+
+    const ulList = document.createElement('ul');
+
+    ulList.classList.add('list');
+
+    if (styles) {
+      const { list } = styles;
+      customStylesFormat(list, ulList);
+    }
+
+    this.#element.appendChild(ulList);
+
+    this.#items.forEach((dataItem) => {
+      const liItem = document.createElement('li');
+      const strongItem = document.createElement('strong');
+
+      liItem.classList.add('list__item');
+      strongItem.classList.add('category');
+
+      if (multiselect) {
+        const checkBox = document.createElement('input');
+        checkBox.type = 'checkbox';
+        checkBox.setAttribute('id', `chbox-${dataItem.id}`);
+
+        liItem.appendChild(checkBox);
+      }
+
+      let textNode = '';
+
+      if (dataItem.title) {
+        textNode = document.createTextNode(dataItem.title);
+        liItem.appendChild(textNode);
+        ulList.appendChild(liItem);
+      } else {
+        textNode = document.createTextNode(dataItem);
+        strongItem.appendChild(textNode);
+        ulList.appendChild(strongItem);
+      }
+    });
+
+    this.#items.filter((item, index) => {
+      if (typeof item !== 'object') {
+        this.#items.splice(index, 1);
+      }
+      return item;
+    });
+
+    this.#addOptionsBehaviour();
+  }
+
+  /**
+   * Приватный метод рендера экземпляра класса DropDown
+   *@protected
+   * @method #renderUrl
+   * @description Рендер елементов в селекте переданных с URL и их настойка
+   */
+  async #renderUrl() {
+    const { url, items, multiselect } = this.#options;
+
+    if (items) {
+      return;
+    }
+
+    if (!url) {
+      return;
+    }
+
+    const response = await fetch(url);
+    const dataUrl = await response.json();
+
+    dataUrl.forEach((dataItem, index) => {
+      const item = {
+        id: dataItem.id,
+        title: dataItem.name,
+        value: index,
+      };
+      const ulUrl = this.#element.querySelector('.list');
+      const liUrl = document.createElement('li');
+      const textUrl = document.createTextNode(item.title);
+
+      if (multiselect) {
+        const checkBox = document.createElement('input');
+        checkBox.type = 'checkbox';
+
+        checkBox.setAttribute('id', `chbox-${item.id}`);
+        liUrl.appendChild(checkBox);
+      }
+
+      liUrl.classList.add('list__item');
+
+      liUrl.appendChild(textUrl);
+      ulUrl.appendChild(liUrl);
+
+      this.#items.push(item);
+    });
+
+    this.#items.filter((item, index) => {
+      if (typeof item !== 'object') {
+        this.#items.splice(index, 1);
+      }
+      return item;
+    });
+
+    this.#addOptionsBehaviour();
+  }
+
+  /**
+   * Приватный метод экземпляра класса DropDown
+   * @protected
+   * @param {boolean} oneClick необязательный параметр передаваемый из функции buttonControl
+   * @description Открывает список для выбора элемента
+   * @method #open
+   */
+  #open(oneClick) {
+    this.#list = this.#element.querySelector('.list');
+    this.#caret = this.#element.querySelector('.caret');
+
+    if (oneClick === true) {
+      this.#list.classList.add('open');
+      this.#caret.classList.add('caret_rotate');
+    } else {
+      this.#list.classList.toggle('open');
+      this.#caret.classList.toggle('caret_rotate');
+    }
+  }
+
+  /**
+   * Приватный метод экземпляра класса DropDown
+   * @protected
+   * @description Закрывает список
+   * @method #close
+   */
+  #close() {
+    this.#list.classList.remove('open');
+    this.#caret.classList.remove('caret_rotate');
+  }
+
+  /**
+   * Приватный метод экземпляра класса DropDown
+   * @protected
+   * @description Метод реализовывающий выбор элементов в разных режимах. Обычный/Мультиселект/Мультиселект + Мультиселект Таг.
+   * @method #addOptionsBehaviour
+   */
+  #addOptionsBehaviour() {
+    const { multiselect, placeholder, selected, multiselectTag } = this.#options;
+
+    const options = this.#element.querySelectorAll('.list__item');
+    const select = this.#element.querySelector('.selected');
+
+    const ul = document.createElement('ul');
+
+    if (multiselect) {
+      ul.classList.add('multiselect-tag');
+      select.classList.add('overflow-hidden');
+    }
+
+    options.forEach((option, index) => {
+      option.addEventListener('click', (event) => {
+        const item = this.#items[index];
+        if (multiselect) {
+          event.stopPropagation();
+          option.classList.toggle('active');
+
+          const checkBox = option.querySelector('input[type="checkbox"]');
+
+          if (checkBox) {
+            if (!(event.target instanceof HTMLInputElement)) {
+              checkBox.checked = !checkBox.checked;
+            }
+
+            const checkIndex = this.#indexes.indexOf(index);
+
+            if (checkIndex === -1) {
+              this.#indexes.push(index);
+
+              select.innerText = '';
+
+              if (multiselectTag) {
+                this.#selectedItems.push(item);
+                select.appendChild(ul);
+
+                const data = {
+                  option: this.#options,
+                  element: this.#element,
+                  indexes: this.#indexes,
+                  selectedItems: this.#selectedItems,
+                };
+
+                ul.appendChild(createBreadcrumb(data, item.title, index, item.id));
+              } else {
+                this.#selectedItems.push(item.title);
+                select.innerText = this.#selectedItems;
+              }
+            } else {
+              if (multiselectTag) {
+                const tagItem = document.getElementById(`tag-${index}-${item.id}`);
+
+                ul.removeChild(tagItem);
+              }
+              this.#indexes.splice(checkIndex, 1);
+              this.#selectedItems.splice(checkIndex, 1);
+            }
+
+            if (!this.#selectedItems.length) {
+              if (placeholder) {
+                select.innerText = placeholder;
+              } else if (selected) {
+                select.innerText = selected;
+              } else {
+                select.innerText = 'Select...';
+              }
+            } else {
+              if (multiselectTag) {
+                select.appendChild(ul);
+              } else {
+                select.innerText = this.#selectedItems;
+              }
+            }
+          }
+        } else {
+          select.innerText = item.title;
+          this.#selectedItems = item;
+
+          options.forEach((option) => {
+            option.classList.remove('active');
+          });
+          option.classList.add('active');
+        }
+      });
+    });
+  }
+
+  /**
+   * Приватный метод экземпляра класса DropDown
+   * @protected
+   * @description Открывает и закрывает список по переданному эвенту
+   * @method #initEvent
+   */
+  #initEvent() {
+    const { event } = this.#options;
+    if (!event) {
+      return;
+    }
+
+    if (event) {
+      if (event === 'mouseenter') {
+        this.#element.addEventListener(event, () => {
+          this.#open();
+        });
+        this.#element.addEventListener('mouseleave', () => {
+          this.#close();
+        });
+      }
+    }
+  }
+}
+
+        
+