{"version":3,"file":"index.mjs","sources":[""],"sourcesContent":["import { isNonEmptyArr } from \"@web3r/flowerkit/arr\";\r\nimport { getMergedObj } from \"@web3r/flowerkit/obj\";\r\nimport { getId } from \"@web3r/flowerkit/str\";\r\nimport { clusterDefaults, pointDefaults } from \"../../config\";\r\nimport type {\r\n  TAPI, TCluster, TClusterDefaults, TClusterElements,\r\n  TConstructorInstance, TFactoryCallback, TMapContext, TPoint, TPointDefaults, ILayoutBalloonCluster,\r\n} from \"../../config/types\";\r\nimport {\r\n  getLayoutConstructor, getUserField, isValidLayout,\r\n} from \"../index\";\r\nimport { getNormalizedPoints } from \"../placemark\";\r\n\r\n/**\r\n * Получает кластеры с предустановленными параметрами\r\n * @param clusters{TCluster[]}\r\n * @param clusterOptions{TClusterDefaults}\r\n * @param pointOptions{TPointDefaults}\r\n * @returns TCluster[]\r\n */\r\nconst getNormalizedClusters = (clusters: TCluster[], clusterOptions: Partial<TClusterDefaults> = clusterDefaults, pointOptions: Partial<TPointDefaults> = pointDefaults) => {\r\n  return (Array.isArray(clusters) ? clusters : [])\r\n    .filter((item) => {\r\n      if (!!item && !!item.id && Array.isArray(item.points)) {\r\n        return true;\r\n      } else {\r\n        console.error(`[Map] All clusters must have \"id\" (string) and \"points\" (array) props`, item);\r\n        return false;\r\n      }\r\n    })\r\n    .map((item) => {\r\n      const defaults = {\r\n        ...clusterDefaults,\r\n        ...clusterOptions,\r\n      };\r\n      const withDefaults = getMergedObj(defaults, item, {\r\n        isMergeArrays: false,\r\n      });\r\n      return {\r\n        ...withDefaults,\r\n        points: getNormalizedPoints(withDefaults.points, pointOptions),\r\n      };\r\n    });\r\n};\r\n\r\n/**\r\n * Получает экземпляр вызова templateLayoutFactory для указанного типа элемента\r\n * @param ymaps\r\n * @param props\r\n * @param getCN\r\n * @param callback\r\n * @param type\r\n * @returns {object}\r\n */\r\nconst ClustererInstanceLayout = async function({\r\n  ymaps, props, getCN, callback, type,\r\n}: {\r\n  ymaps: TAPI;\r\n  props: TCluster;\r\n  getCN: TMapContext[\"getCN\"];\r\n  callback?: TFactoryCallback<ILayoutBalloonCluster>;\r\n  type: TClusterElements;\r\n}): Promise<TConstructorInstance<ILayoutBalloonCluster>> {\r\n\r\n  return await getClustererLayout({\r\n    clusterer: props,\r\n    instance: ymaps,\r\n    getCN,\r\n    type,\r\n  })\r\n    .then((html) => {\r\n      return getLayoutConstructor(ymaps, html, callback, null);\r\n    });\r\n};\r\n\r\n/**\r\n * Получает разметку для Clusterer\r\n * @param getCN{Function}\r\n * @param clusterer{Object}\r\n * @param instance{Object}\r\n * @param type{String}\r\n * @returns {String}\r\n */\r\nconst getClustererLayout = async ({\r\n  getCN, instance, clusterer, type,\r\n}: {\r\n  getCN: TMapContext[\"getCN\"];\r\n  instance: TAPI;\r\n  clusterer: TCluster;\r\n  type: TClusterElements;\r\n}): Promise<string> => {\r\n\r\n  const userFnArg = {\r\n    point: clusterer.points[0]!,\r\n    clusterer,\r\n    instance,\r\n    getCN,\r\n  };\r\n\r\n  return new Promise<string>((resolve, reject) => {\n    void (async () => {\n      switch (type) {\n        case \"balloon\": {\r\n          const { getLayout = null, extraClasses = {} } = clusterer.render?.balloon ?? {};\r\n          if (typeof getLayout === \"function\") { // user layout\r\n            const layout = await getUserField(getLayout, userFnArg) || \"\";\r\n            resolve(layout);\r\n          } else { // default layout\r\n            resolve(`\r\n          <div class=\"${getCN(\"clusterBalloon\", extraClasses)}\" id=\"cluster_balloon_${clusterer.id}\">\r\n            <div class=\"${getCN(\"clusterBalloonInner\")}\">\r\n              <ul class=\"${getCN(\"clusterBalloonList\")}\">\r\n                {% for point in properties.points %}\r\n                <li class=\"{% if point.id === properties.activePoint.id %}${getCN(\"clusterBalloonListItem\", { isActive: true })}{% else %}${getCN(\"clusterBalloonListItem\")}{% endif %}\" >\r\n                  <button data-js-map-cluster-balloon-tab=\"{{ point.id }}\" class=\"${getCN(\"clusterBalloonListLink\")}\">{{ point.balloonHeader|raw }}</button>\r\n                </li>\r\n                {% endfor %}\r\n              </ul>\r\n              <div class=\"${getCN(\"clusterBalloonDetail\")}\">\r\n                <div class=\"${getCN(\"clusterBalloonDetailHeader\")}\">{{ properties.activePoint.balloonHeader|raw }}</div>\r\n                <div class=\"${getCN(\"clusterBalloonDetailContent\")}\">{{ properties.activePoint.balloonContent|raw }}</div>\r\n              </div>\r\n            </div>\r\n            <div class=\"${getCN(\"clusterBalloonClose\")}\">\r\n                <button data-js-map-cluster-balloon-close=\"\" type=\"button\" class=\"${getCN(\"balloonCloseBtn\")}\">\r\n                  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"3rem\" viewBox=\"0 -960 960 960\" width=\"3rem\" fill=\"currentColor\"><path d=\"m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z\"/></svg>\r\n                </button>\r\n              </div>\r\n          </div>\r\n        `);\r\n          }\r\n          break;\r\n        }\r\n        case \"icon\": {\r\n          const { getLayout = null, extraClasses = {} } = clusterer.render?.icon ?? {};\r\n          if (typeof getLayout === \"function\") { // user layout\r\n            const layout = await getUserField(getLayout, userFnArg) || \"\";\r\n            resolve(layout);\r\n          } else { // default layout\r\n            resolve(`\r\n          <div class=\"${getCN(\"cluster\", extraClasses)}\" id=\"cluster_${clusterer.id}\">\r\n            <div class=\"${getCN(\"clusterInner\")}\">\r\n              $[properties.geoObjects.length]\r\n            </div>\r\n          </div>\r\n        `);\r\n          }\r\n          break;\r\n        }\r\n        default: {\n          throw new Error(`Unsupported type \"${type}\"`);\n        }\n      }\n    })().catch(reject);\n  })\n    .then((layout) => {\r\n      return isValidLayout(layout) ? layout : Promise.reject(clusterer);\r\n    })\r\n    .catch((err) => {\r\n      console.error(\"[Maps] Something went wrong while parsing layout: \", err);\r\n      return \"\";\r\n    });\r\n};\r\n\r\n/**\r\n * Получает количество активных точек в кластерах\r\n * @returns {Number}\r\n */\r\nconst getActivePointsCount: ((clusters: TCluster[]) => number) = (clusters = []): number => {\r\n  return clusters\r\n    .map((item) => {\r\n      return item.points.filter((point) => point.state?.isActive).length;\r\n    })\r\n    .reduce((prev, current) => {\r\n      return prev + current;\r\n    }, 0);\r\n};\r\n\r\n/**\r\n * Получает начальное состояние кластеризации\r\n * @param clusters\r\n * @param points\r\n * @param clusterOptions\r\n * @param pointOptions\r\n * @returns {Array}\r\n */\r\nconst getInitialClusters = (clusters?: TCluster[], points?: TPoint[], clusterOptions?: Partial<TClusterDefaults>, pointOptions?: Partial<TPointDefaults>): TCluster[] => {\r\n  return (!!clusters && isNonEmptyArr(clusters)) ? getNormalizedClusters(clusters, clusterOptions, pointOptions) : getNormalizedClusters([\r\n    {\r\n      id: getId(8),\r\n      points: (!!points && isNonEmptyArr(points)) ? points : [],\r\n    },\r\n  ], clusterOptions, pointOptions);\r\n};\r\n\r\nexport {\r\n  ClustererInstanceLayout,\r\n  getActivePointsCount,\r\n  getClustererLayout,\r\n  getInitialClusters,\r\n  getNormalizedClusters,\r\n};\r\n"],"names":["getNormalizedClusters","clusters","clusterOptions","clusterDefaults","pointOptions","pointDefaults","Array","isArray","filter","item","id","points","console","error","map","defaults","withDefaults","getMergedObj","isMergeArrays","getNormalizedPoints","ClustererInstanceLayout","async","ymaps","props","getCN","callback","type","getClustererLayout","clusterer","instance","then","html","getLayoutConstructor","userFnArg","point","Promise","resolve","reject","getLayout","extraClasses","render","balloon","layout","getUserField","isActive","icon","Error","catch","isValidLayout","err","getActivePointsCount","state","length","reduce","prev","current","getInitialClusters","isNonEmptyArr","getId"],"mappings":";;;;;;;GAoBA,MAAMA,sBAAwB,CAACC,SAAsBC,eAA4CC,gBAAiBC,aAAwCC,iBAChJC,MAAMC,QAAQN,UAAYA,SAAW,IAC1CO,OAAQC,OACP,KAAMA,QAAUA,KAAKC,IAAMJ,MAAMC,QAAQE,KAAKE,QAC5C,OAAO,SACF,CACLC,QAAQC,MAAM,wEAAyEJ,MACvF,OAAO,KACT,IAEDK,IAAKL,OACJ,MAAMM,SAAW,IACZZ,mBACAD,gBAEL,MAAMc,aAAeC,aAAaF,SAAUN,KAAM,CAChDS,cAAe,QAEjB,MAAO,IACFF,aACHL,OAAQQ,oBAAoBH,aAAaL,OAAQP;;;;;;;;;GAczD,MAAMgB,wBAA0BC,gBAAeC,MAC7CA,MAAKC,MAAEA,MAAKC,MAAEA,MAAKC,SAAEA,SAAQC,KAAEA,OAS/B,aAAaC,mBAAmB,CAC9BC,UAAWL,MACXM,SAAUP,MACVE,YACAE,YAECI,KAAMC,MACEC,qBAAqBV,MAAOS,KAAMN,SAAU,MAEzD;;;;;;;;GAUA,MAAME,mBAAqBN,OACzBG,YAAOK,kBAAUD,oBAAWF,cAQ5B,MAAMO,UAAY,CAChBC,MAAON,UAAUjB,OAAO,GACxBiB,oBACAC,kBACAL,aAGF,OAAO,IAAIW,QAAgB,CAACC,QAASC,cAC9B,WACH,OAAQX,MACN,IAAK,UAAW,CACd,MAAMY,UAAEA,UAAY,KAAIC,aAAEA,aAAe,CAAA,GAAOX,UAAUY,QAAQC,SAAW,CAAA,EAC7E,UAAWH,YAAc,WAAY;;AACnC,MAAMI,aAAeC,aAAaL,UAAWL,YAAc,GAC3DG,QAAQM,OACV;;AACEN,QAAQ,2BACIZ,MAAM,iBAAkBe,sCAAsCX,UAAUlB,iCACtEc,MAAM,sDACLA,MAAM,4JAE2CA,MAAM,yBAA0B,CAAEoB,SAAU,mBAAoBpB,MAAM,8HAC9DA,MAAM,0KAI9DA,MAAM,0DACJA,MAAM,oHACNA,MAAM,4JAGVA,MAAM,+GACoDA,MAAM,4VAOhF,KACF,CACA,IAAK,OAAQ,CACX,MAAMc,UAAEA,UAAY,KAAIC,aAAEA,aAAe,CAAA,GAAOX,UAAUY,QAAQK,MAAQ,CAAA,EAC1E,UAAWP,YAAc,WAAY;;AACnC,MAAMI,aAAeC,aAAaL,UAAWL,YAAc,GAC3DG,QAAQM,OACV;;AACEN,QAAQ,2BACIZ,MAAM,UAAWe,8BAA8BX,UAAUlB,iCACvDc,MAAM,oHAMtB,KACF,CACA,QACE,MAAM,IAAIsB,MAAM,qBAAqBpB,SAG1C,EArDI,GAqDAqB,MAAMV,UAEVP,KAAMY,QACEM,cAAcN,QAAUA,OAASP,QAAQE,OAAOT,YAExDmB,MAAOE,MACNrC,QAAQC,MAAM,qDAAsDoC,KACpE,MAAO;;;;GAQb,MAAMC,qBAA2D,CAACjD,SAAW,KACpEA,SACJa,IAAKL,MACGA,KAAKE,OAAOH,OAAQ0B,OAAUA,MAAMiB,OAAOP,UAAUQ,QAE7DC,OAAO,CAACC,KAAMC,UACND,KAAOC,QACb;;;;;;;;GAWP,MAAMC,mBAAqB,CAACvD,SAAuBU,OAAmBT,eAA4CE,iBACtGH,UAAYwD,cAAcxD,UAAaD,sBAAsBC,SAAUC,eAAgBE,cAAgBJ,sBAAsB,CACrI,CACEU,GAAIgD,MAAM,GACV/C,SAAWA,QAAU8C,cAAc9C,QAAWA,OAAS,KAExDT,eAAgBE"}