@ozdao/martyrs 0.2.453 → 0.2.455

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/dist/{Media-BsgJlo-X.js → Media-1oukRVfv.js} +1 -1
  2. package/dist/{Media-CxRfrG2S.mjs → Media-q-XJSM_H.mjs} +3 -3
  3. package/dist/builder.js +5 -0
  4. package/dist/builder.mjs +5 -0
  5. package/dist/{main-Zocv7IVl.js → main-C7jGMDJC.js} +6 -6
  6. package/dist/{main-7FA_ai95.mjs → main-yXkgrjj8.mjs} +120 -133
  7. package/dist/martyrs/src/components/DatePicker/DatePicker.vue.cjs +2 -2
  8. package/dist/martyrs/src/components/DatePicker/DatePicker.vue.cjs.map +1 -1
  9. package/dist/martyrs/src/components/DatePicker/DatePicker.vue.js +2 -2
  10. package/dist/martyrs/src/components/DatePicker/DatePicker.vue.js.map +1 -1
  11. package/dist/martyrs/src/components/EmptyState/EmptyState.vue.cjs +1 -1
  12. package/dist/martyrs/src/components/EmptyState/EmptyState.vue.js +1 -1
  13. package/dist/martyrs/src/components/Media/Media.vue.cjs +2 -2
  14. package/dist/martyrs/src/components/Media/Media.vue.cjs.map +1 -1
  15. package/dist/martyrs/src/components/Media/Media.vue.js +2 -2
  16. package/dist/martyrs/src/components/Media/Media.vue.js.map +1 -1
  17. package/dist/martyrs/src/components/Popup/Popup.vue2.cjs +0 -8
  18. package/dist/martyrs/src/components/Popup/Popup.vue2.cjs.map +1 -1
  19. package/dist/martyrs/src/components/Popup/Popup.vue2.js +0 -8
  20. package/dist/martyrs/src/components/Popup/Popup.vue2.js.map +1 -1
  21. package/dist/martyrs/src/components/Slider/Slider.native.vue.cjs +229 -0
  22. package/dist/martyrs/src/components/Slider/Slider.native.vue.cjs.map +1 -0
  23. package/dist/martyrs/src/components/Slider/Slider.native.vue.js +229 -0
  24. package/dist/martyrs/src/components/Slider/Slider.native.vue.js.map +1 -0
  25. package/dist/martyrs/src/modules/events/components/blocks/CardEvent.vue.cjs +29 -17
  26. package/dist/martyrs/src/modules/events/components/blocks/CardEvent.vue.cjs.map +1 -1
  27. package/dist/martyrs/src/modules/events/components/blocks/CardEvent.vue.js +29 -17
  28. package/dist/martyrs/src/modules/events/components/blocks/CardEvent.vue.js.map +1 -1
  29. package/dist/martyrs/src/modules/events/components/pages/Event.vue.cjs +1 -22
  30. package/dist/martyrs/src/modules/events/components/pages/Event.vue.cjs.map +1 -1
  31. package/dist/martyrs/src/modules/events/components/pages/Event.vue.js +4 -25
  32. package/dist/martyrs/src/modules/events/components/pages/Event.vue.js.map +1 -1
  33. package/dist/martyrs/src/modules/events/components/pages/Events.vue.cjs +50 -132
  34. package/dist/martyrs/src/modules/events/components/pages/Events.vue.cjs.map +1 -1
  35. package/dist/martyrs/src/modules/events/components/pages/Events.vue.js +66 -148
  36. package/dist/martyrs/src/modules/events/components/pages/Events.vue.js.map +1 -1
  37. package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.cjs +3 -33
  38. package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.cjs.map +1 -1
  39. package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.js +3 -33
  40. package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.js.map +1 -1
  41. package/dist/martyrs/src/modules/events/components/pages/EventsSearch.vue.cjs +98 -0
  42. package/dist/martyrs/src/modules/events/components/pages/EventsSearch.vue.cjs.map +1 -0
  43. package/dist/martyrs/src/modules/events/components/pages/EventsSearch.vue.js +98 -0
  44. package/dist/martyrs/src/modules/events/components/pages/EventsSearch.vue.js.map +1 -0
  45. package/dist/martyrs/src/modules/events/components/sections/EventsHot.vue.cjs +2 -4
  46. package/dist/martyrs/src/modules/events/components/sections/EventsHot.vue.cjs.map +1 -1
  47. package/dist/martyrs/src/modules/events/components/sections/EventsHot.vue.js +2 -4
  48. package/dist/martyrs/src/modules/events/components/sections/EventsHot.vue.js.map +1 -1
  49. package/dist/martyrs/src/modules/events/components/sections/FeaturedEvents.vue.cjs +8 -7
  50. package/dist/martyrs/src/modules/events/components/sections/FeaturedEvents.vue.cjs.map +1 -1
  51. package/dist/martyrs/src/modules/events/components/sections/FeaturedEvents.vue.js +8 -7
  52. package/dist/martyrs/src/modules/events/components/sections/FeaturedEvents.vue.js.map +1 -1
  53. package/dist/martyrs/src/modules/events/components/sections/List.vue.cjs +3 -3
  54. package/dist/martyrs/src/modules/events/components/sections/List.vue.cjs.map +1 -1
  55. package/dist/martyrs/src/modules/events/components/sections/List.vue.js +3 -3
  56. package/dist/martyrs/src/modules/events/components/sections/List.vue.js.map +1 -1
  57. package/dist/martyrs/src/modules/events/components/sections/SelectDate.vue.cjs +190 -0
  58. package/dist/martyrs/src/modules/events/components/sections/SelectDate.vue.cjs.map +1 -0
  59. package/dist/martyrs/src/modules/events/components/sections/SelectDate.vue.js +190 -0
  60. package/dist/martyrs/src/modules/events/components/sections/SelectDate.vue.js.map +1 -0
  61. package/dist/martyrs/src/modules/events/router/events.cjs +15 -0
  62. package/dist/martyrs/src/modules/events/router/events.cjs.map +1 -1
  63. package/dist/martyrs/src/modules/events/router/events.js +15 -0
  64. package/dist/martyrs/src/modules/events/router/events.js.map +1 -1
  65. package/dist/martyrs/src/modules/globals/globals.client.cjs +2 -0
  66. package/dist/martyrs/src/modules/globals/globals.client.cjs.map +1 -1
  67. package/dist/martyrs/src/modules/globals/globals.client.js +2 -0
  68. package/dist/martyrs/src/modules/globals/globals.client.js.map +1 -1
  69. package/dist/martyrs/src/modules/globals/views/components/layouts/App.vue.cjs +4 -1
  70. package/dist/martyrs/src/modules/globals/views/components/layouts/App.vue.cjs.map +1 -1
  71. package/dist/martyrs/src/modules/globals/views/components/layouts/App.vue.js +3 -0
  72. package/dist/martyrs/src/modules/globals/views/components/layouts/App.vue.js.map +1 -1
  73. package/dist/martyrs/src/modules/globals/views/components/layouts/Client.vue.cjs +2 -4
  74. package/dist/martyrs/src/modules/globals/views/components/layouts/Client.vue.cjs.map +1 -1
  75. package/dist/martyrs/src/modules/globals/views/components/layouts/Client.vue.js +0 -2
  76. package/dist/martyrs/src/modules/globals/views/components/layouts/Client.vue.js.map +1 -1
  77. package/dist/martyrs/src/modules/globals/views/plugins/AlertDialog.vue.cjs +43 -0
  78. package/dist/martyrs/src/modules/globals/views/plugins/AlertDialog.vue.cjs.map +1 -0
  79. package/dist/martyrs/src/modules/globals/views/plugins/AlertDialog.vue.js +43 -0
  80. package/dist/martyrs/src/modules/globals/views/plugins/AlertDialog.vue.js.map +1 -0
  81. package/dist/martyrs/src/modules/globals/views/plugins/alert.plugin.cjs +53 -0
  82. package/dist/martyrs/src/modules/globals/views/plugins/alert.plugin.cjs.map +1 -0
  83. package/dist/martyrs/src/modules/globals/views/plugins/alert.plugin.js +53 -0
  84. package/dist/martyrs/src/modules/globals/views/plugins/alert.plugin.js.map +1 -0
  85. package/dist/martyrs/src/modules/organizations/components/sections/Documents.vue.cjs +0 -1
  86. package/dist/martyrs/src/modules/organizations/components/sections/Documents.vue.cjs.map +1 -1
  87. package/dist/martyrs/src/modules/organizations/components/sections/Documents.vue.js +0 -1
  88. package/dist/martyrs/src/modules/organizations/components/sections/Documents.vue.js.map +1 -1
  89. package/dist/martyrs/src/modules/products/components/elements/Price.vue.cjs +5 -6
  90. package/dist/martyrs/src/modules/products/components/elements/Price.vue.cjs.map +1 -1
  91. package/dist/martyrs/src/modules/products/components/elements/Price.vue.js +5 -6
  92. package/dist/martyrs/src/modules/products/components/elements/Price.vue.js.map +1 -1
  93. package/dist/martyrs/src/modules/products/components/pages/Product.vue.cjs +61 -69
  94. package/dist/martyrs/src/modules/products/components/pages/Product.vue.cjs.map +1 -1
  95. package/dist/martyrs/src/modules/products/components/pages/Product.vue.js +62 -70
  96. package/dist/martyrs/src/modules/products/components/pages/Product.vue.js.map +1 -1
  97. package/dist/martyrs/src/modules/products/store/products.cjs +0 -1
  98. package/dist/martyrs/src/modules/products/store/products.cjs.map +1 -1
  99. package/dist/martyrs/src/modules/products/store/products.js +0 -1
  100. package/dist/martyrs/src/modules/products/store/products.js.map +1 -1
  101. package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.cjs +0 -1
  102. package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.cjs.map +1 -1
  103. package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js +0 -1
  104. package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js.map +1 -1
  105. package/dist/martyrs.cjs.js +1 -1
  106. package/dist/martyrs.css +1 -1
  107. package/dist/martyrs.es.js +1 -1
  108. package/dist/organizations.server.js +0 -1
  109. package/dist/organizations.server.mjs +0 -1
  110. package/dist/products.server.js +5 -0
  111. package/dist/products.server.mjs +5 -0
  112. package/dist/style.css +93 -6
  113. package/package.json +1 -1
  114. package/src/builder/rspack/rspack.config.client.js +5 -0
  115. package/src/components/DatePicker/DatePicker.vue +1 -1
  116. package/src/components/EmptyState/EmptyState.vue +1 -1
  117. package/src/components/Media/Media.vue +1 -1
  118. package/src/components/Popup/Popup.vue +2 -2
  119. package/src/components/Slider/Slider.native.vue +313 -0
  120. package/src/modules/events/components/blocks/CardEvent.vue +21 -7
  121. package/src/modules/events/components/pages/Event.vue +0 -20
  122. package/src/modules/events/components/pages/Events.vue +91 -141
  123. package/src/modules/events/components/pages/EventsBackoffice.vue +5 -3
  124. package/src/modules/events/components/pages/EventsSearch.vue +122 -0
  125. package/src/modules/events/components/sections/EventsHot.vue +3 -5
  126. package/src/modules/events/components/sections/FeaturedEvents.vue +44 -12
  127. package/src/modules/events/components/sections/List.vue +3 -3
  128. package/src/modules/events/components/sections/SelectDate.vue +217 -0
  129. package/src/modules/events/router/events.js +12 -0
  130. package/src/modules/globals/globals.client.js +5 -2
  131. package/src/modules/globals/views/components/layouts/App.vue +7 -1
  132. package/src/modules/globals/views/components/layouts/Client.vue +0 -3
  133. package/src/modules/globals/views/plugins/AlertDialog.vue +35 -0
  134. package/src/modules/globals/views/plugins/alert.plugin.js +65 -0
  135. package/src/modules/organizations/policies/organizations.policies.js +0 -1
  136. package/src/modules/products/components/elements/Price.vue +3 -4
  137. package/src/modules/products/components/pages/Product.old.vue +201 -0
  138. package/src/modules/products/components/pages/Product.vue +57 -38
  139. package/src/modules/products/controllers/products.controller.js +7 -0
  140. package/src/modules/products/store/products.js +0 -1
  141. package/src/styles/base/all.scss +1 -0
  142. package/src/styles/typography.scss +22 -0
@@ -35,8 +35,8 @@ const _sfc_main = {
35
35
  emit("update:date", null);
36
36
  } else {
37
37
  selectedDate.value = date;
38
- const formattedDate = formatDateForRouter(date);
39
- emit("update:date", formattedDate);
38
+ formatDateForRouter(date);
39
+ emit("update:date", date);
40
40
  }
41
41
  }
42
42
  function isHighlighted(date) {
@@ -1 +1 @@
1
- {"version":3,"file":"DatePicker.vue.cjs","sources":["../../../../../src/components/DatePicker/DatePicker.vue"],"sourcesContent":["<template>\n <div>\n <div \n class=\"w-100 scroller o-scroll scroll-snap-type-x-mandatory scroll-pd-regular scroll-hide flex-nowrap flex\" \n ref=\"scrollContainer\"\n >\n <div \n v-for=\"date in dates\" \n :key=\"date.toString()\" \n @click=\"selectDate(date)\"\n :class=\"{\n 'selected': selectedDate && selectedDate.toDateString() === date.toDateString(),\n 'highlighted': isHighlighted(date)\n }\"\n class=\"cursor-pointer scroll-snap-align-start mn-r-small mn-l-small flex-column flex-center flex\"\n >\n <span class=\"t-transp\">\n {{ dayLetter(date) }}\n </span>\n <span \n :class=\"{\n 'bg-main': selectedDate && selectedDate.toDateString() === date.toDateString(),\n 'br-1px br-solid br-main':isHighlighted(date),\n }\"\n class=\"transition-ease-in-out t-semi flex-center flex radius-big i-semi day-number\"\n >\n {{ date.getDate() }}\n </span>\n </div>\n </div>\n </div>\n</template>\n\n<script setup>\nimport { ref, onMounted, defineProps, defineEmits } from 'vue';\n\nconst emit = defineEmits();\nconst props = defineProps(['date', 'options','locale']);\n\nconst scrollContainer = ref(null);\n\n// Initialize base date for generating the date range\nconst baseDate = new Date();\nbaseDate.setHours(0, 0, 0, 0);\n\n// Initialize selectedDate as null or with provided date\nconst selectedDate = ref(null);\n\nif (props.date) {\n const day = parseInt(props.date.substring(0, 2));\n const month = parseInt(props.date.substring(2, 4)) - 1;\n const year = parseInt(props.date.substring(4));\n\n selectedDate.value = new Date(year, month, day);\n selectedDate.value.setHours(0, 0, 0, 0);\n}\n\nconst dates = generateDates(baseDate, props.options.dateEnd || 30);\n\nonMounted(() => {\n if (scrollContainer.value) {\n const target = scrollContainer.value.getElementsByClassName('selected')[0] || \n scrollContainer.value.getElementsByClassName('bg-main')[0] || \n scrollContainer.value.getElementsByClassName('highlighted')[0];\n if (target) {\n scrollContainer.value.scrollLeft = target.offsetLeft - \n scrollContainer.value.offsetWidth / 2 + target.offsetWidth / 2;\n }\n }\n});\n\nfunction selectDate(date) {\n if (selectedDate.value && selectedDate.value.toDateString() === date.toDateString()) {\n // If clicking the same date, reset selection\n selectedDate.value = null;\n emit('update:date', null);\n } else {\n // Select new date\n selectedDate.value = date;\n const formattedDate = formatDateForRouter(date);\n emit('update:date', formattedDate);\n }\n}\n\nfunction isHighlighted(date) {\n return selectedDate.value === null && date.toDateString() === baseDate.toDateString();\n}\n\nfunction formatDateForRouter(date) {\n return `${date.getDate().toString().padStart(2, '0')}${(date.getMonth() + 1)\n .toString().padStart(2, '0')}${date.getFullYear()}`;\n}\n\nfunction dayLetter(date) {\n return date.toLocaleDateString(props.locale ? props.locale : 'en', { \n weekday: 'narrow' \n }).toUpperCase();\n}\n\nfunction generateDates(start, count) {\n const dates = [];\n for (let i = props.options.dateStart || 0; i < count - props.options.dateStart || 0; i++) {\n const newDate = new Date(start);\n newDate.setDate(start.getDate() + i);\n newDate.setHours(0, 0, 0, 0);\n dates.push(newDate);\n }\n return dates;\n}\n</script>"],"names":["ref","onMounted","dates"],"mappings":";;;;;;;;;AAoCA,UAAM,OAAO;AACb,UAAM,QAAQ;AAEd,UAAM,kBAAkBA,IAAG,IAAC,IAAI;AAGhC,UAAM,WAAW,oBAAI,KAAM;AAC3B,aAAS,SAAS,GAAG,GAAG,GAAG,CAAC;AAG5B,UAAM,eAAeA,IAAG,IAAC,IAAI;AAE7B,QAAI,MAAM,MAAM;AACd,YAAM,MAAM,SAAS,MAAM,KAAK,UAAU,GAAG,CAAC,CAAC;AAC/C,YAAM,QAAQ,SAAS,MAAM,KAAK,UAAU,GAAG,CAAC,CAAC,IAAI;AACrD,YAAM,OAAO,SAAS,MAAM,KAAK,UAAU,CAAC,CAAC;AAE7C,mBAAa,QAAQ,IAAI,KAAK,MAAM,OAAO,GAAG;AAC9C,mBAAa,MAAM,SAAS,GAAG,GAAG,GAAG,CAAC;AAAA,IACxC;AAEA,UAAM,QAAQ,cAAc,UAAU,MAAM,QAAQ,WAAW,EAAE;AAEjEC,QAAAA,UAAU,MAAM;AACd,UAAI,gBAAgB,OAAO;AACzB,cAAM,SAAS,gBAAgB,MAAM,uBAAuB,UAAU,EAAE,CAAC,KAC3D,gBAAgB,MAAM,uBAAuB,SAAS,EAAE,CAAC,KACzD,gBAAgB,MAAM,uBAAuB,aAAa,EAAE,CAAC;AAC3E,YAAI,QAAQ;AACV,0BAAgB,MAAM,aAAa,OAAO,aACxC,gBAAgB,MAAM,cAAc,IAAI,OAAO,cAAc;AAAA,QACrE;AAAA,MACA;AAAA,IACA,CAAC;AAED,aAAS,WAAW,MAAM;AACxB,UAAI,aAAa,SAAS,aAAa,MAAM,mBAAmB,KAAK,gBAAgB;AAEnF,qBAAa,QAAQ;AACrB,aAAK,eAAe,IAAI;AAAA,MAC5B,OAAS;AAEL,qBAAa,QAAQ;AACrB,cAAM,gBAAgB,oBAAoB,IAAI;AAC9C,aAAK,eAAe,aAAa;AAAA,MACrC;AAAA,IACA;AAEA,aAAS,cAAc,MAAM;AAC3B,aAAO,aAAa,UAAU,QAAQ,KAAK,aAAc,MAAK,SAAS,aAAc;AAAA,IACvF;AAEA,aAAS,oBAAoB,MAAM;AACjC,aAAO,GAAG,KAAK,QAAS,EAAC,SAAQ,EAAG,SAAS,GAAG,GAAG,CAAC,IAAI,KAAK,SAAU,IAAG,GACvE,SAAU,EAAC,SAAS,GAAG,GAAG,CAAC,GAAG,KAAK,YAAW,CAAE;AAAA,IACrD;AAEA,aAAS,UAAU,MAAM;AACvB,aAAO,KAAK,mBAAmB,MAAM,SAAS,MAAM,SAAS,MAAM;AAAA,QACjE,SAAS;AAAA,MACV,CAAA,EAAE,YAAa;AAAA,IAClB;AAEA,aAAS,cAAc,OAAO,OAAO;AACnC,YAAMC,SAAQ,CAAE;AAChB,eAAS,IAAI,MAAM,QAAQ,aAAa,GAAG,IAAI,QAAQ,MAAM,QAAQ,aAAa,GAAG,KAAK;AACxF,cAAM,UAAU,IAAI,KAAK,KAAK;AAC9B,gBAAQ,QAAQ,MAAM,QAAO,IAAK,CAAC;AACnC,gBAAQ,SAAS,GAAG,GAAG,GAAG,CAAC;AAC3B,QAAAA,OAAM,KAAK,OAAO;AAAA,MACtB;AACE,aAAOA;AAAA,IACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"DatePicker.vue.cjs","sources":["../../../../../src/components/DatePicker/DatePicker.vue"],"sourcesContent":["<template>\n <div>\n <div \n class=\"w-100 scroller o-scroll scroll-snap-type-x-mandatory scroll-pd-regular scroll-hide flex-nowrap flex\" \n ref=\"scrollContainer\"\n >\n <div \n v-for=\"date in dates\" \n :key=\"date.toString()\" \n @click=\"selectDate(date)\"\n :class=\"{\n 'selected': selectedDate && selectedDate.toDateString() === date.toDateString(),\n 'highlighted': isHighlighted(date)\n }\"\n class=\"cursor-pointer scroll-snap-align-start mn-r-small mn-l-small flex-column flex-center flex\"\n >\n <span class=\"t-transp\">\n {{ dayLetter(date) }}\n </span>\n <span \n :class=\"{\n 'bg-main': selectedDate && selectedDate.toDateString() === date.toDateString(),\n 'br-1px br-solid br-main':isHighlighted(date),\n }\"\n class=\"transition-ease-in-out t-semi flex-center flex radius-big i-semi day-number\"\n >\n {{ date.getDate() }}\n </span>\n </div>\n </div>\n </div>\n</template>\n\n<script setup>\nimport { ref, onMounted, defineProps, defineEmits } from 'vue';\n\nconst emit = defineEmits();\nconst props = defineProps(['date', 'options','locale']);\n\nconst scrollContainer = ref(null);\n\n// Initialize base date for generating the date range\nconst baseDate = new Date();\nbaseDate.setHours(0, 0, 0, 0);\n\n// Initialize selectedDate as null or with provided date\nconst selectedDate = ref(null);\n\nif (props.date) {\n const day = parseInt(props.date.substring(0, 2));\n const month = parseInt(props.date.substring(2, 4)) - 1;\n const year = parseInt(props.date.substring(4));\n\n selectedDate.value = new Date(year, month, day);\n selectedDate.value.setHours(0, 0, 0, 0);\n}\n\nconst dates = generateDates(baseDate, props.options.dateEnd || 30);\n\nonMounted(() => {\n if (scrollContainer.value) {\n const target = scrollContainer.value.getElementsByClassName('selected')[0] || \n scrollContainer.value.getElementsByClassName('bg-main')[0] || \n scrollContainer.value.getElementsByClassName('highlighted')[0];\n if (target) {\n scrollContainer.value.scrollLeft = target.offsetLeft - \n scrollContainer.value.offsetWidth / 2 + target.offsetWidth / 2;\n }\n }\n});\n\nfunction selectDate(date) {\n if (selectedDate.value && selectedDate.value.toDateString() === date.toDateString()) {\n // If clicking the same date, reset selection\n selectedDate.value = null;\n emit('update:date', null);\n } else {\n // Select new date\n selectedDate.value = date;\n const formattedDate = formatDateForRouter(date);\n emit('update:date', date);\n }\n}\n\nfunction isHighlighted(date) {\n return selectedDate.value === null && date.toDateString() === baseDate.toDateString();\n}\n\nfunction formatDateForRouter(date) {\n return `${date.getDate().toString().padStart(2, '0')}${(date.getMonth() + 1)\n .toString().padStart(2, '0')}${date.getFullYear()}`;\n}\n\nfunction dayLetter(date) {\n return date.toLocaleDateString(props.locale ? props.locale : 'en', { \n weekday: 'narrow' \n }).toUpperCase();\n}\n\nfunction generateDates(start, count) {\n const dates = [];\n for (let i = props.options.dateStart || 0; i < count - props.options.dateStart || 0; i++) {\n const newDate = new Date(start);\n newDate.setDate(start.getDate() + i);\n newDate.setHours(0, 0, 0, 0);\n dates.push(newDate);\n }\n return dates;\n}\n</script>"],"names":["ref","onMounted","dates"],"mappings":";;;;;;;;;AAoCA,UAAM,OAAO;AACb,UAAM,QAAQ;AAEd,UAAM,kBAAkBA,IAAG,IAAC,IAAI;AAGhC,UAAM,WAAW,oBAAI,KAAM;AAC3B,aAAS,SAAS,GAAG,GAAG,GAAG,CAAC;AAG5B,UAAM,eAAeA,IAAG,IAAC,IAAI;AAE7B,QAAI,MAAM,MAAM;AACd,YAAM,MAAM,SAAS,MAAM,KAAK,UAAU,GAAG,CAAC,CAAC;AAC/C,YAAM,QAAQ,SAAS,MAAM,KAAK,UAAU,GAAG,CAAC,CAAC,IAAI;AACrD,YAAM,OAAO,SAAS,MAAM,KAAK,UAAU,CAAC,CAAC;AAE7C,mBAAa,QAAQ,IAAI,KAAK,MAAM,OAAO,GAAG;AAC9C,mBAAa,MAAM,SAAS,GAAG,GAAG,GAAG,CAAC;AAAA,IACxC;AAEA,UAAM,QAAQ,cAAc,UAAU,MAAM,QAAQ,WAAW,EAAE;AAEjEC,QAAAA,UAAU,MAAM;AACd,UAAI,gBAAgB,OAAO;AACzB,cAAM,SAAS,gBAAgB,MAAM,uBAAuB,UAAU,EAAE,CAAC,KAC3D,gBAAgB,MAAM,uBAAuB,SAAS,EAAE,CAAC,KACzD,gBAAgB,MAAM,uBAAuB,aAAa,EAAE,CAAC;AAC3E,YAAI,QAAQ;AACV,0BAAgB,MAAM,aAAa,OAAO,aACxC,gBAAgB,MAAM,cAAc,IAAI,OAAO,cAAc;AAAA,QACrE;AAAA,MACA;AAAA,IACA,CAAC;AAED,aAAS,WAAW,MAAM;AACxB,UAAI,aAAa,SAAS,aAAa,MAAM,mBAAmB,KAAK,gBAAgB;AAEnF,qBAAa,QAAQ;AACrB,aAAK,eAAe,IAAI;AAAA,MAC5B,OAAS;AAEL,qBAAa,QAAQ;AACC,4BAAoB,IAAI;AAC9C,aAAK,eAAe,IAAI;AAAA,MAC5B;AAAA,IACA;AAEA,aAAS,cAAc,MAAM;AAC3B,aAAO,aAAa,UAAU,QAAQ,KAAK,aAAc,MAAK,SAAS,aAAc;AAAA,IACvF;AAEA,aAAS,oBAAoB,MAAM;AACjC,aAAO,GAAG,KAAK,QAAS,EAAC,SAAQ,EAAG,SAAS,GAAG,GAAG,CAAC,IAAI,KAAK,SAAU,IAAG,GACvE,SAAU,EAAC,SAAS,GAAG,GAAG,CAAC,GAAG,KAAK,YAAW,CAAE;AAAA,IACrD;AAEA,aAAS,UAAU,MAAM;AACvB,aAAO,KAAK,mBAAmB,MAAM,SAAS,MAAM,SAAS,MAAM;AAAA,QACjE,SAAS;AAAA,MACV,CAAA,EAAE,YAAa;AAAA,IAClB;AAEA,aAAS,cAAc,OAAO,OAAO;AACnC,YAAMC,SAAQ,CAAE;AAChB,eAAS,IAAI,MAAM,QAAQ,aAAa,GAAG,IAAI,QAAQ,MAAM,QAAQ,aAAa,GAAG,KAAK;AACxF,cAAM,UAAU,IAAI,KAAK,KAAK;AAC9B,gBAAQ,QAAQ,MAAM,QAAO,IAAK,CAAC;AACnC,gBAAQ,SAAS,GAAG,GAAG,GAAG,CAAC;AAC3B,QAAAA,OAAM,KAAK,OAAO;AAAA,MACtB;AACE,aAAOA;AAAA,IACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -33,8 +33,8 @@ const _sfc_main = {
33
33
  emit("update:date", null);
34
34
  } else {
35
35
  selectedDate.value = date;
36
- const formattedDate = formatDateForRouter(date);
37
- emit("update:date", formattedDate);
36
+ formatDateForRouter(date);
37
+ emit("update:date", date);
38
38
  }
39
39
  }
40
40
  function isHighlighted(date) {
@@ -1 +1 @@
1
- {"version":3,"file":"DatePicker.vue.js","sources":["../../../../../src/components/DatePicker/DatePicker.vue"],"sourcesContent":["<template>\n <div>\n <div \n class=\"w-100 scroller o-scroll scroll-snap-type-x-mandatory scroll-pd-regular scroll-hide flex-nowrap flex\" \n ref=\"scrollContainer\"\n >\n <div \n v-for=\"date in dates\" \n :key=\"date.toString()\" \n @click=\"selectDate(date)\"\n :class=\"{\n 'selected': selectedDate && selectedDate.toDateString() === date.toDateString(),\n 'highlighted': isHighlighted(date)\n }\"\n class=\"cursor-pointer scroll-snap-align-start mn-r-small mn-l-small flex-column flex-center flex\"\n >\n <span class=\"t-transp\">\n {{ dayLetter(date) }}\n </span>\n <span \n :class=\"{\n 'bg-main': selectedDate && selectedDate.toDateString() === date.toDateString(),\n 'br-1px br-solid br-main':isHighlighted(date),\n }\"\n class=\"transition-ease-in-out t-semi flex-center flex radius-big i-semi day-number\"\n >\n {{ date.getDate() }}\n </span>\n </div>\n </div>\n </div>\n</template>\n\n<script setup>\nimport { ref, onMounted, defineProps, defineEmits } from 'vue';\n\nconst emit = defineEmits();\nconst props = defineProps(['date', 'options','locale']);\n\nconst scrollContainer = ref(null);\n\n// Initialize base date for generating the date range\nconst baseDate = new Date();\nbaseDate.setHours(0, 0, 0, 0);\n\n// Initialize selectedDate as null or with provided date\nconst selectedDate = ref(null);\n\nif (props.date) {\n const day = parseInt(props.date.substring(0, 2));\n const month = parseInt(props.date.substring(2, 4)) - 1;\n const year = parseInt(props.date.substring(4));\n\n selectedDate.value = new Date(year, month, day);\n selectedDate.value.setHours(0, 0, 0, 0);\n}\n\nconst dates = generateDates(baseDate, props.options.dateEnd || 30);\n\nonMounted(() => {\n if (scrollContainer.value) {\n const target = scrollContainer.value.getElementsByClassName('selected')[0] || \n scrollContainer.value.getElementsByClassName('bg-main')[0] || \n scrollContainer.value.getElementsByClassName('highlighted')[0];\n if (target) {\n scrollContainer.value.scrollLeft = target.offsetLeft - \n scrollContainer.value.offsetWidth / 2 + target.offsetWidth / 2;\n }\n }\n});\n\nfunction selectDate(date) {\n if (selectedDate.value && selectedDate.value.toDateString() === date.toDateString()) {\n // If clicking the same date, reset selection\n selectedDate.value = null;\n emit('update:date', null);\n } else {\n // Select new date\n selectedDate.value = date;\n const formattedDate = formatDateForRouter(date);\n emit('update:date', formattedDate);\n }\n}\n\nfunction isHighlighted(date) {\n return selectedDate.value === null && date.toDateString() === baseDate.toDateString();\n}\n\nfunction formatDateForRouter(date) {\n return `${date.getDate().toString().padStart(2, '0')}${(date.getMonth() + 1)\n .toString().padStart(2, '0')}${date.getFullYear()}`;\n}\n\nfunction dayLetter(date) {\n return date.toLocaleDateString(props.locale ? props.locale : 'en', { \n weekday: 'narrow' \n }).toUpperCase();\n}\n\nfunction generateDates(start, count) {\n const dates = [];\n for (let i = props.options.dateStart || 0; i < count - props.options.dateStart || 0; i++) {\n const newDate = new Date(start);\n newDate.setDate(start.getDate() + i);\n newDate.setHours(0, 0, 0, 0);\n dates.push(newDate);\n }\n return dates;\n}\n</script>"],"names":["dates"],"mappings":";;;;;;;AAoCA,UAAM,OAAO;AACb,UAAM,QAAQ;AAEd,UAAM,kBAAkB,IAAI,IAAI;AAGhC,UAAM,WAAW,oBAAI,KAAM;AAC3B,aAAS,SAAS,GAAG,GAAG,GAAG,CAAC;AAG5B,UAAM,eAAe,IAAI,IAAI;AAE7B,QAAI,MAAM,MAAM;AACd,YAAM,MAAM,SAAS,MAAM,KAAK,UAAU,GAAG,CAAC,CAAC;AAC/C,YAAM,QAAQ,SAAS,MAAM,KAAK,UAAU,GAAG,CAAC,CAAC,IAAI;AACrD,YAAM,OAAO,SAAS,MAAM,KAAK,UAAU,CAAC,CAAC;AAE7C,mBAAa,QAAQ,IAAI,KAAK,MAAM,OAAO,GAAG;AAC9C,mBAAa,MAAM,SAAS,GAAG,GAAG,GAAG,CAAC;AAAA,IACxC;AAEA,UAAM,QAAQ,cAAc,UAAU,MAAM,QAAQ,WAAW,EAAE;AAEjE,cAAU,MAAM;AACd,UAAI,gBAAgB,OAAO;AACzB,cAAM,SAAS,gBAAgB,MAAM,uBAAuB,UAAU,EAAE,CAAC,KAC3D,gBAAgB,MAAM,uBAAuB,SAAS,EAAE,CAAC,KACzD,gBAAgB,MAAM,uBAAuB,aAAa,EAAE,CAAC;AAC3E,YAAI,QAAQ;AACV,0BAAgB,MAAM,aAAa,OAAO,aACxC,gBAAgB,MAAM,cAAc,IAAI,OAAO,cAAc;AAAA,QACrE;AAAA,MACA;AAAA,IACA,CAAC;AAED,aAAS,WAAW,MAAM;AACxB,UAAI,aAAa,SAAS,aAAa,MAAM,mBAAmB,KAAK,gBAAgB;AAEnF,qBAAa,QAAQ;AACrB,aAAK,eAAe,IAAI;AAAA,MAC5B,OAAS;AAEL,qBAAa,QAAQ;AACrB,cAAM,gBAAgB,oBAAoB,IAAI;AAC9C,aAAK,eAAe,aAAa;AAAA,MACrC;AAAA,IACA;AAEA,aAAS,cAAc,MAAM;AAC3B,aAAO,aAAa,UAAU,QAAQ,KAAK,aAAc,MAAK,SAAS,aAAc;AAAA,IACvF;AAEA,aAAS,oBAAoB,MAAM;AACjC,aAAO,GAAG,KAAK,QAAS,EAAC,SAAQ,EAAG,SAAS,GAAG,GAAG,CAAC,IAAI,KAAK,SAAU,IAAG,GACvE,SAAU,EAAC,SAAS,GAAG,GAAG,CAAC,GAAG,KAAK,YAAW,CAAE;AAAA,IACrD;AAEA,aAAS,UAAU,MAAM;AACvB,aAAO,KAAK,mBAAmB,MAAM,SAAS,MAAM,SAAS,MAAM;AAAA,QACjE,SAAS;AAAA,MACV,CAAA,EAAE,YAAa;AAAA,IAClB;AAEA,aAAS,cAAc,OAAO,OAAO;AACnC,YAAMA,SAAQ,CAAE;AAChB,eAAS,IAAI,MAAM,QAAQ,aAAa,GAAG,IAAI,QAAQ,MAAM,QAAQ,aAAa,GAAG,KAAK;AACxF,cAAM,UAAU,IAAI,KAAK,KAAK;AAC9B,gBAAQ,QAAQ,MAAM,QAAO,IAAK,CAAC;AACnC,gBAAQ,SAAS,GAAG,GAAG,GAAG,CAAC;AAC3B,QAAAA,OAAM,KAAK,OAAO;AAAA,MACtB;AACE,aAAOA;AAAA,IACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"DatePicker.vue.js","sources":["../../../../../src/components/DatePicker/DatePicker.vue"],"sourcesContent":["<template>\n <div>\n <div \n class=\"w-100 scroller o-scroll scroll-snap-type-x-mandatory scroll-pd-regular scroll-hide flex-nowrap flex\" \n ref=\"scrollContainer\"\n >\n <div \n v-for=\"date in dates\" \n :key=\"date.toString()\" \n @click=\"selectDate(date)\"\n :class=\"{\n 'selected': selectedDate && selectedDate.toDateString() === date.toDateString(),\n 'highlighted': isHighlighted(date)\n }\"\n class=\"cursor-pointer scroll-snap-align-start mn-r-small mn-l-small flex-column flex-center flex\"\n >\n <span class=\"t-transp\">\n {{ dayLetter(date) }}\n </span>\n <span \n :class=\"{\n 'bg-main': selectedDate && selectedDate.toDateString() === date.toDateString(),\n 'br-1px br-solid br-main':isHighlighted(date),\n }\"\n class=\"transition-ease-in-out t-semi flex-center flex radius-big i-semi day-number\"\n >\n {{ date.getDate() }}\n </span>\n </div>\n </div>\n </div>\n</template>\n\n<script setup>\nimport { ref, onMounted, defineProps, defineEmits } from 'vue';\n\nconst emit = defineEmits();\nconst props = defineProps(['date', 'options','locale']);\n\nconst scrollContainer = ref(null);\n\n// Initialize base date for generating the date range\nconst baseDate = new Date();\nbaseDate.setHours(0, 0, 0, 0);\n\n// Initialize selectedDate as null or with provided date\nconst selectedDate = ref(null);\n\nif (props.date) {\n const day = parseInt(props.date.substring(0, 2));\n const month = parseInt(props.date.substring(2, 4)) - 1;\n const year = parseInt(props.date.substring(4));\n\n selectedDate.value = new Date(year, month, day);\n selectedDate.value.setHours(0, 0, 0, 0);\n}\n\nconst dates = generateDates(baseDate, props.options.dateEnd || 30);\n\nonMounted(() => {\n if (scrollContainer.value) {\n const target = scrollContainer.value.getElementsByClassName('selected')[0] || \n scrollContainer.value.getElementsByClassName('bg-main')[0] || \n scrollContainer.value.getElementsByClassName('highlighted')[0];\n if (target) {\n scrollContainer.value.scrollLeft = target.offsetLeft - \n scrollContainer.value.offsetWidth / 2 + target.offsetWidth / 2;\n }\n }\n});\n\nfunction selectDate(date) {\n if (selectedDate.value && selectedDate.value.toDateString() === date.toDateString()) {\n // If clicking the same date, reset selection\n selectedDate.value = null;\n emit('update:date', null);\n } else {\n // Select new date\n selectedDate.value = date;\n const formattedDate = formatDateForRouter(date);\n emit('update:date', date);\n }\n}\n\nfunction isHighlighted(date) {\n return selectedDate.value === null && date.toDateString() === baseDate.toDateString();\n}\n\nfunction formatDateForRouter(date) {\n return `${date.getDate().toString().padStart(2, '0')}${(date.getMonth() + 1)\n .toString().padStart(2, '0')}${date.getFullYear()}`;\n}\n\nfunction dayLetter(date) {\n return date.toLocaleDateString(props.locale ? props.locale : 'en', { \n weekday: 'narrow' \n }).toUpperCase();\n}\n\nfunction generateDates(start, count) {\n const dates = [];\n for (let i = props.options.dateStart || 0; i < count - props.options.dateStart || 0; i++) {\n const newDate = new Date(start);\n newDate.setDate(start.getDate() + i);\n newDate.setHours(0, 0, 0, 0);\n dates.push(newDate);\n }\n return dates;\n}\n</script>"],"names":["dates"],"mappings":";;;;;;;AAoCA,UAAM,OAAO;AACb,UAAM,QAAQ;AAEd,UAAM,kBAAkB,IAAI,IAAI;AAGhC,UAAM,WAAW,oBAAI,KAAM;AAC3B,aAAS,SAAS,GAAG,GAAG,GAAG,CAAC;AAG5B,UAAM,eAAe,IAAI,IAAI;AAE7B,QAAI,MAAM,MAAM;AACd,YAAM,MAAM,SAAS,MAAM,KAAK,UAAU,GAAG,CAAC,CAAC;AAC/C,YAAM,QAAQ,SAAS,MAAM,KAAK,UAAU,GAAG,CAAC,CAAC,IAAI;AACrD,YAAM,OAAO,SAAS,MAAM,KAAK,UAAU,CAAC,CAAC;AAE7C,mBAAa,QAAQ,IAAI,KAAK,MAAM,OAAO,GAAG;AAC9C,mBAAa,MAAM,SAAS,GAAG,GAAG,GAAG,CAAC;AAAA,IACxC;AAEA,UAAM,QAAQ,cAAc,UAAU,MAAM,QAAQ,WAAW,EAAE;AAEjE,cAAU,MAAM;AACd,UAAI,gBAAgB,OAAO;AACzB,cAAM,SAAS,gBAAgB,MAAM,uBAAuB,UAAU,EAAE,CAAC,KAC3D,gBAAgB,MAAM,uBAAuB,SAAS,EAAE,CAAC,KACzD,gBAAgB,MAAM,uBAAuB,aAAa,EAAE,CAAC;AAC3E,YAAI,QAAQ;AACV,0BAAgB,MAAM,aAAa,OAAO,aACxC,gBAAgB,MAAM,cAAc,IAAI,OAAO,cAAc;AAAA,QACrE;AAAA,MACA;AAAA,IACA,CAAC;AAED,aAAS,WAAW,MAAM;AACxB,UAAI,aAAa,SAAS,aAAa,MAAM,mBAAmB,KAAK,gBAAgB;AAEnF,qBAAa,QAAQ;AACrB,aAAK,eAAe,IAAI;AAAA,MAC5B,OAAS;AAEL,qBAAa,QAAQ;AACC,4BAAoB,IAAI;AAC9C,aAAK,eAAe,IAAI;AAAA,MAC5B;AAAA,IACA;AAEA,aAAS,cAAc,MAAM;AAC3B,aAAO,aAAa,UAAU,QAAQ,KAAK,aAAc,MAAK,SAAS,aAAc;AAAA,IACvF;AAEA,aAAS,oBAAoB,MAAM;AACjC,aAAO,GAAG,KAAK,QAAS,EAAC,SAAQ,EAAG,SAAS,GAAG,GAAG,CAAC,IAAI,KAAK,SAAU,IAAG,GACvE,SAAU,EAAC,SAAS,GAAG,GAAG,CAAC,GAAG,KAAK,YAAW,CAAE;AAAA,IACrD;AAEA,aAAS,UAAU,MAAM;AACvB,aAAO,KAAK,mBAAmB,MAAM,SAAS,MAAM,SAAS,MAAM;AAAA,QACjE,SAAS;AAAA,MACV,CAAA,EAAE,YAAa;AAAA,IAClB;AAEA,aAAS,cAAc,OAAO,OAAO;AACnC,YAAMA,SAAQ,CAAE;AAChB,eAAS,IAAI,MAAM,QAAQ,aAAa,GAAG,IAAI,QAAQ,MAAM,QAAQ,aAAa,GAAG,KAAK;AACxF,cAAM,UAAU,IAAI,KAAK,KAAK;AAC9B,gBAAQ,QAAQ,MAAM,QAAO,IAAK,CAAC;AACnC,gBAAQ,SAAS,GAAG,GAAG,GAAG,CAAC;AAC3B,QAAAA,OAAM,KAAK,OAAO;AAAA,MACtB;AACE,aAAOA;AAAA,IACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -26,7 +26,7 @@ const _sfc_main = {
26
26
  setup(__props) {
27
27
  return (_ctx, _cache) => {
28
28
  return vue.openBlock(), vue.createElementBlock("section", null, [
29
- vue.createElementVNode("h4", _hoisted_1, vue.toDisplayString(__props.title), 1),
29
+ vue.createElementVNode("h5", _hoisted_1, vue.toDisplayString(__props.title), 1),
30
30
  vue.createElementVNode("p", _hoisted_2, vue.toDisplayString(__props.description), 1),
31
31
  __props.action ? (vue.openBlock(), vue.createElementBlock("button", {
32
32
  key: 0,
@@ -24,7 +24,7 @@ const _sfc_main = {
24
24
  setup(__props) {
25
25
  return (_ctx, _cache) => {
26
26
  return openBlock(), createElementBlock("section", null, [
27
- createElementVNode("h4", _hoisted_1, toDisplayString(__props.title), 1),
27
+ createElementVNode("h5", _hoisted_1, toDisplayString(__props.title), 1),
28
28
  createElementVNode("p", _hoisted_2, toDisplayString(__props.description), 1),
29
29
  __props.action ? (openBlock(), createElementBlock("button", {
30
30
  key: 0,
@@ -142,12 +142,12 @@ const _sfc_main = {
142
142
  type: videoType.value
143
143
  }, null, 8, _hoisted_4)
144
144
  ], 16, _hoisted_3)) : vue.createCommentVNode("", true),
145
- !isLoaded.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_5, " Загрузка... ")) : vue.createCommentVNode("", true),
145
+ !isLoaded.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_5, " Loading... ")) : vue.createCommentVNode("", true),
146
146
  error.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_6, vue.toDisplayString(error.value), 1)) : vue.createCommentVNode("", true)
147
147
  ]);
148
148
  };
149
149
  }
150
150
  };
151
- const Media = /* @__PURE__ */ _pluginVue_exportHelper.default(_sfc_main, [["__scopeId", "data-v-94bcf726"]]);
151
+ const Media = /* @__PURE__ */ _pluginVue_exportHelper.default(_sfc_main, [["__scopeId", "data-v-1f94a0e9"]]);
152
152
  exports.default = Media;
153
153
  //# sourceMappingURL=Media.vue.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Media.vue.cjs","sources":["../../../../../src/components/Media/Media.vue"],"sourcesContent":["<template>\n <div class=\"media-container\">\n <!-- Изображение с ленивой загрузкой и placeholder -->\n <img\n v-if=\"isImage\"\n :src=\"isIntersecting ? url : ''\"\n :data-src=\"url\"\n :alt=\"options?.alt || 'Image'\"\n class=\"media-item\"\n :class=\"{ 'loading': !isLoaded }\"\n loading=\"lazy\"\n @load=\"handleLoad\"\n v-bind=\"options\"\n ref=\"imageElement\"\n />\n \n <!-- Видео с предварительной загрузкой -->\n <video\n v-else-if=\"isVideo\"\n ref=\"videoElement\"\n :class=\"{ 'loading': !isLoaded }\"\n class=\"media-item\"\n :controls=\"!options?.hideControls\"\n :loop=\"options?.loop !== false\"\n :muted=\"options?.muted !== false\"\n :autoplay=\"options?.autoplay\"\n :playsinline=\"options?.playsinline !== false\"\n :preload=\"options?.preload || 'metadata'\"\n @loadeddata=\"handleLoad\"\n v-bind=\"options\"\n >\n <source :src=\"url\" :type=\"videoType\">\n </video>\n \n <!-- Плейсхолдер во время загрузки -->\n <div v-if=\"!isLoaded\" class=\"media-placeholder\">\n Загрузка...\n </div>\n \n <!-- Сообщение об ошибке -->\n <div v-if=\"error\" class=\"media-error\">\n {{ error }}\n </div>\n </div>\n</template>\n\n<script setup>\nimport { ref, onMounted, computed, onUnmounted } from 'vue'\n\nconst props = defineProps({\n url: {\n type: String,\n required: true\n },\n options: {\n type: Object,\n default: () => ({\n muted: true,\n loop: true,\n playsinline: true,\n preload: 'metadata' // 'none' | 'metadata' | 'auto'\n })\n }\n})\n\n// Refs\nconst videoElement = ref(null)\nconst imageElement = ref(null)\nconst isLoaded = ref(false)\nconst error = ref(null)\nconst isIntersecting = ref(false)\nlet observer = null\nlet isPlaying = false\n\n// Определяем тип медиа\nconst fileExtension = computed(() => {\n return props.url?.split('.')?.pop()?.toLowerCase()\n})\n\nconst isImage = computed(() => {\n const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'avif']\n return imageExtensions.includes(fileExtension.value)\n})\n\nconst isVideo = computed(() => {\n const videoExtensions = ['mp4', 'webm', 'ogg']\n return videoExtensions.includes(fileExtension.value)\n})\n\n// Определяем MIME-тип для видео\nconst videoType = computed(() => {\n const types = {\n 'mp4': 'video/mp4',\n 'webm': 'video/webm',\n 'ogg': 'video/ogg'\n }\n return types[fileExtension.value] || ''\n})\n\n// Обработчик загрузки медиа\nfunction handleLoad() {\n isLoaded.value = true\n}\n\n// Обработка ошибок\nfunction handleError(err) {\n error.value = `Ошибка загрузки медиа: ${err.message}`\n isLoaded.value = false\n}\n\n// Управление видео с обработкой ошибок\nasync function playVideo() {\n if (!videoElement.value) return\n \n try {\n if (videoElement.value.paused && !isPlaying) {\n await videoElement.value.play()\n isPlaying = true\n }\n } catch (err) {\n handleError(err)\n }\n}\n\nfunction checkAndPlayVideo() {\n if (!videoElement.value) return\n \n videoElement.value.onplaying = () => {\n isPlaying = true\n }\n \n videoElement.value.onpause = () => {\n isPlaying = false\n }\n \n videoElement.value.onerror = handleError\n}\n\n// Intersection Observer для ленивой загрузки\nfunction setupIntersectionObserver() {\n const options = {\n root: null,\n rootMargin: '50px',\n threshold: 0.1\n }\n \n observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n isIntersecting.value = entry.isIntersecting\n \n if (entry.isIntersecting) {\n if (isVideo.value && props.options?.autoplay) {\n playVideo()\n }\n // Отключаем observer после первой загрузки\n observer.disconnect()\n }\n })\n }, options)\n \n // Наблюдаем за элементом в зависимости от типа медиа\n const element = isImage.value ? imageElement.value : videoElement.value\n if (element) {\n observer.observe(element)\n }\n}\n\n// Lifecycle hooks\nonMounted(() => {\n setupIntersectionObserver()\n})\n\nonUnmounted(() => {\n if (observer) {\n observer.disconnect()\n }\n})\n</script>\n\n<style scoped>\n.media-container {\n}\n\n.media-item {\n all: inherit;\n opacity: 1;\n transition: opacity 0.3s ease;\n}\n\n.media-item.loading {\n opacity: 0;\n}\n\n.media-placeholder {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: #f5f5f5;\n}\n\n.media-error {\n color: #ff4444;\n padding: 1rem;\n text-align: center;\n}\n</style>"],"names":["ref","computed","onMounted","onUnmounted"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,UAAM,QAAQ;AAiBd,UAAM,eAAeA,IAAG,IAAC,IAAI;AAC7B,UAAM,eAAeA,IAAG,IAAC,IAAI;AAC7B,UAAM,WAAWA,IAAG,IAAC,KAAK;AAC1B,UAAM,QAAQA,IAAG,IAAC,IAAI;AACtB,UAAM,iBAAiBA,IAAG,IAAC,KAAK;AAChC,QAAI,WAAW;AACf,QAAI,YAAY;AAGhB,UAAM,gBAAgBC,IAAQ,SAAC,MAAM;;AACnC,cAAO,uBAAM,QAAN,mBAAW,MAAM,SAAjB,mBAAuB,UAAvB,mBAA8B;AAAA,IACvC,CAAC;AAED,UAAM,UAAUA,IAAQ,SAAC,MAAM;AAC7B,YAAM,kBAAkB,CAAC,OAAO,QAAQ,OAAO,OAAO,QAAQ,OAAO,MAAM;AAC3E,aAAO,gBAAgB,SAAS,cAAc,KAAK;AAAA,IACrD,CAAC;AAED,UAAM,UAAUA,IAAQ,SAAC,MAAM;AAC7B,YAAM,kBAAkB,CAAC,OAAO,QAAQ,KAAK;AAC7C,aAAO,gBAAgB,SAAS,cAAc,KAAK;AAAA,IACrD,CAAC;AAGD,UAAM,YAAYA,IAAQ,SAAC,MAAM;AAC/B,YAAM,QAAQ;AAAA,QACZ,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,OAAO;AAAA,MACX;AACE,aAAO,MAAM,cAAc,KAAK,KAAK;AAAA,IACvC,CAAC;AAGD,aAAS,aAAa;AACpB,eAAS,QAAQ;AAAA,IACnB;AAGA,aAAS,YAAY,KAAK;AACxB,YAAM,QAAQ,0BAA0B,IAAI,OAAO;AACnD,eAAS,QAAQ;AAAA,IACnB;AAGA,mBAAe,YAAY;AACzB,UAAI,CAAC,aAAa,MAAO;AAEzB,UAAI;AACF,YAAI,aAAa,MAAM,UAAU,CAAC,WAAW;AAC3C,gBAAM,aAAa,MAAM,KAAI;AAC7B,sBAAY;AAAA,QAClB;AAAA,MACG,SAAQ,KAAK;AACZ,oBAAY,GAAG;AAAA,MACnB;AAAA,IACA;AAiBA,aAAS,4BAA4B;AACnC,YAAM,UAAU;AAAA,QACd,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,WAAW;AAAA,MACf;AAEE,iBAAW,IAAI,qBAAqB,CAAC,YAAY;AAC/C,gBAAQ,QAAQ,WAAS;;AACvB,yBAAe,QAAQ,MAAM;AAE7B,cAAI,MAAM,gBAAgB;AACxB,gBAAI,QAAQ,WAAS,WAAM,YAAN,mBAAe,WAAU;AAC5C,wBAAS;AAAA,YACnB;AAEQ,qBAAS,WAAU;AAAA,UAC3B;AAAA,QACK,CAAA;AAAA,MACL,GAAK,OAAO;AAGV,YAAM,UAAU,QAAQ,QAAQ,aAAa,QAAQ,aAAa;AAClE,UAAI,SAAS;AACX,iBAAS,QAAQ,OAAO;AAAA,MAC5B;AAAA,IACA;AAGAC,QAAAA,UAAU,MAAM;AACd,gCAAyB;AAAA,IAC3B,CAAC;AAEDC,QAAAA,YAAY,MAAM;AAChB,UAAI,UAAU;AACZ,iBAAS,WAAU;AAAA,MACvB;AAAA,IACA,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"Media.vue.cjs","sources":["../../../../../src/components/Media/Media.vue"],"sourcesContent":["<template>\n <div class=\"media-container\">\n <!-- Изображение с ленивой загрузкой и placeholder -->\n <img\n v-if=\"isImage\"\n :src=\"isIntersecting ? url : ''\"\n :data-src=\"url\"\n :alt=\"options?.alt || 'Image'\"\n class=\"media-item\"\n :class=\"{ 'loading': !isLoaded }\"\n loading=\"lazy\"\n @load=\"handleLoad\"\n v-bind=\"options\"\n ref=\"imageElement\"\n />\n \n <!-- Видео с предварительной загрузкой -->\n <video\n v-else-if=\"isVideo\"\n ref=\"videoElement\"\n :class=\"{ 'loading': !isLoaded }\"\n class=\"media-item\"\n :controls=\"!options?.hideControls\"\n :loop=\"options?.loop !== false\"\n :muted=\"options?.muted !== false\"\n :autoplay=\"options?.autoplay\"\n :playsinline=\"options?.playsinline !== false\"\n :preload=\"options?.preload || 'metadata'\"\n @loadeddata=\"handleLoad\"\n v-bind=\"options\"\n >\n <source :src=\"url\" :type=\"videoType\">\n </video>\n \n <!-- Плейсхолдер во время загрузки -->\n <div v-if=\"!isLoaded\" class=\"media-placeholder\">\n Loading...\n </div>\n \n <!-- Сообщение об ошибке -->\n <div v-if=\"error\" class=\"media-error\">\n {{ error }}\n </div>\n </div>\n</template>\n\n<script setup>\nimport { ref, onMounted, computed, onUnmounted } from 'vue'\n\nconst props = defineProps({\n url: {\n type: String,\n required: true\n },\n options: {\n type: Object,\n default: () => ({\n muted: true,\n loop: true,\n playsinline: true,\n preload: 'metadata' // 'none' | 'metadata' | 'auto'\n })\n }\n})\n\n// Refs\nconst videoElement = ref(null)\nconst imageElement = ref(null)\nconst isLoaded = ref(false)\nconst error = ref(null)\nconst isIntersecting = ref(false)\nlet observer = null\nlet isPlaying = false\n\n// Определяем тип медиа\nconst fileExtension = computed(() => {\n return props.url?.split('.')?.pop()?.toLowerCase()\n})\n\nconst isImage = computed(() => {\n const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'avif']\n return imageExtensions.includes(fileExtension.value)\n})\n\nconst isVideo = computed(() => {\n const videoExtensions = ['mp4', 'webm', 'ogg']\n return videoExtensions.includes(fileExtension.value)\n})\n\n// Определяем MIME-тип для видео\nconst videoType = computed(() => {\n const types = {\n 'mp4': 'video/mp4',\n 'webm': 'video/webm',\n 'ogg': 'video/ogg'\n }\n return types[fileExtension.value] || ''\n})\n\n// Обработчик загрузки медиа\nfunction handleLoad() {\n isLoaded.value = true\n}\n\n// Обработка ошибок\nfunction handleError(err) {\n error.value = `Ошибка загрузки медиа: ${err.message}`\n isLoaded.value = false\n}\n\n// Управление видео с обработкой ошибок\nasync function playVideo() {\n if (!videoElement.value) return\n \n try {\n if (videoElement.value.paused && !isPlaying) {\n await videoElement.value.play()\n isPlaying = true\n }\n } catch (err) {\n handleError(err)\n }\n}\n\nfunction checkAndPlayVideo() {\n if (!videoElement.value) return\n \n videoElement.value.onplaying = () => {\n isPlaying = true\n }\n \n videoElement.value.onpause = () => {\n isPlaying = false\n }\n \n videoElement.value.onerror = handleError\n}\n\n// Intersection Observer для ленивой загрузки\nfunction setupIntersectionObserver() {\n const options = {\n root: null,\n rootMargin: '50px',\n threshold: 0.1\n }\n \n observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n isIntersecting.value = entry.isIntersecting\n \n if (entry.isIntersecting) {\n if (isVideo.value && props.options?.autoplay) {\n playVideo()\n }\n // Отключаем observer после первой загрузки\n observer.disconnect()\n }\n })\n }, options)\n \n // Наблюдаем за элементом в зависимости от типа медиа\n const element = isImage.value ? imageElement.value : videoElement.value\n if (element) {\n observer.observe(element)\n }\n}\n\n// Lifecycle hooks\nonMounted(() => {\n setupIntersectionObserver()\n})\n\nonUnmounted(() => {\n if (observer) {\n observer.disconnect()\n }\n})\n</script>\n\n<style scoped>\n.media-container {\n}\n\n.media-item {\n all: inherit;\n opacity: 1;\n transition: opacity 0.3s ease;\n}\n\n.media-item.loading {\n opacity: 0;\n}\n\n.media-placeholder {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: #f5f5f5;\n}\n\n.media-error {\n color: #ff4444;\n padding: 1rem;\n text-align: center;\n}\n</style>"],"names":["ref","computed","onMounted","onUnmounted"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,UAAM,QAAQ;AAiBd,UAAM,eAAeA,IAAG,IAAC,IAAI;AAC7B,UAAM,eAAeA,IAAG,IAAC,IAAI;AAC7B,UAAM,WAAWA,IAAG,IAAC,KAAK;AAC1B,UAAM,QAAQA,IAAG,IAAC,IAAI;AACtB,UAAM,iBAAiBA,IAAG,IAAC,KAAK;AAChC,QAAI,WAAW;AACf,QAAI,YAAY;AAGhB,UAAM,gBAAgBC,IAAQ,SAAC,MAAM;;AACnC,cAAO,uBAAM,QAAN,mBAAW,MAAM,SAAjB,mBAAuB,UAAvB,mBAA8B;AAAA,IACvC,CAAC;AAED,UAAM,UAAUA,IAAQ,SAAC,MAAM;AAC7B,YAAM,kBAAkB,CAAC,OAAO,QAAQ,OAAO,OAAO,QAAQ,OAAO,MAAM;AAC3E,aAAO,gBAAgB,SAAS,cAAc,KAAK;AAAA,IACrD,CAAC;AAED,UAAM,UAAUA,IAAQ,SAAC,MAAM;AAC7B,YAAM,kBAAkB,CAAC,OAAO,QAAQ,KAAK;AAC7C,aAAO,gBAAgB,SAAS,cAAc,KAAK;AAAA,IACrD,CAAC;AAGD,UAAM,YAAYA,IAAQ,SAAC,MAAM;AAC/B,YAAM,QAAQ;AAAA,QACZ,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,OAAO;AAAA,MACX;AACE,aAAO,MAAM,cAAc,KAAK,KAAK;AAAA,IACvC,CAAC;AAGD,aAAS,aAAa;AACpB,eAAS,QAAQ;AAAA,IACnB;AAGA,aAAS,YAAY,KAAK;AACxB,YAAM,QAAQ,0BAA0B,IAAI,OAAO;AACnD,eAAS,QAAQ;AAAA,IACnB;AAGA,mBAAe,YAAY;AACzB,UAAI,CAAC,aAAa,MAAO;AAEzB,UAAI;AACF,YAAI,aAAa,MAAM,UAAU,CAAC,WAAW;AAC3C,gBAAM,aAAa,MAAM,KAAI;AAC7B,sBAAY;AAAA,QAClB;AAAA,MACG,SAAQ,KAAK;AACZ,oBAAY,GAAG;AAAA,MACnB;AAAA,IACA;AAiBA,aAAS,4BAA4B;AACnC,YAAM,UAAU;AAAA,QACd,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,WAAW;AAAA,MACf;AAEE,iBAAW,IAAI,qBAAqB,CAAC,YAAY;AAC/C,gBAAQ,QAAQ,WAAS;;AACvB,yBAAe,QAAQ,MAAM;AAE7B,cAAI,MAAM,gBAAgB;AACxB,gBAAI,QAAQ,WAAS,WAAM,YAAN,mBAAe,WAAU;AAC5C,wBAAS;AAAA,YACnB;AAEQ,qBAAS,WAAU;AAAA,UAC3B;AAAA,QACK,CAAA;AAAA,MACL,GAAK,OAAO;AAGV,YAAM,UAAU,QAAQ,QAAQ,aAAa,QAAQ,aAAa;AAClE,UAAI,SAAS;AACX,iBAAS,QAAQ,OAAO;AAAA,MAC5B;AAAA,IACA;AAGAC,QAAAA,UAAU,MAAM;AACd,gCAAyB;AAAA,IAC3B,CAAC;AAEDC,QAAAA,YAAY,MAAM;AAChB,UAAI,UAAU;AACZ,iBAAS,WAAU;AAAA,MACvB;AAAA,IACA,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -140,13 +140,13 @@ const _sfc_main = {
140
140
  type: videoType.value
141
141
  }, null, 8, _hoisted_4)
142
142
  ], 16, _hoisted_3)) : createCommentVNode("", true),
143
- !isLoaded.value ? (openBlock(), createElementBlock("div", _hoisted_5, " Загрузка... ")) : createCommentVNode("", true),
143
+ !isLoaded.value ? (openBlock(), createElementBlock("div", _hoisted_5, " Loading... ")) : createCommentVNode("", true),
144
144
  error.value ? (openBlock(), createElementBlock("div", _hoisted_6, toDisplayString(error.value), 1)) : createCommentVNode("", true)
145
145
  ]);
146
146
  };
147
147
  }
148
148
  };
149
- const Media = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-94bcf726"]]);
149
+ const Media = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-1f94a0e9"]]);
150
150
  export {
151
151
  Media as default
152
152
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Media.vue.js","sources":["../../../../../src/components/Media/Media.vue"],"sourcesContent":["<template>\n <div class=\"media-container\">\n <!-- Изображение с ленивой загрузкой и placeholder -->\n <img\n v-if=\"isImage\"\n :src=\"isIntersecting ? url : ''\"\n :data-src=\"url\"\n :alt=\"options?.alt || 'Image'\"\n class=\"media-item\"\n :class=\"{ 'loading': !isLoaded }\"\n loading=\"lazy\"\n @load=\"handleLoad\"\n v-bind=\"options\"\n ref=\"imageElement\"\n />\n \n <!-- Видео с предварительной загрузкой -->\n <video\n v-else-if=\"isVideo\"\n ref=\"videoElement\"\n :class=\"{ 'loading': !isLoaded }\"\n class=\"media-item\"\n :controls=\"!options?.hideControls\"\n :loop=\"options?.loop !== false\"\n :muted=\"options?.muted !== false\"\n :autoplay=\"options?.autoplay\"\n :playsinline=\"options?.playsinline !== false\"\n :preload=\"options?.preload || 'metadata'\"\n @loadeddata=\"handleLoad\"\n v-bind=\"options\"\n >\n <source :src=\"url\" :type=\"videoType\">\n </video>\n \n <!-- Плейсхолдер во время загрузки -->\n <div v-if=\"!isLoaded\" class=\"media-placeholder\">\n Загрузка...\n </div>\n \n <!-- Сообщение об ошибке -->\n <div v-if=\"error\" class=\"media-error\">\n {{ error }}\n </div>\n </div>\n</template>\n\n<script setup>\nimport { ref, onMounted, computed, onUnmounted } from 'vue'\n\nconst props = defineProps({\n url: {\n type: String,\n required: true\n },\n options: {\n type: Object,\n default: () => ({\n muted: true,\n loop: true,\n playsinline: true,\n preload: 'metadata' // 'none' | 'metadata' | 'auto'\n })\n }\n})\n\n// Refs\nconst videoElement = ref(null)\nconst imageElement = ref(null)\nconst isLoaded = ref(false)\nconst error = ref(null)\nconst isIntersecting = ref(false)\nlet observer = null\nlet isPlaying = false\n\n// Определяем тип медиа\nconst fileExtension = computed(() => {\n return props.url?.split('.')?.pop()?.toLowerCase()\n})\n\nconst isImage = computed(() => {\n const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'avif']\n return imageExtensions.includes(fileExtension.value)\n})\n\nconst isVideo = computed(() => {\n const videoExtensions = ['mp4', 'webm', 'ogg']\n return videoExtensions.includes(fileExtension.value)\n})\n\n// Определяем MIME-тип для видео\nconst videoType = computed(() => {\n const types = {\n 'mp4': 'video/mp4',\n 'webm': 'video/webm',\n 'ogg': 'video/ogg'\n }\n return types[fileExtension.value] || ''\n})\n\n// Обработчик загрузки медиа\nfunction handleLoad() {\n isLoaded.value = true\n}\n\n// Обработка ошибок\nfunction handleError(err) {\n error.value = `Ошибка загрузки медиа: ${err.message}`\n isLoaded.value = false\n}\n\n// Управление видео с обработкой ошибок\nasync function playVideo() {\n if (!videoElement.value) return\n \n try {\n if (videoElement.value.paused && !isPlaying) {\n await videoElement.value.play()\n isPlaying = true\n }\n } catch (err) {\n handleError(err)\n }\n}\n\nfunction checkAndPlayVideo() {\n if (!videoElement.value) return\n \n videoElement.value.onplaying = () => {\n isPlaying = true\n }\n \n videoElement.value.onpause = () => {\n isPlaying = false\n }\n \n videoElement.value.onerror = handleError\n}\n\n// Intersection Observer для ленивой загрузки\nfunction setupIntersectionObserver() {\n const options = {\n root: null,\n rootMargin: '50px',\n threshold: 0.1\n }\n \n observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n isIntersecting.value = entry.isIntersecting\n \n if (entry.isIntersecting) {\n if (isVideo.value && props.options?.autoplay) {\n playVideo()\n }\n // Отключаем observer после первой загрузки\n observer.disconnect()\n }\n })\n }, options)\n \n // Наблюдаем за элементом в зависимости от типа медиа\n const element = isImage.value ? imageElement.value : videoElement.value\n if (element) {\n observer.observe(element)\n }\n}\n\n// Lifecycle hooks\nonMounted(() => {\n setupIntersectionObserver()\n})\n\nonUnmounted(() => {\n if (observer) {\n observer.disconnect()\n }\n})\n</script>\n\n<style scoped>\n.media-container {\n}\n\n.media-item {\n all: inherit;\n opacity: 1;\n transition: opacity 0.3s ease;\n}\n\n.media-item.loading {\n opacity: 0;\n}\n\n.media-placeholder {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: #f5f5f5;\n}\n\n.media-error {\n color: #ff4444;\n padding: 1rem;\n text-align: center;\n}\n</style>"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,UAAM,QAAQ;AAiBd,UAAM,eAAe,IAAI,IAAI;AAC7B,UAAM,eAAe,IAAI,IAAI;AAC7B,UAAM,WAAW,IAAI,KAAK;AAC1B,UAAM,QAAQ,IAAI,IAAI;AACtB,UAAM,iBAAiB,IAAI,KAAK;AAChC,QAAI,WAAW;AACf,QAAI,YAAY;AAGhB,UAAM,gBAAgB,SAAS,MAAM;;AACnC,cAAO,uBAAM,QAAN,mBAAW,MAAM,SAAjB,mBAAuB,UAAvB,mBAA8B;AAAA,IACvC,CAAC;AAED,UAAM,UAAU,SAAS,MAAM;AAC7B,YAAM,kBAAkB,CAAC,OAAO,QAAQ,OAAO,OAAO,QAAQ,OAAO,MAAM;AAC3E,aAAO,gBAAgB,SAAS,cAAc,KAAK;AAAA,IACrD,CAAC;AAED,UAAM,UAAU,SAAS,MAAM;AAC7B,YAAM,kBAAkB,CAAC,OAAO,QAAQ,KAAK;AAC7C,aAAO,gBAAgB,SAAS,cAAc,KAAK;AAAA,IACrD,CAAC;AAGD,UAAM,YAAY,SAAS,MAAM;AAC/B,YAAM,QAAQ;AAAA,QACZ,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,OAAO;AAAA,MACX;AACE,aAAO,MAAM,cAAc,KAAK,KAAK;AAAA,IACvC,CAAC;AAGD,aAAS,aAAa;AACpB,eAAS,QAAQ;AAAA,IACnB;AAGA,aAAS,YAAY,KAAK;AACxB,YAAM,QAAQ,0BAA0B,IAAI,OAAO;AACnD,eAAS,QAAQ;AAAA,IACnB;AAGA,mBAAe,YAAY;AACzB,UAAI,CAAC,aAAa,MAAO;AAEzB,UAAI;AACF,YAAI,aAAa,MAAM,UAAU,CAAC,WAAW;AAC3C,gBAAM,aAAa,MAAM,KAAI;AAC7B,sBAAY;AAAA,QAClB;AAAA,MACG,SAAQ,KAAK;AACZ,oBAAY,GAAG;AAAA,MACnB;AAAA,IACA;AAiBA,aAAS,4BAA4B;AACnC,YAAM,UAAU;AAAA,QACd,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,WAAW;AAAA,MACf;AAEE,iBAAW,IAAI,qBAAqB,CAAC,YAAY;AAC/C,gBAAQ,QAAQ,WAAS;;AACvB,yBAAe,QAAQ,MAAM;AAE7B,cAAI,MAAM,gBAAgB;AACxB,gBAAI,QAAQ,WAAS,WAAM,YAAN,mBAAe,WAAU;AAC5C,wBAAS;AAAA,YACnB;AAEQ,qBAAS,WAAU;AAAA,UAC3B;AAAA,QACK,CAAA;AAAA,MACL,GAAK,OAAO;AAGV,YAAM,UAAU,QAAQ,QAAQ,aAAa,QAAQ,aAAa;AAClE,UAAI,SAAS;AACX,iBAAS,QAAQ,OAAO;AAAA,MAC5B;AAAA,IACA;AAGA,cAAU,MAAM;AACd,gCAAyB;AAAA,IAC3B,CAAC;AAED,gBAAY,MAAM;AAChB,UAAI,UAAU;AACZ,iBAAS,WAAU;AAAA,MACvB;AAAA,IACA,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"Media.vue.js","sources":["../../../../../src/components/Media/Media.vue"],"sourcesContent":["<template>\n <div class=\"media-container\">\n <!-- Изображение с ленивой загрузкой и placeholder -->\n <img\n v-if=\"isImage\"\n :src=\"isIntersecting ? url : ''\"\n :data-src=\"url\"\n :alt=\"options?.alt || 'Image'\"\n class=\"media-item\"\n :class=\"{ 'loading': !isLoaded }\"\n loading=\"lazy\"\n @load=\"handleLoad\"\n v-bind=\"options\"\n ref=\"imageElement\"\n />\n \n <!-- Видео с предварительной загрузкой -->\n <video\n v-else-if=\"isVideo\"\n ref=\"videoElement\"\n :class=\"{ 'loading': !isLoaded }\"\n class=\"media-item\"\n :controls=\"!options?.hideControls\"\n :loop=\"options?.loop !== false\"\n :muted=\"options?.muted !== false\"\n :autoplay=\"options?.autoplay\"\n :playsinline=\"options?.playsinline !== false\"\n :preload=\"options?.preload || 'metadata'\"\n @loadeddata=\"handleLoad\"\n v-bind=\"options\"\n >\n <source :src=\"url\" :type=\"videoType\">\n </video>\n \n <!-- Плейсхолдер во время загрузки -->\n <div v-if=\"!isLoaded\" class=\"media-placeholder\">\n Loading...\n </div>\n \n <!-- Сообщение об ошибке -->\n <div v-if=\"error\" class=\"media-error\">\n {{ error }}\n </div>\n </div>\n</template>\n\n<script setup>\nimport { ref, onMounted, computed, onUnmounted } from 'vue'\n\nconst props = defineProps({\n url: {\n type: String,\n required: true\n },\n options: {\n type: Object,\n default: () => ({\n muted: true,\n loop: true,\n playsinline: true,\n preload: 'metadata' // 'none' | 'metadata' | 'auto'\n })\n }\n})\n\n// Refs\nconst videoElement = ref(null)\nconst imageElement = ref(null)\nconst isLoaded = ref(false)\nconst error = ref(null)\nconst isIntersecting = ref(false)\nlet observer = null\nlet isPlaying = false\n\n// Определяем тип медиа\nconst fileExtension = computed(() => {\n return props.url?.split('.')?.pop()?.toLowerCase()\n})\n\nconst isImage = computed(() => {\n const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'avif']\n return imageExtensions.includes(fileExtension.value)\n})\n\nconst isVideo = computed(() => {\n const videoExtensions = ['mp4', 'webm', 'ogg']\n return videoExtensions.includes(fileExtension.value)\n})\n\n// Определяем MIME-тип для видео\nconst videoType = computed(() => {\n const types = {\n 'mp4': 'video/mp4',\n 'webm': 'video/webm',\n 'ogg': 'video/ogg'\n }\n return types[fileExtension.value] || ''\n})\n\n// Обработчик загрузки медиа\nfunction handleLoad() {\n isLoaded.value = true\n}\n\n// Обработка ошибок\nfunction handleError(err) {\n error.value = `Ошибка загрузки медиа: ${err.message}`\n isLoaded.value = false\n}\n\n// Управление видео с обработкой ошибок\nasync function playVideo() {\n if (!videoElement.value) return\n \n try {\n if (videoElement.value.paused && !isPlaying) {\n await videoElement.value.play()\n isPlaying = true\n }\n } catch (err) {\n handleError(err)\n }\n}\n\nfunction checkAndPlayVideo() {\n if (!videoElement.value) return\n \n videoElement.value.onplaying = () => {\n isPlaying = true\n }\n \n videoElement.value.onpause = () => {\n isPlaying = false\n }\n \n videoElement.value.onerror = handleError\n}\n\n// Intersection Observer для ленивой загрузки\nfunction setupIntersectionObserver() {\n const options = {\n root: null,\n rootMargin: '50px',\n threshold: 0.1\n }\n \n observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n isIntersecting.value = entry.isIntersecting\n \n if (entry.isIntersecting) {\n if (isVideo.value && props.options?.autoplay) {\n playVideo()\n }\n // Отключаем observer после первой загрузки\n observer.disconnect()\n }\n })\n }, options)\n \n // Наблюдаем за элементом в зависимости от типа медиа\n const element = isImage.value ? imageElement.value : videoElement.value\n if (element) {\n observer.observe(element)\n }\n}\n\n// Lifecycle hooks\nonMounted(() => {\n setupIntersectionObserver()\n})\n\nonUnmounted(() => {\n if (observer) {\n observer.disconnect()\n }\n})\n</script>\n\n<style scoped>\n.media-container {\n}\n\n.media-item {\n all: inherit;\n opacity: 1;\n transition: opacity 0.3s ease;\n}\n\n.media-item.loading {\n opacity: 0;\n}\n\n.media-placeholder {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: #f5f5f5;\n}\n\n.media-error {\n color: #ff4444;\n padding: 1rem;\n text-align: center;\n}\n</style>"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,UAAM,QAAQ;AAiBd,UAAM,eAAe,IAAI,IAAI;AAC7B,UAAM,eAAe,IAAI,IAAI;AAC7B,UAAM,WAAW,IAAI,KAAK;AAC1B,UAAM,QAAQ,IAAI,IAAI;AACtB,UAAM,iBAAiB,IAAI,KAAK;AAChC,QAAI,WAAW;AACf,QAAI,YAAY;AAGhB,UAAM,gBAAgB,SAAS,MAAM;;AACnC,cAAO,uBAAM,QAAN,mBAAW,MAAM,SAAjB,mBAAuB,UAAvB,mBAA8B;AAAA,IACvC,CAAC;AAED,UAAM,UAAU,SAAS,MAAM;AAC7B,YAAM,kBAAkB,CAAC,OAAO,QAAQ,OAAO,OAAO,QAAQ,OAAO,MAAM;AAC3E,aAAO,gBAAgB,SAAS,cAAc,KAAK;AAAA,IACrD,CAAC;AAED,UAAM,UAAU,SAAS,MAAM;AAC7B,YAAM,kBAAkB,CAAC,OAAO,QAAQ,KAAK;AAC7C,aAAO,gBAAgB,SAAS,cAAc,KAAK;AAAA,IACrD,CAAC;AAGD,UAAM,YAAY,SAAS,MAAM;AAC/B,YAAM,QAAQ;AAAA,QACZ,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,OAAO;AAAA,MACX;AACE,aAAO,MAAM,cAAc,KAAK,KAAK;AAAA,IACvC,CAAC;AAGD,aAAS,aAAa;AACpB,eAAS,QAAQ;AAAA,IACnB;AAGA,aAAS,YAAY,KAAK;AACxB,YAAM,QAAQ,0BAA0B,IAAI,OAAO;AACnD,eAAS,QAAQ;AAAA,IACnB;AAGA,mBAAe,YAAY;AACzB,UAAI,CAAC,aAAa,MAAO;AAEzB,UAAI;AACF,YAAI,aAAa,MAAM,UAAU,CAAC,WAAW;AAC3C,gBAAM,aAAa,MAAM,KAAI;AAC7B,sBAAY;AAAA,QAClB;AAAA,MACG,SAAQ,KAAK;AACZ,oBAAY,GAAG;AAAA,MACnB;AAAA,IACA;AAiBA,aAAS,4BAA4B;AACnC,YAAM,UAAU;AAAA,QACd,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,WAAW;AAAA,MACf;AAEE,iBAAW,IAAI,qBAAqB,CAAC,YAAY;AAC/C,gBAAQ,QAAQ,WAAS;;AACvB,yBAAe,QAAQ,MAAM;AAE7B,cAAI,MAAM,gBAAgB;AACxB,gBAAI,QAAQ,WAAS,WAAM,YAAN,mBAAe,WAAU;AAC5C,wBAAS;AAAA,YACnB;AAEQ,qBAAS,WAAU;AAAA,UAC3B;AAAA,QACK,CAAA;AAAA,MACL,GAAK,OAAO;AAGV,YAAM,UAAU,QAAQ,QAAQ,aAAa,QAAQ,aAAa;AAClE,UAAI,SAAS;AACX,iBAAS,QAAQ,OAAO;AAAA,MAC5B;AAAA,IACA;AAGA,cAAU,MAAM;AACd,gCAAyB;AAAA,IAC3B,CAAC;AAED,gBAAY,MAAM;AAChB,UAAI,UAAU;AACZ,iBAAS,WAAU;AAAA,MACvB;AAAA,IACA,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -2,7 +2,6 @@
2
2
  Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
3
3
  const vue = require("vue");
4
4
  const vueRouter = require("vue-router");
5
- const vueI18n = require("vue-i18n");
6
5
  const IconCross = require("../../modules/icons/navigation/IconCross.vue.cjs");
7
6
  ;/* empty css */
8
7
  const _hoisted_1 = {
@@ -35,13 +34,6 @@ const _sfc_main = {
35
34
  });
36
35
  vueRouter.useRoute();
37
36
  vueRouter.useRouter();
38
- const text = {
39
- messages: {
40
- en: {},
41
- ru: {}
42
- }
43
- };
44
- const { t } = vueI18n.useI18n(text);
45
37
  return (_ctx, _cache) => {
46
38
  return vue.openBlock(), vue.createBlock(vue.Transition, { name: "moveFromTop" }, {
47
39
  default: vue.withCtx(() => [
@@ -1 +1 @@
1
- {"version":3,"file":"Popup.vue2.cjs","sources":["../../../../../src/components/Popup/Popup.vue"],"sourcesContent":["<template>\n\t\t<transition name=\"moveFromTop\">\n\t\t\t<teleport to=\"body\" v-if=\"isPopupOpen\">\n\t\t\t\t<div v-if=\"isPopupOpen\" key=\"popup-content\" class=\"pd-small z-index-6 popup-wrapper\"\n\t\t\t\t\t:class=\"{\n \t\t\t\t\t'pd-t-extra': MOBILE_APP === 'ios', \n\t\t\t\t\t}\"\n\t\t\t\t>\n\n\t\t\t\t\t<transition name=\"TransitionTranslateY\" mode=\"out-in\">\n\t\t\t\t\t\t<section class=\"h-max-100 o-y-scroll pos-relative z-index-4\" v-bind=\"$attrs\" :class=\"$attrs.class\">\n\t\t\t\t\t\t\t\t<h4 v-if=\"title\" class=\"mn-b-small\">{{title}}</h4>\n\t\t\t\t\t\t\t\t<IconCross :fill=\"'rgb(var(--white))'\" @click=\"closePopup()\" class=\"cursor-pointer bg-second pd-micro radius-extra pos-absolute pos-t-0 pos-r-0 mn-t-semi mn-r-semi hover-scale-1 i-medium z-index-5\"/>\n\t\t\t\t\t\t\t\t<slot></slot>\n\t\t\t\t\t\t</section> \n\t\t\t\t\t</transition>\n\n\t\t\t\t\t<div \n\t\t\t\t\t\t@click=\"closePopup()\" \n\t\t\t\t :class=\"{'active':isPopupOpen === true}\" \n\t\t\t\t class=\"color-overlay z-index-3\">\n\t\t\t\t\t</div>\n\n\t\t\t\t</div>\n\t\t</teleport>\n\t</transition>\n</template>\n\n<script setup>\nimport { computed, watch, onMounted, ref, nextTick } from 'vue';\n// Import libs\nimport { useRoute, useRouter } from 'vue-router'\nimport { useI18n } from 'vue-i18n'\n// Icons\nimport IconCross from '@martyrs/src/modules/icons/navigation/IconCross.vue';\n// Define props\nconst props = defineProps({\n isPopupOpen: {\n \ttype: Boolean,\n\t default: false\n },\n style: String,\n title: String,\n});\nconst emits = defineEmits(['close-popup'])\n\nfunction closePopup() {\n emits(\"close-popup\");\n} \n\nwatch(() => props.isPopupOpen, (newVal) => {\n if (newVal) {\n document.body.classList.add('no-scroll');\n } else {\n document.body.classList.remove('no-scroll');\n }\n});\n\n// Accessing router and store\nconst route = useRoute()\nconst router = useRouter()\n// Localization\nconst text = {\n \tmessages: {\n\t en: {},\n\t ru: {}\n\t}\n}\nconst { t } = useI18n(text)\n</script>\n\n<style lang=\"scss\">\n\t.no-scroll {\n\t overflow: hidden;\n\t}\n\n\t.popup-wrapper {\n\t\tdisplay: flex;\n\t\tposition: fixed;\n\n\t\talign-items: center;\n\t\tjustify-content: center;\n\n\t\twidth: 100%;\n\t\theight: 100%;\n\n\t\tleft: 0;\n\t\ttop: 0;\n\n\t\tz-index: 40;\n\n\t\t.popup {\n\t\t\tposition: absolute;\n\t\t\theight: auto;\n\t\t\tpadding: 2rem;\n\t\t\tmin-width: 24rem;\n\t\t\tborder-radius: 2rem;\n\t\t\toverflow: hidden;\n\n\t\t\tcolor: white;\n\t\t\tbackground: black;\n\n\t\t\tz-index: 40;\n\t\t}\n\t}\n\n\t.color-overlay {\n\t\tdisplay: block;\n\t\tposition: fixed;\n\n\t\tleft: 0;\n\t\ttop: 0;\n\n\t\twidth: 100%;\n\t\theight: 100%;\n\n\t\tbackground: rgba(0,0,0,0.0);\n\t\tpointer-events: none;\n\n\t\ttransform: scale(1.5);\n\n\t\ttransition: all 0.5s cubic-bezier(.31,.79,.24,.92);\n\n\t\t&.active {\n\t\t\tbackground: rgba(#000,0.25);\n\t\t\tpointer-events: all;\n\t\t}\n\t}\n</style>\n"],"names":["watch","useRoute","useRouter","useI18n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAoCA,UAAM,QAAQ;AAQd,UAAM,QAAQ;AAEd,aAAS,aAAa;AACpB,YAAM,aAAa;AAAA,IACrB;AAEAA,QAAK,MAAC,MAAM,MAAM,aAAa,CAAC,WAAW;AACzC,UAAI,QAAQ;AACV,iBAAS,KAAK,UAAU,IAAI,WAAW;AAAA,MAC3C,OAAS;AACL,iBAAS,KAAK,UAAU,OAAO,WAAW;AAAA,MAC9C;AAAA,IACA,CAAC;AAGaC,cAAQ,SAAA;AACPC,cAAS,UAAA;AAExB,UAAM,OAAO;AAAA,MACV,UAAU;AAAA,QACR,IAAI,CAAE;AAAA,QACN,IAAI,CAAA;AAAA,MACT;AAAA,IACA;AACA,UAAM,EAAE,EAAC,IAAKC,QAAAA,QAAQ,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"Popup.vue2.cjs","sources":["../../../../../src/components/Popup/Popup.vue"],"sourcesContent":["<template>\n\t\t<transition name=\"moveFromTop\">\n\t\t\t<teleport to=\"body\" v-if=\"isPopupOpen\">\n\t\t\t\t<div v-if=\"isPopupOpen\" key=\"popup-content\" class=\"pd-small z-index-6 popup-wrapper\"\n\t\t\t\t\t:class=\"{\n \t\t\t\t\t'pd-t-extra': MOBILE_APP === 'ios', \n\t\t\t\t\t}\"\n\t\t\t\t>\n\n\t\t\t\t\t<transition name=\"TransitionTranslateY\" mode=\"out-in\">\n\t\t\t\t\t\t<section class=\"h-max-100 o-y-scroll pos-relative z-index-4\" v-bind=\"$attrs\" :class=\"$attrs.class\">\n\t\t\t\t\t\t\t\t<h4 v-if=\"title\" class=\"mn-b-small\">{{title}}</h4>\n\t\t\t\t\t\t\t\t<IconCross :fill=\"'rgb(var(--white))'\" @click=\"closePopup()\" class=\"cursor-pointer bg-second pd-micro radius-extra pos-absolute pos-t-0 pos-r-0 mn-t-semi mn-r-semi hover-scale-1 i-medium z-index-5\"/>\n\t\t\t\t\t\t\t\t<slot></slot>\n\t\t\t\t\t\t</section> \n\t\t\t\t\t</transition>\n\n\t\t\t\t\t<div \n\t\t\t\t\t\t@click=\"closePopup()\" \n\t\t\t\t :class=\"{'active':isPopupOpen === true}\" \n\t\t\t\t class=\"color-overlay z-index-3\">\n\t\t\t\t\t</div>\n\n\t\t\t\t</div>\n\t\t</teleport>\n\t</transition>\n</template>\n\n<script setup>\nimport { computed, watch, onMounted, ref, nextTick } from 'vue';\n// Import libs\nimport { useRoute, useRouter } from 'vue-router'\n// import { useI18n } from 'vue-i18n'\n// Icons\nimport IconCross from '@martyrs/src/modules/icons/navigation/IconCross.vue';\n// Define props\nconst props = defineProps({\n isPopupOpen: {\n \ttype: Boolean,\n\t default: false\n },\n style: String,\n title: String,\n});\nconst emits = defineEmits(['close-popup'])\n\nfunction closePopup() {\n emits(\"close-popup\");\n} \n\nwatch(() => props.isPopupOpen, (newVal) => {\n if (newVal) {\n document.body.classList.add('no-scroll');\n } else {\n document.body.classList.remove('no-scroll');\n }\n});\n\n// Accessing router and store\nconst route = useRoute()\nconst router = useRouter()\n// Localization\nconst text = {\n \tmessages: {\n\t en: {},\n\t ru: {}\n\t}\n}\n// const { t } = useI18n(text)\n</script>\n\n<style lang=\"scss\">\n\t.no-scroll {\n\t overflow: hidden;\n\t}\n\n\t.popup-wrapper {\n\t\tdisplay: flex;\n\t\tposition: fixed;\n\n\t\talign-items: center;\n\t\tjustify-content: center;\n\n\t\twidth: 100%;\n\t\theight: 100%;\n\n\t\tleft: 0;\n\t\ttop: 0;\n\n\t\tz-index: 40;\n\n\t\t.popup {\n\t\t\tposition: absolute;\n\t\t\theight: auto;\n\t\t\tpadding: 2rem;\n\t\t\tmin-width: 24rem;\n\t\t\tborder-radius: 2rem;\n\t\t\toverflow: hidden;\n\n\t\t\tcolor: white;\n\t\t\tbackground: black;\n\n\t\t\tz-index: 40;\n\t\t}\n\t}\n\n\t.color-overlay {\n\t\tdisplay: block;\n\t\tposition: fixed;\n\n\t\tleft: 0;\n\t\ttop: 0;\n\n\t\twidth: 100%;\n\t\theight: 100%;\n\n\t\tbackground: rgba(0,0,0,0.0);\n\t\tpointer-events: none;\n\n\t\ttransform: scale(1.5);\n\n\t\ttransition: all 0.5s cubic-bezier(.31,.79,.24,.92);\n\n\t\t&.active {\n\t\t\tbackground: rgba(#000,0.25);\n\t\t\tpointer-events: all;\n\t\t}\n\t}\n</style>\n"],"names":["watch","useRoute","useRouter"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAoCA,UAAM,QAAQ;AAQd,UAAM,QAAQ;AAEd,aAAS,aAAa;AACpB,YAAM,aAAa;AAAA,IACrB;AAEAA,QAAK,MAAC,MAAM,MAAM,aAAa,CAAC,WAAW;AACzC,UAAI,QAAQ;AACV,iBAAS,KAAK,UAAU,IAAI,WAAW;AAAA,MAC3C,OAAS;AACL,iBAAS,KAAK,UAAU,OAAO,WAAW;AAAA,MAC9C;AAAA,IACA,CAAC;AAGaC,cAAQ,SAAA;AACPC,cAAS,UAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,6 +1,5 @@
1
1
  import { watch, createBlock, openBlock, Transition, withCtx, createCommentVNode, Teleport, createElementBlock, normalizeClass, createVNode, createElementVNode, mergeProps, renderSlot, toDisplayString } from "vue";
2
2
  import { useRoute, useRouter } from "vue-router";
3
- import { useI18n } from "vue-i18n";
4
3
  import _sfc_main$1 from "../../modules/icons/navigation/IconCross.vue.js";
5
4
  /* empty css */
6
5
  const _hoisted_1 = {
@@ -33,13 +32,6 @@ const _sfc_main = {
33
32
  });
34
33
  useRoute();
35
34
  useRouter();
36
- const text = {
37
- messages: {
38
- en: {},
39
- ru: {}
40
- }
41
- };
42
- const { t } = useI18n(text);
43
35
  return (_ctx, _cache) => {
44
36
  return openBlock(), createBlock(Transition, { name: "moveFromTop" }, {
45
37
  default: withCtx(() => [
@@ -1 +1 @@
1
- {"version":3,"file":"Popup.vue2.js","sources":["../../../../../src/components/Popup/Popup.vue"],"sourcesContent":["<template>\n\t\t<transition name=\"moveFromTop\">\n\t\t\t<teleport to=\"body\" v-if=\"isPopupOpen\">\n\t\t\t\t<div v-if=\"isPopupOpen\" key=\"popup-content\" class=\"pd-small z-index-6 popup-wrapper\"\n\t\t\t\t\t:class=\"{\n \t\t\t\t\t'pd-t-extra': MOBILE_APP === 'ios', \n\t\t\t\t\t}\"\n\t\t\t\t>\n\n\t\t\t\t\t<transition name=\"TransitionTranslateY\" mode=\"out-in\">\n\t\t\t\t\t\t<section class=\"h-max-100 o-y-scroll pos-relative z-index-4\" v-bind=\"$attrs\" :class=\"$attrs.class\">\n\t\t\t\t\t\t\t\t<h4 v-if=\"title\" class=\"mn-b-small\">{{title}}</h4>\n\t\t\t\t\t\t\t\t<IconCross :fill=\"'rgb(var(--white))'\" @click=\"closePopup()\" class=\"cursor-pointer bg-second pd-micro radius-extra pos-absolute pos-t-0 pos-r-0 mn-t-semi mn-r-semi hover-scale-1 i-medium z-index-5\"/>\n\t\t\t\t\t\t\t\t<slot></slot>\n\t\t\t\t\t\t</section> \n\t\t\t\t\t</transition>\n\n\t\t\t\t\t<div \n\t\t\t\t\t\t@click=\"closePopup()\" \n\t\t\t\t :class=\"{'active':isPopupOpen === true}\" \n\t\t\t\t class=\"color-overlay z-index-3\">\n\t\t\t\t\t</div>\n\n\t\t\t\t</div>\n\t\t</teleport>\n\t</transition>\n</template>\n\n<script setup>\nimport { computed, watch, onMounted, ref, nextTick } from 'vue';\n// Import libs\nimport { useRoute, useRouter } from 'vue-router'\nimport { useI18n } from 'vue-i18n'\n// Icons\nimport IconCross from '@martyrs/src/modules/icons/navigation/IconCross.vue';\n// Define props\nconst props = defineProps({\n isPopupOpen: {\n \ttype: Boolean,\n\t default: false\n },\n style: String,\n title: String,\n});\nconst emits = defineEmits(['close-popup'])\n\nfunction closePopup() {\n emits(\"close-popup\");\n} \n\nwatch(() => props.isPopupOpen, (newVal) => {\n if (newVal) {\n document.body.classList.add('no-scroll');\n } else {\n document.body.classList.remove('no-scroll');\n }\n});\n\n// Accessing router and store\nconst route = useRoute()\nconst router = useRouter()\n// Localization\nconst text = {\n \tmessages: {\n\t en: {},\n\t ru: {}\n\t}\n}\nconst { t } = useI18n(text)\n</script>\n\n<style lang=\"scss\">\n\t.no-scroll {\n\t overflow: hidden;\n\t}\n\n\t.popup-wrapper {\n\t\tdisplay: flex;\n\t\tposition: fixed;\n\n\t\talign-items: center;\n\t\tjustify-content: center;\n\n\t\twidth: 100%;\n\t\theight: 100%;\n\n\t\tleft: 0;\n\t\ttop: 0;\n\n\t\tz-index: 40;\n\n\t\t.popup {\n\t\t\tposition: absolute;\n\t\t\theight: auto;\n\t\t\tpadding: 2rem;\n\t\t\tmin-width: 24rem;\n\t\t\tborder-radius: 2rem;\n\t\t\toverflow: hidden;\n\n\t\t\tcolor: white;\n\t\t\tbackground: black;\n\n\t\t\tz-index: 40;\n\t\t}\n\t}\n\n\t.color-overlay {\n\t\tdisplay: block;\n\t\tposition: fixed;\n\n\t\tleft: 0;\n\t\ttop: 0;\n\n\t\twidth: 100%;\n\t\theight: 100%;\n\n\t\tbackground: rgba(0,0,0,0.0);\n\t\tpointer-events: none;\n\n\t\ttransform: scale(1.5);\n\n\t\ttransition: all 0.5s cubic-bezier(.31,.79,.24,.92);\n\n\t\t&.active {\n\t\t\tbackground: rgba(#000,0.25);\n\t\t\tpointer-events: all;\n\t\t}\n\t}\n</style>\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;AAoCA,UAAM,QAAQ;AAQd,UAAM,QAAQ;AAEd,aAAS,aAAa;AACpB,YAAM,aAAa;AAAA,IACrB;AAEA,UAAM,MAAM,MAAM,aAAa,CAAC,WAAW;AACzC,UAAI,QAAQ;AACV,iBAAS,KAAK,UAAU,IAAI,WAAW;AAAA,MAC3C,OAAS;AACL,iBAAS,KAAK,UAAU,OAAO,WAAW;AAAA,MAC9C;AAAA,IACA,CAAC;AAGa,aAAQ;AACP,cAAS;AAExB,UAAM,OAAO;AAAA,MACV,UAAU;AAAA,QACR,IAAI,CAAE;AAAA,QACN,IAAI,CAAA;AAAA,MACT;AAAA,IACA;AACA,UAAM,EAAE,EAAC,IAAK,QAAQ,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"Popup.vue2.js","sources":["../../../../../src/components/Popup/Popup.vue"],"sourcesContent":["<template>\n\t\t<transition name=\"moveFromTop\">\n\t\t\t<teleport to=\"body\" v-if=\"isPopupOpen\">\n\t\t\t\t<div v-if=\"isPopupOpen\" key=\"popup-content\" class=\"pd-small z-index-6 popup-wrapper\"\n\t\t\t\t\t:class=\"{\n \t\t\t\t\t'pd-t-extra': MOBILE_APP === 'ios', \n\t\t\t\t\t}\"\n\t\t\t\t>\n\n\t\t\t\t\t<transition name=\"TransitionTranslateY\" mode=\"out-in\">\n\t\t\t\t\t\t<section class=\"h-max-100 o-y-scroll pos-relative z-index-4\" v-bind=\"$attrs\" :class=\"$attrs.class\">\n\t\t\t\t\t\t\t\t<h4 v-if=\"title\" class=\"mn-b-small\">{{title}}</h4>\n\t\t\t\t\t\t\t\t<IconCross :fill=\"'rgb(var(--white))'\" @click=\"closePopup()\" class=\"cursor-pointer bg-second pd-micro radius-extra pos-absolute pos-t-0 pos-r-0 mn-t-semi mn-r-semi hover-scale-1 i-medium z-index-5\"/>\n\t\t\t\t\t\t\t\t<slot></slot>\n\t\t\t\t\t\t</section> \n\t\t\t\t\t</transition>\n\n\t\t\t\t\t<div \n\t\t\t\t\t\t@click=\"closePopup()\" \n\t\t\t\t :class=\"{'active':isPopupOpen === true}\" \n\t\t\t\t class=\"color-overlay z-index-3\">\n\t\t\t\t\t</div>\n\n\t\t\t\t</div>\n\t\t</teleport>\n\t</transition>\n</template>\n\n<script setup>\nimport { computed, watch, onMounted, ref, nextTick } from 'vue';\n// Import libs\nimport { useRoute, useRouter } from 'vue-router'\n// import { useI18n } from 'vue-i18n'\n// Icons\nimport IconCross from '@martyrs/src/modules/icons/navigation/IconCross.vue';\n// Define props\nconst props = defineProps({\n isPopupOpen: {\n \ttype: Boolean,\n\t default: false\n },\n style: String,\n title: String,\n});\nconst emits = defineEmits(['close-popup'])\n\nfunction closePopup() {\n emits(\"close-popup\");\n} \n\nwatch(() => props.isPopupOpen, (newVal) => {\n if (newVal) {\n document.body.classList.add('no-scroll');\n } else {\n document.body.classList.remove('no-scroll');\n }\n});\n\n// Accessing router and store\nconst route = useRoute()\nconst router = useRouter()\n// Localization\nconst text = {\n \tmessages: {\n\t en: {},\n\t ru: {}\n\t}\n}\n// const { t } = useI18n(text)\n</script>\n\n<style lang=\"scss\">\n\t.no-scroll {\n\t overflow: hidden;\n\t}\n\n\t.popup-wrapper {\n\t\tdisplay: flex;\n\t\tposition: fixed;\n\n\t\talign-items: center;\n\t\tjustify-content: center;\n\n\t\twidth: 100%;\n\t\theight: 100%;\n\n\t\tleft: 0;\n\t\ttop: 0;\n\n\t\tz-index: 40;\n\n\t\t.popup {\n\t\t\tposition: absolute;\n\t\t\theight: auto;\n\t\t\tpadding: 2rem;\n\t\t\tmin-width: 24rem;\n\t\t\tborder-radius: 2rem;\n\t\t\toverflow: hidden;\n\n\t\t\tcolor: white;\n\t\t\tbackground: black;\n\n\t\t\tz-index: 40;\n\t\t}\n\t}\n\n\t.color-overlay {\n\t\tdisplay: block;\n\t\tposition: fixed;\n\n\t\tleft: 0;\n\t\ttop: 0;\n\n\t\twidth: 100%;\n\t\theight: 100%;\n\n\t\tbackground: rgba(0,0,0,0.0);\n\t\tpointer-events: none;\n\n\t\ttransform: scale(1.5);\n\n\t\ttransition: all 0.5s cubic-bezier(.31,.79,.24,.92);\n\n\t\t&.active {\n\t\t\tbackground: rgba(#000,0.25);\n\t\t\tpointer-events: all;\n\t\t}\n\t}\n</style>\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAoCA,UAAM,QAAQ;AAQd,UAAM,QAAQ;AAEd,aAAS,aAAa;AACpB,YAAM,aAAa;AAAA,IACrB;AAEA,UAAM,MAAM,MAAM,aAAa,CAAC,WAAW;AACzC,UAAI,QAAQ;AACV,iBAAS,KAAK,UAAU,IAAI,WAAW;AAAA,MAC3C,OAAS;AACL,iBAAS,KAAK,UAAU,OAAO,WAAW;AAAA,MAC9C;AAAA,IACA,CAAC;AAGa,aAAQ;AACP,cAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,229 @@
1
+ "use strict";
2
+ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
3
+ const vue = require("vue");
4
+ const vueRouter = require("vue-router");
5
+ const vueI18n = require("vue-i18n");
6
+ const Loader = require("../Loader/Loader.vue2.cjs");
7
+ const _pluginVue_exportHelper = require("../../../../_virtual/_plugin-vue_export-helper.cjs");
8
+ const _hoisted_1 = { class: "pos-relative" };
9
+ const _hoisted_2 = {
10
+ key: 0,
11
+ class: "h-20r radius-semi pos-relative w-100 bg-light"
12
+ };
13
+ const _hoisted_3 = {
14
+ key: 1,
15
+ class: "bg-light radius-semi flex flex-center w-100 h-20r"
16
+ };
17
+ const _hoisted_4 = { class: "text-gray-500" };
18
+ const _hoisted_5 = {
19
+ key: 0,
20
+ class: "carousel__dots"
21
+ };
22
+ const _hoisted_6 = ["onClick"];
23
+ const _sfc_main = {
24
+ __name: "Slider.native",
25
+ props: {
26
+ showDots: Boolean,
27
+ store: Object,
28
+ options: Object,
29
+ text: Object,
30
+ user: Object
31
+ },
32
+ setup(__props) {
33
+ const props = __props;
34
+ vueRouter.useRouter();
35
+ const carouselRef = vue.ref(null);
36
+ const entitiesState = vue.ref([]);
37
+ const isLoading = vue.ref(true);
38
+ const selectedIndex = vue.ref(0);
39
+ const autoplayInterval = vue.ref(null);
40
+ const scrollTimeout = vue.ref(null);
41
+ const { t } = vueI18n.useI18n({
42
+ messages: props.text
43
+ });
44
+ const scrollTo = (index) => {
45
+ if (!carouselRef.value) return;
46
+ const container = carouselRef.value.querySelector(".carousel__container");
47
+ const slides = container.querySelectorAll(".carousel__slide");
48
+ if (slides[index]) {
49
+ container.scrollTo({
50
+ left: slides[index].offsetLeft,
51
+ behavior: "smooth"
52
+ });
53
+ selectedIndex.value = index;
54
+ }
55
+ };
56
+ const handleScroll = () => {
57
+ if (scrollTimeout.value) {
58
+ clearTimeout(scrollTimeout.value);
59
+ }
60
+ scrollTimeout.value = setTimeout(() => {
61
+ updateSelectedIndex();
62
+ }, 50);
63
+ };
64
+ const updateSelectedIndex = () => {
65
+ if (!carouselRef.value) return;
66
+ const container = carouselRef.value.querySelector(".carousel__container");
67
+ const slides = container.querySelectorAll(".carousel__slide");
68
+ if (!slides.length) return;
69
+ const scrollPosition = container.scrollLeft;
70
+ const slideWidth = slides[0].offsetWidth;
71
+ const index = Math.round(scrollPosition / slideWidth);
72
+ const boundedIndex = Math.max(0, Math.min(index, entitiesState.value.length - 1));
73
+ selectedIndex.value = boundedIndex;
74
+ };
75
+ const setupAutoplay = () => {
76
+ if (autoplayInterval.value) {
77
+ clearInterval(autoplayInterval.value);
78
+ }
79
+ autoplayInterval.value = setInterval(() => {
80
+ const nextIndex = (selectedIndex.value + 1) % entitiesState.value.length;
81
+ scrollTo(nextIndex);
82
+ }, 2e3);
83
+ };
84
+ vue.onMounted(async () => {
85
+ try {
86
+ entitiesState.value = await props.store.read(props.options);
87
+ } catch (error) {
88
+ console.error("Error loading entities:", error);
89
+ entitiesState.value = [];
90
+ } finally {
91
+ isLoading.value = false;
92
+ }
93
+ if (entitiesState.value.length && carouselRef.value) {
94
+ const container = carouselRef.value.querySelector(".carousel__container");
95
+ const slides = container.querySelectorAll(".carousel__slide");
96
+ const observer = new IntersectionObserver((entries) => {
97
+ entries.forEach((entry) => {
98
+ if (entry.isIntersecting) {
99
+ const slideIndex = Array.from(slides).indexOf(entry.target);
100
+ if (slideIndex !== -1) {
101
+ selectedIndex.value = slideIndex;
102
+ }
103
+ }
104
+ });
105
+ }, {
106
+ root: container,
107
+ threshold: 0.7
108
+ // Consider slide visible when 70% is in view
109
+ });
110
+ slides.forEach((slide) => {
111
+ observer.observe(slide);
112
+ });
113
+ container.addEventListener("focusin", () => {
114
+ if (autoplayInterval.value) {
115
+ clearInterval(autoplayInterval.value);
116
+ }
117
+ });
118
+ container.addEventListener("focusout", () => {
119
+ setupAutoplay();
120
+ });
121
+ container.addEventListener("mousedown", () => {
122
+ if (autoplayInterval.value) {
123
+ clearInterval(autoplayInterval.value);
124
+ }
125
+ });
126
+ container.addEventListener("touchstart", () => {
127
+ if (autoplayInterval.value) {
128
+ clearInterval(autoplayInterval.value);
129
+ }
130
+ });
131
+ container.addEventListener("mouseup", () => {
132
+ setupAutoplay();
133
+ });
134
+ container.addEventListener("touchend", () => {
135
+ setupAutoplay();
136
+ });
137
+ setupAutoplay();
138
+ carouselRef.value._observer = observer;
139
+ }
140
+ });
141
+ vue.onBeforeUnmount(() => {
142
+ if (carouselRef.value) {
143
+ if (carouselRef.value._observer) {
144
+ carouselRef.value._observer.disconnect();
145
+ }
146
+ const container = carouselRef.value.querySelector(".carousel__container");
147
+ if (container) {
148
+ container.removeEventListener("focusin", () => {
149
+ });
150
+ container.removeEventListener("focusout", () => {
151
+ });
152
+ container.removeEventListener("mousedown", () => {
153
+ });
154
+ container.removeEventListener("touchstart", () => {
155
+ });
156
+ container.removeEventListener("mouseup", () => {
157
+ });
158
+ container.removeEventListener("touchend", () => {
159
+ });
160
+ }
161
+ }
162
+ if (autoplayInterval.value) {
163
+ clearInterval(autoplayInterval.value);
164
+ }
165
+ if (scrollTimeout.value) {
166
+ clearTimeout(scrollTimeout.value);
167
+ }
168
+ });
169
+ vue.watch(entitiesState, (newValue) => {
170
+ if (newValue.length && carouselRef.value) {
171
+ selectedIndex.value = 0;
172
+ scrollTo(0);
173
+ setupAutoplay();
174
+ }
175
+ });
176
+ return (_ctx, _cache) => {
177
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
178
+ isLoading.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2, [
179
+ vue.createVNode(Loader.default)
180
+ ])) : !entitiesState.value.length ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3, [
181
+ vue.createElementVNode("p", _hoisted_4, vue.toDisplayString(vue.unref(t)("title")), 1)
182
+ ])) : (vue.openBlock(), vue.createElementBlock("div", {
183
+ key: 2,
184
+ class: "carousel",
185
+ ref_key: "carouselRef",
186
+ ref: carouselRef
187
+ }, [
188
+ vue.createElementVNode("div", {
189
+ class: "carousel__container",
190
+ onScroll: handleScroll
191
+ }, [
192
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(entitiesState.value, (entity, key, index) => {
193
+ return vue.openBlock(), vue.createElementBlock("div", {
194
+ class: "carousel__slide pd-nano",
195
+ key
196
+ }, [
197
+ vue.createVNode(vue.Transition, {
198
+ name: "fade",
199
+ mode: "out-in",
200
+ appear: ""
201
+ }, {
202
+ default: vue.withCtx(() => [
203
+ vue.renderSlot(_ctx.$slots, "default", {
204
+ item: entity,
205
+ user: __props.user
206
+ }, void 0, true)
207
+ ]),
208
+ _: 2
209
+ }, 1024)
210
+ ]);
211
+ }), 128))
212
+ ], 32),
213
+ __props.showDots && entitiesState.value.length > 1 ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_5, [
214
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(entitiesState.value, (_, index) => {
215
+ return vue.openBlock(), vue.createElementBlock("button", {
216
+ key: index,
217
+ class: vue.normalizeClass(["carousel__dot", { "carousel__dot--active": selectedIndex.value === index }]),
218
+ onClick: ($event) => scrollTo(index)
219
+ }, null, 10, _hoisted_6);
220
+ }), 128))
221
+ ])) : vue.createCommentVNode("", true)
222
+ ], 512))
223
+ ]);
224
+ };
225
+ }
226
+ };
227
+ const SliderNative = /* @__PURE__ */ _pluginVue_exportHelper.default(_sfc_main, [["__scopeId", "data-v-a766dedc"]]);
228
+ exports.default = SliderNative;
229
+ //# sourceMappingURL=Slider.native.vue.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Slider.native.vue.cjs","sources":["../../../../../src/components/Slider/Slider.native.vue"],"sourcesContent":["<template>\n <div class=\"pos-relative\">\n <!-- Loading State -->\n <div v-if=\"isLoading\" class=\"h-20r radius-semi pos-relative w-100 bg-light\">\n <Loader />\n </div>\n <!-- Empty State -->\n <div v-else-if=\"!entitiesState.length\" class=\"bg-light radius-semi flex flex-center w-100 h-20r\">\n <p class=\"text-gray-500\">{{t('title')}}</p>\n </div>\n <!-- Native Carousel -->\n <div v-else class=\"carousel\" ref=\"carouselRef\">\n <div class=\"carousel__container\" @scroll=\"handleScroll\">\n <div \n class=\"carousel__slide pd-nano\" \n v-for=\"(entity, key, index) in entitiesState\" \n :key=\"key\"\n >\n <transition name=\"fade\" mode=\"out-in\" appear>\n <slot\n :item=\"entity\"\n :user=\"user\"\n ></slot>\n </transition>\n </div>\n </div>\n \n <!-- Navigation Dots (optional) -->\n <div class=\"carousel__dots\" v-if=\"showDots && entitiesState.length > 1\">\n <button \n v-for=\"(_, index) in entitiesState\" \n :key=\"index\"\n class=\"carousel__dot\"\n :class=\"{ 'carousel__dot--active': selectedIndex === index }\"\n @click=\"scrollTo(index)\"\n ></button>\n </div>\n </div>\n </div>\n</template>\n\n<script setup>\nimport { ref, onMounted, onBeforeUnmount, watch } from 'vue'\nimport { useRouter } from 'vue-router'\nimport { useI18n } from 'vue-i18n'\nimport Loader from '@martyrs/src/components/Loader/Loader.vue'\n\n// Props for customization\nconst props = defineProps({\n showDots: Boolean,\n store: Object,\n options: Object,\n text: Object,\n user: Object\n});\n\nconst router = useRouter()\nconst carouselRef = ref(null)\nconst entitiesState = ref([])\nconst isLoading = ref(true)\nconst selectedIndex = ref(0)\nconst autoplayInterval = ref(null)\nconst scrollTimeout = ref(null)\n\nconst { t } = useI18n({\n messages: props.text\n})\n\n// Scroll to specific slide\nconst scrollTo = (index) => {\n if (!carouselRef.value) return\n \n const container = carouselRef.value.querySelector('.carousel__container')\n const slides = container.querySelectorAll('.carousel__slide')\n \n if (slides[index]) {\n container.scrollTo({\n left: slides[index].offsetLeft,\n behavior: 'smooth'\n })\n \n selectedIndex.value = index\n }\n}\n\n// Handle scroll event with debounce\nconst handleScroll = () => {\n // Clear previous timeout\n if (scrollTimeout.value) {\n clearTimeout(scrollTimeout.value)\n }\n \n // Set a timeout to update the index when scrolling stops\n scrollTimeout.value = setTimeout(() => {\n updateSelectedIndex()\n }, 50) // Small delay to ensure scroll has completed\n}\n\n// Update selected index when scrolling\nconst updateSelectedIndex = () => {\n if (!carouselRef.value) return\n \n const container = carouselRef.value.querySelector('.carousel__container')\n const slides = container.querySelectorAll('.carousel__slide')\n \n if (!slides.length) return\n \n const scrollPosition = container.scrollLeft\n const slideWidth = slides[0].offsetWidth\n \n // Find current slide index based on scroll position\n const index = Math.round(scrollPosition / slideWidth)\n \n // Ensure index is within bounds\n const boundedIndex = Math.max(0, Math.min(index, entitiesState.value.length - 1))\n \n // Update selected index\n selectedIndex.value = boundedIndex\n}\n\n// Setup autoplay functionality\nconst setupAutoplay = () => {\n if (autoplayInterval.value) {\n clearInterval(autoplayInterval.value)\n }\n \n autoplayInterval.value = setInterval(() => {\n const nextIndex = (selectedIndex.value + 1) % entitiesState.value.length\n scrollTo(nextIndex)\n }, 2000) // 2 seconds interval like in original\n}\n\nonMounted(async() => {\n try {\n entitiesState.value = await props.store.read(props.options)\n } catch (error) {\n console.error('Error loading entities:', error)\n entitiesState.value = []\n } finally {\n isLoading.value = false\n }\n \n // Initialize native carousel after entities are loaded\n if (entitiesState.value.length && carouselRef.value) {\n // Listen for scroll end using intersection observer for better performance\n const container = carouselRef.value.querySelector('.carousel__container')\n const slides = container.querySelectorAll('.carousel__slide')\n \n // Create intersection observer to detect when slides are visible\n const observer = new IntersectionObserver((entries) => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n // Find the index of the visible slide\n const slideIndex = Array.from(slides).indexOf(entry.target)\n if (slideIndex !== -1) {\n selectedIndex.value = slideIndex\n }\n }\n })\n }, {\n root: container,\n threshold: 0.7 // Consider slide visible when 70% is in view\n })\n \n // Observe all slides\n slides.forEach(slide => {\n observer.observe(slide)\n })\n \n // Add focus/blur events to pause autoplay on focus\n container.addEventListener('focusin', () => {\n if (autoplayInterval.value) {\n clearInterval(autoplayInterval.value)\n }\n })\n \n container.addEventListener('focusout', () => {\n setupAutoplay()\n })\n \n // Stop autoplay on touch/mouse interaction\n container.addEventListener('mousedown', () => {\n if (autoplayInterval.value) {\n clearInterval(autoplayInterval.value)\n }\n })\n \n container.addEventListener('touchstart', () => {\n if (autoplayInterval.value) {\n clearInterval(autoplayInterval.value)\n }\n })\n \n // Resume autoplay after interaction ends\n container.addEventListener('mouseup', () => {\n setupAutoplay()\n })\n \n container.addEventListener('touchend', () => {\n setupAutoplay()\n })\n \n // Initialize autoplay\n setupAutoplay()\n \n // Store observer for cleanup\n carouselRef.value._observer = observer\n }\n})\n\nonBeforeUnmount(() => {\n // Clean up all resources\n if (carouselRef.value) {\n // Clean up intersection observer\n if (carouselRef.value._observer) {\n carouselRef.value._observer.disconnect()\n }\n \n // Clean up event listeners\n const container = carouselRef.value.querySelector('.carousel__container')\n if (container) {\n container.removeEventListener('focusin', () => {})\n container.removeEventListener('focusout', () => {})\n container.removeEventListener('mousedown', () => {})\n container.removeEventListener('touchstart', () => {})\n container.removeEventListener('mouseup', () => {})\n container.removeEventListener('touchend', () => {})\n }\n }\n \n // Clear all timeouts and intervals\n if (autoplayInterval.value) {\n clearInterval(autoplayInterval.value)\n }\n \n if (scrollTimeout.value) {\n clearTimeout(scrollTimeout.value)\n }\n})\n\n// Watch for changes in entities to reinitialize if needed\nwatch(entitiesState, (newValue) => {\n if (newValue.length && carouselRef.value) {\n // Reset to first slide\n selectedIndex.value = 0\n scrollTo(0)\n \n // Reset autoplay\n setupAutoplay()\n }\n})\n</script>\n\n<style scoped>\n.carousel {\n position: relative;\n width: 100%;\n overflow: hidden;\n}\n\n.carousel__container {\n display: flex;\n scroll-snap-type: x mandatory;\n overflow-x: scroll;\n scrollbar-width: none; /* Firefox */\n -ms-overflow-style: none; /* IE and Edge */\n scroll-behavior: smooth;\n}\n\n.carousel__container::-webkit-scrollbar {\n display: none; /* Chrome, Safari, Opera */\n}\n\n.carousel__slide {\n flex: 0 0 100%;\n width: 100%;\n scroll-snap-align: start;\n scroll-snap-stop: always;\n}\n\n/* Navigation dots */\n.carousel__dots {\n display: flex;\n justify-content: center;\n gap: 0.5rem;\n margin-top: 1rem;\n}\n\n.carousel__dot {\n width: 0.625rem;\n height: 0.625rem;\n border-radius: 50%;\n background-color: rgba(0, 0, 0, 0.2);\n border: none;\n padding: 0;\n cursor: pointer;\n transition: background-color 0.3s ease;\n}\n\n.carousel__dot--active {\n background-color: rgba(0, 0, 0, 0.6);\n}\n\n.fade-enter-active,\n.fade-leave-active {\n transition: opacity 0.3s ease;\n}\n\n.fade-enter-from,\n.fade-leave-to {\n opacity: 0;\n}\n</style>"],"names":["useRouter","ref","useI18n","onMounted","onBeforeUnmount","watch"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDA,UAAM,QAAQ;AAQCA,cAAS,UAAA;AACxB,UAAM,cAAcC,IAAG,IAAC,IAAI;AAC5B,UAAM,gBAAgBA,IAAG,IAAC,CAAE,CAAA;AAC5B,UAAM,YAAYA,IAAG,IAAC,IAAI;AAC1B,UAAM,gBAAgBA,IAAG,IAAC,CAAC;AAC3B,UAAM,mBAAmBA,IAAG,IAAC,IAAI;AACjC,UAAM,gBAAgBA,IAAG,IAAC,IAAI;AAE9B,UAAM,EAAE,EAAG,IAAGC,gBAAQ;AAAA,MACpB,UAAU,MAAM;AAAA,IAClB,CAAC;AAGD,UAAM,WAAW,CAAC,UAAU;AAC1B,UAAI,CAAC,YAAY,MAAO;AAExB,YAAM,YAAY,YAAY,MAAM,cAAc,sBAAsB;AACxE,YAAM,SAAS,UAAU,iBAAiB,kBAAkB;AAE5D,UAAI,OAAO,KAAK,GAAG;AACjB,kBAAU,SAAS;AAAA,UACjB,MAAM,OAAO,KAAK,EAAE;AAAA,UACpB,UAAU;AAAA,QACX,CAAA;AAED,sBAAc,QAAQ;AAAA,MAC1B;AAAA,IACA;AAGA,UAAM,eAAe,MAAM;AAEzB,UAAI,cAAc,OAAO;AACvB,qBAAa,cAAc,KAAK;AAAA,MACpC;AAGE,oBAAc,QAAQ,WAAW,MAAM;AACrC,4BAAmB;AAAA,MACpB,GAAE,EAAE;AAAA,IACP;AAGA,UAAM,sBAAsB,MAAM;AAChC,UAAI,CAAC,YAAY,MAAO;AAExB,YAAM,YAAY,YAAY,MAAM,cAAc,sBAAsB;AACxE,YAAM,SAAS,UAAU,iBAAiB,kBAAkB;AAE5D,UAAI,CAAC,OAAO,OAAQ;AAEpB,YAAM,iBAAiB,UAAU;AACjC,YAAM,aAAa,OAAO,CAAC,EAAE;AAG7B,YAAM,QAAQ,KAAK,MAAM,iBAAiB,UAAU;AAGpD,YAAM,eAAe,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,cAAc,MAAM,SAAS,CAAC,CAAC;AAGhF,oBAAc,QAAQ;AAAA,IACxB;AAGA,UAAM,gBAAgB,MAAM;AAC1B,UAAI,iBAAiB,OAAO;AAC1B,sBAAc,iBAAiB,KAAK;AAAA,MACxC;AAEE,uBAAiB,QAAQ,YAAY,MAAM;AACzC,cAAM,aAAa,cAAc,QAAQ,KAAK,cAAc,MAAM;AAClE,iBAAS,SAAS;AAAA,MACnB,GAAE,GAAI;AAAA,IACT;AAEAC,QAAAA,UAAU,YAAW;AACnB,UAAI;AACF,sBAAc,QAAQ,MAAM,MAAM,MAAM,KAAK,MAAM,OAAO;AAAA,MAC3D,SAAQ,OAAO;AACd,gBAAQ,MAAM,2BAA2B,KAAK;AAC9C,sBAAc,QAAQ,CAAA;AAAA,MAC1B,UAAY;AACR,kBAAU,QAAQ;AAAA,MACtB;AAGE,UAAI,cAAc,MAAM,UAAU,YAAY,OAAO;AAEnD,cAAM,YAAY,YAAY,MAAM,cAAc,sBAAsB;AACxE,cAAM,SAAS,UAAU,iBAAiB,kBAAkB;AAG5D,cAAM,WAAW,IAAI,qBAAqB,CAAC,YAAY;AACrD,kBAAQ,QAAQ,WAAS;AACvB,gBAAI,MAAM,gBAAgB;AAExB,oBAAM,aAAa,MAAM,KAAK,MAAM,EAAE,QAAQ,MAAM,MAAM;AAC1D,kBAAI,eAAe,IAAI;AACrB,8BAAc,QAAQ;AAAA,cAClC;AAAA,YACA;AAAA,UACO,CAAA;AAAA,QACP,GAAO;AAAA,UACD,MAAM;AAAA,UACN,WAAW;AAAA;AAAA,QACZ,CAAA;AAGD,eAAO,QAAQ,WAAS;AACtB,mBAAS,QAAQ,KAAK;AAAA,QACvB,CAAA;AAGD,kBAAU,iBAAiB,WAAW,MAAM;AAC1C,cAAI,iBAAiB,OAAO;AAC1B,0BAAc,iBAAiB,KAAK;AAAA,UAC5C;AAAA,QACK,CAAA;AAED,kBAAU,iBAAiB,YAAY,MAAM;AAC3C,wBAAa;AAAA,QACd,CAAA;AAGD,kBAAU,iBAAiB,aAAa,MAAM;AAC5C,cAAI,iBAAiB,OAAO;AAC1B,0BAAc,iBAAiB,KAAK;AAAA,UAC5C;AAAA,QACK,CAAA;AAED,kBAAU,iBAAiB,cAAc,MAAM;AAC7C,cAAI,iBAAiB,OAAO;AAC1B,0BAAc,iBAAiB,KAAK;AAAA,UAC5C;AAAA,QACK,CAAA;AAGD,kBAAU,iBAAiB,WAAW,MAAM;AAC1C,wBAAa;AAAA,QACd,CAAA;AAED,kBAAU,iBAAiB,YAAY,MAAM;AAC3C,wBAAa;AAAA,QACd,CAAA;AAGD,sBAAa;AAGb,oBAAY,MAAM,YAAY;AAAA,MAClC;AAAA,IACA,CAAC;AAEDC,QAAAA,gBAAgB,MAAM;AAEpB,UAAI,YAAY,OAAO;AAErB,YAAI,YAAY,MAAM,WAAW;AAC/B,sBAAY,MAAM,UAAU,WAAU;AAAA,QAC5C;AAGI,cAAM,YAAY,YAAY,MAAM,cAAc,sBAAsB;AACxE,YAAI,WAAW;AACb,oBAAU,oBAAoB,WAAW,MAAM;AAAA,UAAE,CAAA;AACjD,oBAAU,oBAAoB,YAAY,MAAM;AAAA,UAAE,CAAA;AAClD,oBAAU,oBAAoB,aAAa,MAAM;AAAA,UAAE,CAAA;AACnD,oBAAU,oBAAoB,cAAc,MAAM;AAAA,UAAE,CAAA;AACpD,oBAAU,oBAAoB,WAAW,MAAM;AAAA,UAAE,CAAA;AACjD,oBAAU,oBAAoB,YAAY,MAAM;AAAA,UAAE,CAAA;AAAA,QACxD;AAAA,MACA;AAGE,UAAI,iBAAiB,OAAO;AAC1B,sBAAc,iBAAiB,KAAK;AAAA,MACxC;AAEE,UAAI,cAAc,OAAO;AACvB,qBAAa,cAAc,KAAK;AAAA,MACpC;AAAA,IACA,CAAC;AAGDC,QAAAA,MAAM,eAAe,CAAC,aAAa;AACjC,UAAI,SAAS,UAAU,YAAY,OAAO;AAExC,sBAAc,QAAQ;AACtB,iBAAS,CAAC;AAGV,sBAAa;AAAA,MACjB;AAAA,IACA,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}