{"version":3,"file":"index.mjs","sources":[""],"sourcesContent":["import { getDocument } from \"ssr-window\";\r\nimport { onContentLoaded } from \"../../utils/onContentLoaded\";\r\n\r\n\r\n/**\r\n * Конфигурация диспетчера.\r\n */\r\nexport type TDispatcherCfg = {\r\n  eventContentProp: string;\r\n  isInitiatorValid: (params: TInitiatorValidationArg) => boolean;\r\n  isDebug: boolean;\r\n};\r\n\r\n\r\n/**\r\n * Базовая структура элемента коллекции для диспетчеризации.\r\n */\r\nexport type TDispatcherCollectionItem = {\r\n  instance: Element;\r\n};\r\n\r\n\r\n/**\r\n * Контекст, в пределах которого выполняется инициатор.\r\n */\r\nexport type TDispatcherContext = Document | HTMLElement;\r\n\r\n\r\n/**\r\n * Функция получения коллекции экземпляров.\r\n */\r\nexport type TDispatcherGetCollection = () => TDispatcherCollectionItem[];\r\n\r\n\r\n/**\r\n * Функция-инициатор, запускаемая для контекста.\r\n */\r\nexport type TDispatcherInitiatorFn = (context: TDispatcherContext) => void;\r\n\r\n\r\n/**\r\n * Значение записи инициатора в карте диспетчера.\r\n */\r\nexport type TDispatcherInitiatorMapValue = {\r\n  initiator: TDispatcherInitiatorFn;\r\n  getCollection?: TDispatcherGetCollection;\r\n};\r\n\r\n\r\n/**\r\n * Тип динамически вызываемого метода экземпляра.\r\n */\r\nexport type TDispatcherMethod = (...args: never[]) => unknown;\r\n\r\n\r\n/**\r\n * Аргументы валидации инициатора перед запуском.\r\n */\r\nexport type TInitiatorValidationArg = {\r\n  initiatorFn: TDispatcherInitiatorFn;\r\n  eventContentField: TDispatcherContext;\r\n  event: CustomEvent<Record<string, unknown>>;\r\n  initiators: Map<string, TDispatcherInitiatorMapValue>;\r\n};\r\n\r\nfunction hasMethod<T extends object, K extends PropertyKey>(\r\n  value: T,\r\n  key: K\r\n): value is T & Record<K, TDispatcherMethod> {\r\n  const method = (value as Record<PropertyKey, unknown>)[key];\r\n  return typeof method === \"function\";\r\n}\r\n\r\n/**\r\n * Диспетчер для управления инициаторами плагинов и их вызовом при загрузке контента. Singleton.\r\n * @module Dispatcher\r\n */\r\nclass Dispatcher {\r\n\r\n  static #instance: Dispatcher | null = null;\r\n\r\n  eventContentProp: string;\r\n\r\n  isInitiatorValid: TDispatcherCfg[\"isInitiatorValid\"];\n\n  isDebug: boolean;\n\n  /**\n   * Реестр инициаторов по селектору.\n   * Ключ — селектор, значение — функция инициализации и опциональная коллекция.\n   * @type {Map<string, TDispatcherInitiatorMapValue>}\n   */\n  static initiators = new Map<string, TDispatcherInitiatorMapValue>();\n\n  /**\n   * Признак регистрации плагина в глобальном namespace Core.\n   * @type {boolean}\n   */\n  static isApp = true;\n\n  /**\n   * Конфигурация Dispatcher по умолчанию.\n   * @type {TDispatcherCfg}\n   */\n  static defaultCfg: TDispatcherCfg = {\n    eventContentProp: \"content\",\n    isInitiatorValid: ({ initiatorFn, eventContentField }: TInitiatorValidationArg) => typeof initiatorFn === \"function\" && !!eventContentField,\n    isDebug: false,\r\n  };\r\n\r\n  constructor(cfg: Partial<TDispatcherCfg> = {}) {\r\n    if (Dispatcher.#instance) {\r\n      return Dispatcher.#instance;\r\n    }\r\n\r\n    const { eventContentProp, isInitiatorValid, isDebug } = { ...Dispatcher.defaultCfg, ...cfg };\r\n    this.eventContentProp = eventContentProp;\r\n    this.isInitiatorValid = isInitiatorValid.bind(this);\r\n    this.isDebug = isDebug;\r\n    this.#bindEvents();\r\n    Dispatcher.#instance = this;\r\n  }\r\n\r\n  #bindEvents() {\r\n    onContentLoaded<Record<string, unknown>>((e: CustomEvent<Record<string, unknown>>) => this.#onContentLoadedCallback(e));\r\n  }\r\n\r\n  #onContentLoadedCallback(e: CustomEvent<Record<string, unknown>>) {\r\n    const eventContentField = e?.detail?.[this.eventContentProp];\r\n\r\n    if (!eventContentField) {\r\n      console.error(`[Dispatcher] OnContentLoaded event problem: prop '${this.eventContentProp}' in 'eventContentField' is undefined`, e);\r\n      return;\r\n    }\r\n\r\n    Dispatcher.initiators.forEach(({ initiator }) => {\r\n      if (eventContentField instanceof Document || eventContentField instanceof HTMLElement) {\r\n        if (this.isInitiatorValid({\r\n          event: e,\r\n          initiatorFn: initiator,\r\n          eventContentField,\r\n          initiators: Dispatcher.initiators,\r\n        })) {\r\n          initiator(eventContentField);\r\n          if (this.isDebug) {\r\n            console.debug(\"[Dispatcher] Run initiator:\", initiator, eventContentField);\r\n          }\r\n        } else {\r\n          console.debug(\"[Dispatcher] Initiator is rejected by isInitiatorValid filter:\", initiator);\r\n        }\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Проверяет существование инициатора по селектору\r\n   * @param selector{String} селектор инициатора\r\n   * @returns {Boolean} результат проверки\r\n   */\r\n  static isInitiatorExist(selector: string) {\r\n    return Dispatcher.initiators.has(selector);\r\n  }\r\n\r\n  /**\r\n   * Устанавливает инициатор для селектора\r\n   * @param params{Object} параметры инициатора\r\n   * @param params.selector{String} селектор для идентификации\r\n   * @param params.initiator{Function} функция-инициатор\r\n   * @param params.getCollection{Function=} функция для получения коллекции экземпляров\r\n   */\r\n  static set initiator({ selector, initiator, getCollection = () => [] }: { selector: string; initiator: TDispatcherInitiatorFn; getCollection?: TDispatcherGetCollection; }) {\r\n    if (!Dispatcher.isInitiatorExist(selector)) {\r\n      Dispatcher.initiators.set(selector, { initiator, getCollection });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Выполняет действие для всех экземпляров коллекций в указанном элементе\r\n   * @param el{HTMLElement|null=} корневой элемент для поиска, по умолчанию body\r\n   * @param action{String} название метода для вызова у экземпляров\r\n   * @param filterFn{Function=} функция-фильтр для отбора экземпляров\r\n   */\r\n  static dispatchAction(\r\n    el: HTMLElement | null = null,\r\n    action: string,\r\n    filterFn: (instance: TDispatcherCollectionItem) => boolean = (_instance: TDispatcherCollectionItem) => true\r\n  ) {\r\n    const root = el || getDocument().body;\r\n\r\n    if (root) {\r\n      Dispatcher.initiators.forEach(({ getCollection = () => [] }) => {\r\n        getCollection().forEach((instance: TDispatcherCollectionItem) => {\r\n          if (root.contains(instance.instance) && hasMethod(instance, action) && filterFn(instance)) {\r\n            instance[action]();\r\n          }\r\n        });\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Удаляет инициатор по селектору\r\n   * @param selector{String} селектор инициатора для удаления\r\n   */\r\n  static removeInitiator(selector: string) {\r\n    if (Dispatcher.isInitiatorExist(selector)) {\r\n      Dispatcher.initiators.delete(selector);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Очищает все инициаторы\r\n   */\r\n  static clear() {\r\n    Dispatcher.initiators.clear();\r\n  }\r\n\r\n}\r\n\r\nexport {\r\n  Dispatcher,\r\n};\r\n"],"names":["hasMethod","value","key","method","Dispatcher","static","eventContentProp","isInitiatorValid","isDebug","Map","initiatorFn","eventContentField","constructor","cfg","instance","defaultCfg","this","bind","bindEvents","onContentLoaded","e","onContentLoadedCallback","detail","console","error","initiators","forEach","initiator","Document","HTMLElement","event","debug","isInitiatorExist","selector","has","getCollection","set","dispatchAction","el","action","filterFn","_instance","root","getDocument","body","contains","removeInitiator","delete","clear"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;GAiEA,SAASA,UACPC,MACAC,KAEA,MAAMC,OAAUF,MAAuCC,KACvD,cAAcC,SAAW,UAC3B;;;;GAMA,MAAMC,WAEJC,gBAAsC,KAEtCC,iBAEAC,iBAEAC;;;;;;AAOAH,kBAAoB,IAAII;;;;;AAMxBJ,aAAe;;;;;AAMfA,kBAAoC,CAClCC,iBAAkB,UAClBC,iBAAkB,EAAGG,wBAAaC,8CAAwDD,cAAgB,cAAgBC,kBAC1HH,QAAS,OAGX,WAAAI,CAAYC,IAA+B,IACzC,GAAIT,YAAWU,SACb,OAAOV,YAAWU,SAGpB,MAAMR,iBAAEA,iBAAgBC,iBAAEA,iBAAgBC,QAAEA,SAAY,IAAKJ,WAAWW,cAAeF,KACvFG,KAAKV,iBAAmBA,iBACxBU,KAAKT,iBAAmBA,iBAAiBU,KAAKD,MAC9CA,KAAKR,QAAUA,QACfQ,MAAKE,aACLd,YAAWU,SAAYE,IACzB,CAEA,WAAAE,GACEC,gBAA0CC,GAA4CJ,MAAKK,wBAAyBD,GACtH,CAEA,wBAAAC,CAAyBD,GACvB,MAAMT,kBAAoBS,GAAGE,SAASN,KAAKV,kBAE3C,IAAKK,kBAAmB,CACtBY,QAAQC,MAAM,qDAAqDR,KAAKV,wDAAyDc,GACjI,MACF,CAEAhB,WAAWqB,WAAWC,QAAQ,EAAGC,wBAC/B,GAAIhB,6BAA6BiB,UAAYjB,6BAA6BkB,YACxE,GAAIb,KAAKT,iBAAiB,CACxBuB,MAAOV,EACPV,YAAaiB,UACbhB,oCACAc,WAAYrB,WAAWqB,aACrB,CACFE,UAAUhB,mBACV,GAAIK,KAAKR,QACPe,QAAQQ,MAAM,8BAA+BJ,UAAWhB,kBAE5D,MACEY,QAAQQ,MAAM,iEAAkEJ,YAIxF;;;;;KAOA,uBAAOK,CAAiBC,UACtB,OAAO7B,WAAWqB,WAAWS,IAAID,SACnC;;;;;;;KASA,oBAAWN,EAAUM,SAAEA,SAAQN,UAAEA,UAASQ,cAAEA,cAAgB,IAAM,KAChE,IAAK/B,WAAW4B,iBAAiBC,UAC/B7B,WAAWqB,WAAWW,IAAIH,SAAU,CAAEN,oBAAWQ,6BAErD;;;;;;KAQA,qBAAOE,CACLC,GAAyB,KACzBC,OACAC,SAA8DC,WAAyC,MAEvG,MAAMC,KAAOJ,IAAMK,cAAcC,KAEjC,GAAIF,KACFtC,WAAWqB,WAAWC,QAAQ,EAAGS,4BAAgB,IAAM,OACrDA,gBAAgBT,QAASZ,WACvB,GAAI4B,KAAKG,SAAS/B,SAASA,WAAad,UAAUc,SAAUyB,SAAWC,SAAS1B,UAC9EA,SAASyB,aAKnB;;;;KAMA,sBAAOO,CAAgBb,UACrB,GAAI7B,WAAW4B,iBAAiBC,UAC9B7B,WAAWqB,WAAWsB,OAAOd,SAEjC;;;KAKA,YAAOe,GACL5C,WAAWqB,WAAWuB,OACxB"}