spree_storefront 5.0.0.rc1

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 (341) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +13 -0
  3. data/Rakefile +15 -0
  4. data/app/assets/config/spree_storefront_manifest.js +6 -0
  5. data/app/assets/stylesheets/storefront_page_builder.css +51 -0
  6. data/app/controllers/concerns/spree/cart_methods.rb +40 -0
  7. data/app/controllers/concerns/spree/locale_urls.rb +23 -0
  8. data/app/controllers/concerns/spree/password_protected.rb +17 -0
  9. data/app/controllers/concerns/spree/theme_concern.rb +29 -0
  10. data/app/controllers/spree/account/addresses_controller.rb +16 -0
  11. data/app/controllers/spree/account/base_controller.rb +20 -0
  12. data/app/controllers/spree/account/newsletter_controller.rb +34 -0
  13. data/app/controllers/spree/account/orders_controller.rb +34 -0
  14. data/app/controllers/spree/account/profile_controller.rb +23 -0
  15. data/app/controllers/spree/account/store_credits_controller.rb +23 -0
  16. data/app/controllers/spree/account/wished_items_controller.rb +45 -0
  17. data/app/controllers/spree/addresses_controller.rb +101 -0
  18. data/app/controllers/spree/checkout_controller.rb +365 -0
  19. data/app/controllers/spree/contacts_controller.rb +46 -0
  20. data/app/controllers/spree/digital_links_controller.rb +48 -0
  21. data/app/controllers/spree/home_controller.rb +5 -0
  22. data/app/controllers/spree/line_items_controller.rb +96 -0
  23. data/app/controllers/spree/newsletter_subscribers_controller.rb +43 -0
  24. data/app/controllers/spree/order_status_controller.rb +32 -0
  25. data/app/controllers/spree/orders_controller.rb +104 -0
  26. data/app/controllers/spree/page_sections_controller.rb +17 -0
  27. data/app/controllers/spree/pages_controller.rb +13 -0
  28. data/app/controllers/spree/password_controller.rb +21 -0
  29. data/app/controllers/spree/policies_controller.rb +17 -0
  30. data/app/controllers/spree/posts_controller.rb +76 -0
  31. data/app/controllers/spree/products_controller.rb +99 -0
  32. data/app/controllers/spree/search_controller.rb +39 -0
  33. data/app/controllers/spree/seo_controller.rb +25 -0
  34. data/app/controllers/spree/settings_controller.rb +68 -0
  35. data/app/controllers/spree/store_controller.rb +247 -0
  36. data/app/controllers/spree/taxonomies_controller.rb +30 -0
  37. data/app/controllers/spree/taxons_controller.rb +46 -0
  38. data/app/controllers/spree/wishlists_controller.rb +19 -0
  39. data/app/finders/spree/storefront/variant_finder.rb +80 -0
  40. data/app/helpers/spree/analytics_helper.rb +28 -0
  41. data/app/helpers/spree/cart_helper.rb +48 -0
  42. data/app/helpers/spree/checkout_analytics_helper.rb +77 -0
  43. data/app/helpers/spree/checkout_helper.rb +58 -0
  44. data/app/helpers/spree/filters_helper.rb +180 -0
  45. data/app/helpers/spree/fonts_helper.rb +58 -0
  46. data/app/helpers/spree/orders_helper.rb +7 -0
  47. data/app/helpers/spree/page_helper.rb +67 -0
  48. data/app/helpers/spree/posts_helper.rb +42 -0
  49. data/app/helpers/spree/products_helper.rb +205 -0
  50. data/app/helpers/spree/storefront_helper.rb +86 -0
  51. data/app/helpers/spree/storefront_locale_helper.rb +42 -0
  52. data/app/helpers/spree/theme_helper.rb +244 -0
  53. data/app/helpers/spree/turbo_helper.rb +13 -0
  54. data/app/helpers/spree/turbo_stream_actions_helper.rb +13 -0
  55. data/app/helpers/spree/wishlist_helper.rb +7 -0
  56. data/app/javascript/spree/storefront/application.js +156 -0
  57. data/app/javascript/spree/storefront/controllers/accordion_controller.js +25 -0
  58. data/app/javascript/spree/storefront/controllers/account_nav_controller.js +10 -0
  59. data/app/javascript/spree/storefront/controllers/card_validation_controller.js +103 -0
  60. data/app/javascript/spree/storefront/controllers/carousel_controller.js +44 -0
  61. data/app/javascript/spree/storefront/controllers/cart_controller.js +10 -0
  62. data/app/javascript/spree/storefront/controllers/checkout_address_book_controller.js +28 -0
  63. data/app/javascript/spree/storefront/controllers/checkout_delivery_controller.js +39 -0
  64. data/app/javascript/spree/storefront/controllers/checkout_promotions_controller.js +28 -0
  65. data/app/javascript/spree/storefront/controllers/checkout_summary_controller.js +46 -0
  66. data/app/javascript/spree/storefront/controllers/clear_input_controller.js +23 -0
  67. data/app/javascript/spree/storefront/controllers/copy_input_controller.js +19 -0
  68. data/app/javascript/spree/storefront/controllers/dropdown_controller.js +14 -0
  69. data/app/javascript/spree/storefront/controllers/header_controller.js +33 -0
  70. data/app/javascript/spree/storefront/controllers/infinite_scroll_controller.js +31 -0
  71. data/app/javascript/spree/storefront/controllers/lightbox_controller.js +138 -0
  72. data/app/javascript/spree/storefront/controllers/mobile_nav_controller.js +17 -0
  73. data/app/javascript/spree/storefront/controllers/modal_controller.js +15 -0
  74. data/app/javascript/spree/storefront/controllers/no_ui_slider_controller.js +55 -0
  75. data/app/javascript/spree/storefront/controllers/pdp_desktop_gallery_controller.js +28 -0
  76. data/app/javascript/spree/storefront/controllers/plp_variant_picker_controller.js +151 -0
  77. data/app/javascript/spree/storefront/controllers/product_form_controller.js +136 -0
  78. data/app/javascript/spree/storefront/controllers/quantity_picker_controller.js +43 -0
  79. data/app/javascript/spree/storefront/controllers/search_suggestions_controller.js +61 -0
  80. data/app/javascript/spree/storefront/controllers/searchable_list_controller.js +25 -0
  81. data/app/javascript/spree/storefront/controllers/slideover_controller.js +40 -0
  82. data/app/javascript/spree/storefront/controllers/sticky_button_controller.js +32 -0
  83. data/app/javascript/spree/storefront/controllers/toggle_menu_controller.js +32 -0
  84. data/app/javascript/spree/storefront/controllers/turbo_stream_form_controller.js +51 -0
  85. data/app/javascript/spree/storefront/controllers/wished_item_controller.js +69 -0
  86. data/app/javascript/spree/storefront/helpers/lazy_load_controllers_with_manifest.js +78 -0
  87. data/app/javascript/spree/storefront/helpers/show_flash_message.js +25 -0
  88. data/app/models/spree/color_names.rb +35 -0
  89. data/app/models/spree/contact.rb +24 -0
  90. data/app/presenters/spree/colors_preview_styles_presenter.rb +84 -0
  91. data/app/presenters/spree/featured_product_presenter.rb +42 -0
  92. data/app/presenters/spree/mega_nav_presenter.rb +55 -0
  93. data/app/views/devise/passwords/edit.html.erb +22 -0
  94. data/app/views/devise/passwords/new.html.erb +16 -0
  95. data/app/views/devise/registrations/_form.html.erb +21 -0
  96. data/app/views/devise/registrations/edit.html.erb +24 -0
  97. data/app/views/devise/registrations/new.html.erb +27 -0
  98. data/app/views/devise/sessions/new.html.erb +25 -0
  99. data/app/views/devise/shared/_links.html.erb +22 -0
  100. data/app/views/layouts/spree/checkout.html.erb +58 -0
  101. data/app/views/layouts/spree/password.html.erb +34 -0
  102. data/app/views/layouts/spree/storefront.html.erb +38 -0
  103. data/app/views/spree/account/wished_items/create.turbo_stream.erb +8 -0
  104. data/app/views/spree/account/wished_items/destroy.turbo_stream.erb +20 -0
  105. data/app/views/spree/addresses/destroy.turbo_stream.erb +1 -0
  106. data/app/views/spree/addresses/edit.html.erb +57 -0
  107. data/app/views/spree/addresses/new.html.erb +71 -0
  108. data/app/views/spree/checkout/_address.html.erb +153 -0
  109. data/app/views/spree/checkout/_button_processing.html.erb +7 -0
  110. data/app/views/spree/checkout/_coupon_code.html.erb +55 -0
  111. data/app/views/spree/checkout/_credit_card.html.erb +12 -0
  112. data/app/views/spree/checkout/_delivery.html.erb +70 -0
  113. data/app/views/spree/checkout/_line_item.html.erb +26 -0
  114. data/app/views/spree/checkout/_line_items.html.erb +7 -0
  115. data/app/views/spree/checkout/_missing_all_line_items.html.erb +17 -0
  116. data/app/views/spree/checkout/_missing_line_items.html.erb +28 -0
  117. data/app/views/spree/checkout/_payment.html.erb +35 -0
  118. data/app/views/spree/checkout/_payment_methods.html.erb +72 -0
  119. data/app/views/spree/checkout/_payment_sources.html.erb +24 -0
  120. data/app/views/spree/checkout/_quick_checkout.html.erb +1 -0
  121. data/app/views/spree/checkout/_sidebar.html.erb +34 -0
  122. data/app/views/spree/checkout/_store_credit.html.erb +21 -0
  123. data/app/views/spree/checkout/_summary.html.erb +116 -0
  124. data/app/views/spree/checkout/_user_account.html.erb +9 -0
  125. data/app/views/spree/checkout/apply_coupon_code.turbo_stream.erb +45 -0
  126. data/app/views/spree/checkout/apply_store_credit.turbo_stream.erb +19 -0
  127. data/app/views/spree/checkout/edit.html.erb +98 -0
  128. data/app/views/spree/checkout/payment/_check.html.erb +0 -0
  129. data/app/views/spree/checkout/payment/_gateway.html.erb +74 -0
  130. data/app/views/spree/checkout/payment/_store_credit.html.erb +13 -0
  131. data/app/views/spree/checkout/remove_coupon_code.turbo_stream.erb +34 -0
  132. data/app/views/spree/checkout/remove_store_credit.turbo_stream.erb +19 -0
  133. data/app/views/spree/checkout/update.turbo_stream.erb +25 -0
  134. data/app/views/spree/home/index.html.erb +1 -0
  135. data/app/views/spree/line_items/create.turbo_stream.erb +13 -0
  136. data/app/views/spree/line_items/destroy.turbo_stream.erb +11 -0
  137. data/app/views/spree/line_items/update.turbo_stream.erb +10 -0
  138. data/app/views/spree/newsletter_subscribers/create.turbo_stream.erb +7 -0
  139. data/app/views/spree/order_status/new.html.erb +16 -0
  140. data/app/views/spree/page_sections/show.html.erb +3 -0
  141. data/app/views/spree/pages/show.html.erb +1 -0
  142. data/app/views/spree/password/show.html.erb +1 -0
  143. data/app/views/spree/posts/index.html.erb +1 -0
  144. data/app/views/spree/posts/related_products.html.erb +7 -0
  145. data/app/views/spree/posts/show.html.erb +1 -0
  146. data/app/views/spree/products/index.html.erb +1 -0
  147. data/app/views/spree/products/index.turbo_stream.erb +1 -0
  148. data/app/views/spree/products/related.html.erb +3 -0
  149. data/app/views/spree/products/show.html.erb +1 -0
  150. data/app/views/spree/search/show.html.erb +6 -0
  151. data/app/views/spree/search/show.turbo_stream.erb +1 -0
  152. data/app/views/spree/search/suggestions.turbo_stream.erb +8 -0
  153. data/app/views/spree/seo/robots.text.erb +31 -0
  154. data/app/views/spree/seo/sitemap.xml.erb +25 -0
  155. data/app/views/spree/shared/_fonts.html.erb +14 -0
  156. data/app/views/spree/shared/_head.html.erb +36 -0
  157. data/app/views/spree/shared/_load_more_products.turbo_stream.erb +7 -0
  158. data/app/views/spree/shared/_product_listing_page.html.erb +11 -0
  159. data/app/views/spree/shared/_products.html.erb +1 -0
  160. data/app/views/spree/taxonomies/show.html.erb +1 -0
  161. data/app/views/spree/taxons/show.html.erb +1 -0
  162. data/app/views/spree/taxons/show.turbo_stream.erb +1 -0
  163. data/app/views/spree/waitlists/create.turbo_stream.erb +9 -0
  164. data/app/views/themes/default/kaminari/storefront/_first_page.html.erb +8 -0
  165. data/app/views/themes/default/kaminari/storefront/_gap.html.erb +8 -0
  166. data/app/views/themes/default/kaminari/storefront/_last_page.html.erb +8 -0
  167. data/app/views/themes/default/kaminari/storefront/_next_page.html.erb +13 -0
  168. data/app/views/themes/default/kaminari/storefront/_page.html.erb +10 -0
  169. data/app/views/themes/default/kaminari/storefront/_paginator.html.erb +27 -0
  170. data/app/views/themes/default/kaminari/storefront/_prev_page.html.erb +13 -0
  171. data/app/views/themes/default/spree/account/_account_nav.html.erb +46 -0
  172. data/app/views/themes/default/spree/account/_order.html.erb +39 -0
  173. data/app/views/themes/default/spree/account/_orders.html.erb +16 -0
  174. data/app/views/themes/default/spree/account/addresses/_address.html.erb +42 -0
  175. data/app/views/themes/default/spree/account/addresses/index.html.erb +28 -0
  176. data/app/views/themes/default/spree/account/newsletter/_newsletter_settings.html.erb +13 -0
  177. data/app/views/themes/default/spree/account/newsletter/edit.html.erb +16 -0
  178. data/app/views/themes/default/spree/account/newsletter/update.html.erb +1 -0
  179. data/app/views/themes/default/spree/account/orders/index.html.erb +24 -0
  180. data/app/views/themes/default/spree/account/orders/show.html.erb +22 -0
  181. data/app/views/themes/default/spree/account/profile/edit.html.erb +36 -0
  182. data/app/views/themes/default/spree/account/store_credits/_store_credit_event.html.erb +29 -0
  183. data/app/views/themes/default/spree/account/store_credits/index.html.erb +31 -0
  184. data/app/views/themes/default/spree/checkout/_footer.html.erb +10 -0
  185. data/app/views/themes/default/spree/checkout/complete.html.erb +84 -0
  186. data/app/views/themes/default/spree/contacts/new.html.erb +23 -0
  187. data/app/views/themes/default/spree/orders/_cart.html.erb +14 -0
  188. data/app/views/themes/default/spree/orders/_empty.html.erb +11 -0
  189. data/app/views/themes/default/spree/orders/_line_item.html.erb +47 -0
  190. data/app/views/themes/default/spree/orders/_line_item_quantity.html.erb +11 -0
  191. data/app/views/themes/default/spree/orders/_summary.html.erb +41 -0
  192. data/app/views/themes/default/spree/orders/edit.html.erb +18 -0
  193. data/app/views/themes/default/spree/orders/show.html.erb +6 -0
  194. data/app/views/themes/default/spree/page_sections/_announcement_bar.html.erb +10 -0
  195. data/app/views/themes/default/spree/page_sections/_custom_code.html.erb +5 -0
  196. data/app/views/themes/default/spree/page_sections/_featured_product.html.erb +136 -0
  197. data/app/views/themes/default/spree/page_sections/_featured_taxon.html.erb +116 -0
  198. data/app/views/themes/default/spree/page_sections/_featured_taxons.html.erb +71 -0
  199. data/app/views/themes/default/spree/page_sections/_footer.html.erb +62 -0
  200. data/app/views/themes/default/spree/page_sections/_header.html.erb +166 -0
  201. data/app/views/themes/default/spree/page_sections/_image_banner.html.erb +57 -0
  202. data/app/views/themes/default/spree/page_sections/_image_with_text.html.erb +66 -0
  203. data/app/views/themes/default/spree/page_sections/_main_password_footer.html.erb +64 -0
  204. data/app/views/themes/default/spree/page_sections/_main_password_header.html.erb +54 -0
  205. data/app/views/themes/default/spree/page_sections/_newsletter.html.erb +47 -0
  206. data/app/views/themes/default/spree/page_sections/_page_title.html.erb +7 -0
  207. data/app/views/themes/default/spree/page_sections/_post_details.html.erb +19 -0
  208. data/app/views/themes/default/spree/page_sections/_post_grid.html.erb +11 -0
  209. data/app/views/themes/default/spree/page_sections/_product_details.html.erb +102 -0
  210. data/app/views/themes/default/spree/page_sections/_product_grid.html.erb +52 -0
  211. data/app/views/themes/default/spree/page_sections/_related_products.html.erb +15 -0
  212. data/app/views/themes/default/spree/page_sections/_rich_text.html.erb +18 -0
  213. data/app/views/themes/default/spree/page_sections/_taxon_banner.html.erb +37 -0
  214. data/app/views/themes/default/spree/page_sections/_taxon_grid.html.erb +103 -0
  215. data/app/views/themes/default/spree/page_sections/_video.html.erb +27 -0
  216. data/app/views/themes/default/spree/page_sections/nav/_desktop.html.erb +49 -0
  217. data/app/views/themes/default/spree/page_sections/nav/_mobile.html.erb +136 -0
  218. data/app/views/themes/default/spree/policies/show.html.erb +11 -0
  219. data/app/views/themes/default/spree/posts/_json_ld.html.erb +20 -0
  220. data/app/views/themes/default/spree/posts/_pagination.html.erb +1 -0
  221. data/app/views/themes/default/spree/posts/_post.html.erb +13 -0
  222. data/app/views/themes/default/spree/products/_add_to_cart_button.html.erb +58 -0
  223. data/app/views/themes/default/spree/products/_add_to_waitlist.html.erb +36 -0
  224. data/app/views/themes/default/spree/products/_add_to_wishlist.html.erb +33 -0
  225. data/app/views/themes/default/spree/products/_breadcrumbs.html.erb +23 -0
  226. data/app/views/themes/default/spree/products/_color_picker.html.erb +19 -0
  227. data/app/views/themes/default/spree/products/_color_swatches.html.erb +61 -0
  228. data/app/views/themes/default/spree/products/_details.html.erb +55 -0
  229. data/app/views/themes/default/spree/products/_featured_image.html.erb +37 -0
  230. data/app/views/themes/default/spree/products/_filters.html.erb +45 -0
  231. data/app/views/themes/default/spree/products/_json_ld.html.erb +38 -0
  232. data/app/views/themes/default/spree/products/_json_ld_list.html.erb +9 -0
  233. data/app/views/themes/default/spree/products/_json_ld_variant.html.erb +10 -0
  234. data/app/views/themes/default/spree/products/_label.html.erb +26 -0
  235. data/app/views/themes/default/spree/products/_media_gallery.html.erb +94 -0
  236. data/app/views/themes/default/spree/products/_price.html.erb +59 -0
  237. data/app/views/themes/default/spree/products/_product.html.erb +62 -0
  238. data/app/views/themes/default/spree/products/_quantity_selector.html.erb +32 -0
  239. data/app/views/themes/default/spree/products/_returns_policy_modal.html.erb +22 -0
  240. data/app/views/themes/default/spree/products/_show_more_button.html.erb +8 -0
  241. data/app/views/themes/default/spree/products/_sort.html.erb +45 -0
  242. data/app/views/themes/default/spree/products/_swiper.html.erb +85 -0
  243. data/app/views/themes/default/spree/products/_tags.html.erb +0 -0
  244. data/app/views/themes/default/spree/products/_variant_options.html.erb +71 -0
  245. data/app/views/themes/default/spree/products/_variant_picker.html.erb +50 -0
  246. data/app/views/themes/default/spree/products/filters/_availability.html.erb +32 -0
  247. data/app/views/themes/default/spree/products/filters/_colors.html.erb +23 -0
  248. data/app/views/themes/default/spree/products/filters/_generic.html.erb +75 -0
  249. data/app/views/themes/default/spree/products/filters/_price.html.erb +35 -0
  250. data/app/views/themes/default/spree/products/filters/_taxons.erb +78 -0
  251. data/app/views/themes/default/spree/search/_suggestions.html.erb +92 -0
  252. data/app/views/themes/default/spree/settings/show.html.erb +32 -0
  253. data/app/views/themes/default/spree/shared/_account_pane.html.erb +28 -0
  254. data/app/views/themes/default/spree/shared/_address.html.erb +35 -0
  255. data/app/views/themes/default/spree/shared/_cart_icon.html.erb +13 -0
  256. data/app/views/themes/default/spree/shared/_cart_pane.html.erb +38 -0
  257. data/app/views/themes/default/spree/shared/_css_variables.html.erb +54 -0
  258. data/app/views/themes/default/spree/shared/_custom_head.html.erb +0 -0
  259. data/app/views/themes/default/spree/shared/_error_messages.html.erb +9 -0
  260. data/app/views/themes/default/spree/shared/_error_messages_without_base_attribute.html.erb +15 -0
  261. data/app/views/themes/default/spree/shared/_flash.html.erb +16 -0
  262. data/app/views/themes/default/spree/shared/_flashes.html.erb +10 -0
  263. data/app/views/themes/default/spree/shared/_json_ld.html.erb +32 -0
  264. data/app/views/themes/default/spree/shared/_line_item_options.html.erb +18 -0
  265. data/app/views/themes/default/spree/shared/_logo.html.erb +42 -0
  266. data/app/views/themes/default/spree/shared/_meta_tags.html.erb +45 -0
  267. data/app/views/themes/default/spree/shared/_order_details.html.erb +106 -0
  268. data/app/views/themes/default/spree/shared/_order_line_item.html.erb +65 -0
  269. data/app/views/themes/default/spree/shared/_order_shipment.html.erb +71 -0
  270. data/app/views/themes/default/spree/shared/_search.html.erb +32 -0
  271. data/app/views/themes/default/spree/shared/_title.html.erb +3 -0
  272. data/app/views/themes/default/spree/shared/_wishlist_icon.html.erb +13 -0
  273. data/app/views/themes/default/spree/shared/icons/_account.html.erb +17 -0
  274. data/app/views/themes/default/spree/shared/icons/_arrow-left.html.erb +8 -0
  275. data/app/views/themes/default/spree/shared/icons/_arrow-right.html.erb +3 -0
  276. data/app/views/themes/default/spree/shared/icons/_bell.html.erb +9 -0
  277. data/app/views/themes/default/spree/shared/icons/_cart.html.erb +10 -0
  278. data/app/views/themes/default/spree/shared/icons/_cart_48.html.erb +6 -0
  279. data/app/views/themes/default/spree/shared/icons/_check.html.erb +4 -0
  280. data/app/views/themes/default/spree/shared/icons/_chevron.html.erb +15 -0
  281. data/app/views/themes/default/spree/shared/icons/_chevron_down.html.erb +5 -0
  282. data/app/views/themes/default/spree/shared/icons/_chevron_right.html.erb +15 -0
  283. data/app/views/themes/default/spree/shared/icons/_chevron_up.html.erb +3 -0
  284. data/app/views/themes/default/spree/shared/icons/_close.html.erb +9 -0
  285. data/app/views/themes/default/spree/shared/icons/_cross.html.erb +16 -0
  286. data/app/views/themes/default/spree/shared/icons/_delete.html.erb +3 -0
  287. data/app/views/themes/default/spree/shared/icons/_delivery.html.erb +5 -0
  288. data/app/views/themes/default/spree/shared/icons/_disabled.html.erb +13 -0
  289. data/app/views/themes/default/spree/shared/icons/_edit.html.erb +3 -0
  290. data/app/views/themes/default/spree/shared/icons/_facebook.html.erb +16 -0
  291. data/app/views/themes/default/spree/shared/icons/_filter.html.erb +8 -0
  292. data/app/views/themes/default/spree/shared/icons/_heart.html.erb +12 -0
  293. data/app/views/themes/default/spree/shared/icons/_info.html.erb +7 -0
  294. data/app/views/themes/default/spree/shared/icons/_instagram.html.erb +18 -0
  295. data/app/views/themes/default/spree/shared/icons/_lock.html.erb +13 -0
  296. data/app/views/themes/default/spree/shared/icons/_menu.html.erb +10 -0
  297. data/app/views/themes/default/spree/shared/icons/_minus.html.erb +5 -0
  298. data/app/views/themes/default/spree/shared/icons/_pinch.html.erb +6 -0
  299. data/app/views/themes/default/spree/shared/icons/_pinterest.html.erb +8 -0
  300. data/app/views/themes/default/spree/shared/icons/_plus.html.erb +17 -0
  301. data/app/views/themes/default/spree/shared/icons/_return.html.erb +11 -0
  302. data/app/views/themes/default/spree/shared/icons/_search.html.erb +17 -0
  303. data/app/views/themes/default/spree/shared/icons/_spinner.html.erb +1 -0
  304. data/app/views/themes/default/spree/shared/icons/_spotify.html.erb +8 -0
  305. data/app/views/themes/default/spree/shared/icons/_tiktok.html.erb +9 -0
  306. data/app/views/themes/default/spree/shared/icons/_twitter.html.erb +16 -0
  307. data/app/views/themes/default/spree/shared/icons/_youtube.html.erb +9 -0
  308. data/app/views/themes/default/spree/shared/icons/_zoom.html.erb +10 -0
  309. data/app/views/themes/default/spree/wishlists/_no_wished_items.html.erb +10 -0
  310. data/app/views/themes/default/spree/wishlists/_wished_item.html.erb +38 -0
  311. data/app/views/themes/default/spree/wishlists/show.html.erb +17 -0
  312. data/config/i18n-tasks.yml +176 -0
  313. data/config/importmap.rb +22 -0
  314. data/config/initializers/assets.rb +1 -0
  315. data/config/initializers/heroicon.rb +10 -0
  316. data/config/locales/en.yml +76 -0
  317. data/config/routes.rb +88 -0
  318. data/lib/generators/spree/storefront/install/install_generator.rb +45 -0
  319. data/lib/generators/spree/storefront/install/templates/application.tailwind.css +1760 -0
  320. data/lib/generators/spree/storefront/install/templates/dev +16 -0
  321. data/lib/generators/spree/storefront/install/templates/tailwind.config.js +128 -0
  322. data/lib/generators/spree/storefront/theme/templates/model.rb.tt +12 -0
  323. data/lib/generators/spree/storefront/theme/theme_generator.rb +41 -0
  324. data/lib/spree/storefront/configuration.rb +11 -0
  325. data/lib/spree/storefront/engine.rb +51 -0
  326. data/lib/spree/storefront/testing_support/capybara_utils.rb +13 -0
  327. data/lib/spree/storefront.rb +16 -0
  328. data/lib/spree_storefront.rb +1 -0
  329. data/vendor/colornames.json +1 -0
  330. data/vendor/javascript/@kanety--stimulus-accordion.js +4 -0
  331. data/vendor/javascript/@stimulus-components--carousel.js +4 -0
  332. data/vendor/javascript/card-validator.js +4 -0
  333. data/vendor/javascript/credit-card-type.js +4 -0
  334. data/vendor/javascript/headroom.js.js +19 -0
  335. data/vendor/javascript/nouislider.js +4 -0
  336. data/vendor/javascript/photoswipe--dist--photoswipe-lightbox.esm.js.js +667 -0
  337. data/vendor/javascript/photoswipe.js +1675 -0
  338. data/vendor/javascript/stimulus-read-more.js +4 -0
  339. data/vendor/javascript/stimulus-scroll-to.js +4 -0
  340. data/vendor/javascript/swiper--bundle.js +4 -0
  341. metadata +567 -0
@@ -0,0 +1,1675 @@
1
+ // photoswipe@5.4.4 downloaded from https://ga.jspm.io/npm:photoswipe@5.4.4/dist/photoswipe.esm.js
2
+
3
+ /** @typedef {import('../photoswipe.js').Point} Point */
4
+ /**
5
+ * @template {keyof HTMLElementTagNameMap} T
6
+ * @param {string} className
7
+ * @param {T} tagName
8
+ * @param {Node} [appendToEl]
9
+ * @returns {HTMLElementTagNameMap[T]}
10
+ */
11
+ function createElement(t,e,i){const s=document.createElement(e);t&&(s.className=t);i&&i.appendChild(s);return s}
12
+ /**
13
+ * @param {Point} p1
14
+ * @param {Point} p2
15
+ * @returns {Point}
16
+ */function equalizePoints(t,e){t.x=e.x;t.y=e.y;e.id!==void 0&&(t.id=e.id);return t}
17
+ /**
18
+ * @param {Point} p
19
+ */function roundPoint(t){t.x=Math.round(t.x);t.y=Math.round(t.y)}
20
+ /**
21
+ * Returns distance between two points.
22
+ *
23
+ * @param {Point} p1
24
+ * @param {Point} p2
25
+ * @returns {number}
26
+ */function getDistanceBetween(t,e){const i=Math.abs(t.x-e.x);const s=Math.abs(t.y-e.y);return Math.sqrt(i*i+s*s)}
27
+ /**
28
+ * Whether X and Y positions of points are equal
29
+ *
30
+ * @param {Point} p1
31
+ * @param {Point} p2
32
+ * @returns {boolean}
33
+ */function pointsEqual(t,e){return t.x===e.x&&t.y===e.y}
34
+ /**
35
+ * The float result between the min and max values.
36
+ *
37
+ * @param {number} val
38
+ * @param {number} min
39
+ * @param {number} max
40
+ * @returns {number}
41
+ */function clamp(t,e,i){return Math.min(Math.max(t,e),i)}
42
+ /**
43
+ * Get transform string
44
+ *
45
+ * @param {number} x
46
+ * @param {number} [y]
47
+ * @param {number} [scale]
48
+ * @returns {string}
49
+ */function toTransformString(t,e,i){let s=`translate3d(${t}px,${e||0}px,0)`;i!==void 0&&(s+=` scale3d(${i},${i},1)`);return s}
50
+ /**
51
+ * Apply transform:translate(x, y) scale(scale) to element
52
+ *
53
+ * @param {HTMLElement} el
54
+ * @param {number} x
55
+ * @param {number} [y]
56
+ * @param {number} [scale]
57
+ */function setTransform(t,e,i,s){t.style.transform=toTransformString(e,i,s)}const t="cubic-bezier(.4,0,.22,1)";
58
+ /**
59
+ * Apply CSS transition to element
60
+ *
61
+ * @param {HTMLElement} el
62
+ * @param {string} [prop] CSS property to animate
63
+ * @param {number} [duration] in ms
64
+ * @param {string} [ease] CSS easing function
65
+ */function setTransitionStyle(e,i,s,n){e.style.transition=i?`${i} ${s}ms ${n||t}`:"none"}
66
+ /**
67
+ * Apply width and height CSS properties to element
68
+ *
69
+ * @param {HTMLElement} el
70
+ * @param {string | number} w
71
+ * @param {string | number} h
72
+ */function setWidthHeight(t,e,i){t.style.width=typeof e==="number"?`${e}px`:e;t.style.height=typeof i==="number"?`${i}px`:i}
73
+ /**
74
+ * @param {HTMLElement} el
75
+ */function removeTransitionStyle(t){setTransitionStyle(t)}
76
+ /**
77
+ * @param {HTMLImageElement} img
78
+ * @returns {Promise<HTMLImageElement | void>}
79
+ */function decodeImage(t){return"decode"in t?t.decode().catch((()=>{})):t.complete?Promise.resolve(t):new Promise(((e,i)=>{t.onload=()=>e(t);t.onerror=i}))}
80
+ /** @typedef {LOAD_STATE[keyof LOAD_STATE]} LoadState */
81
+ /** @type {{ IDLE: 'idle'; LOADING: 'loading'; LOADED: 'loaded'; ERROR: 'error' }} */const e={IDLE:"idle",LOADING:"loading",LOADED:"loaded",ERROR:"error"};
82
+ /**
83
+ * Check if click or keydown event was dispatched
84
+ * with a special key or via mouse wheel.
85
+ *
86
+ * @param {MouseEvent | KeyboardEvent} e
87
+ * @returns {boolean}
88
+ */function specialKeyUsed(t){return"button"in t&&t.button===1||t.ctrlKey||t.metaKey||t.altKey||t.shiftKey}
89
+ /**
90
+ * Parse `gallery` or `children` options.
91
+ *
92
+ * @param {import('../photoswipe.js').ElementProvider} [option]
93
+ * @param {string} [legacySelector]
94
+ * @param {HTMLElement | Document} [parent]
95
+ * @returns HTMLElement[]
96
+ */function getElementsFromOption(t,e,i=document){
97
+ /** @type {HTMLElement[]} */
98
+ let s=[];if(t instanceof Element)s=[t];else if(t instanceof NodeList||Array.isArray(t))s=Array.from(t);else{const n=typeof t==="string"?t:e;n&&(s=Array.from(i.querySelectorAll(n)))}return s}
99
+ /**
100
+ * Check if browser is Safari
101
+ *
102
+ * @returns {boolean}
103
+ */function isSafari(){return!!(navigator.vendor&&navigator.vendor.match(/apple/i))}let i=false;try{window.addEventListener("test",null,Object.defineProperty({},"passive",{get:()=>{i=true}}))}catch(t){}
104
+ /**
105
+ * @typedef {Object} PoolItem
106
+ * @prop {HTMLElement | Window | Document | undefined | null} target
107
+ * @prop {string} type
108
+ * @prop {EventListenerOrEventListenerObject} listener
109
+ * @prop {boolean} [passive]
110
+ */class DOMEvents{constructor(){
111
+ /**
112
+ * @type {PoolItem[]}
113
+ * @private
114
+ */
115
+ this._pool=[]}
116
+ /**
117
+ * Adds event listeners
118
+ *
119
+ * @param {PoolItem['target']} target
120
+ * @param {PoolItem['type']} type Can be multiple, separated by space.
121
+ * @param {PoolItem['listener']} listener
122
+ * @param {PoolItem['passive']} [passive]
123
+ */add(t,e,i,s){this._toggleListener(t,e,i,s)}
124
+ /**
125
+ * Removes event listeners
126
+ *
127
+ * @param {PoolItem['target']} target
128
+ * @param {PoolItem['type']} type
129
+ * @param {PoolItem['listener']} listener
130
+ * @param {PoolItem['passive']} [passive]
131
+ */remove(t,e,i,s){this._toggleListener(t,e,i,s,true)}removeAll(){this._pool.forEach((t=>{this._toggleListener(t.target,t.type,t.listener,t.passive,true,true)}));this._pool=[]}
132
+ /**
133
+ * Adds or removes event
134
+ *
135
+ * @private
136
+ * @param {PoolItem['target']} target
137
+ * @param {PoolItem['type']} type
138
+ * @param {PoolItem['listener']} listener
139
+ * @param {PoolItem['passive']} [passive]
140
+ * @param {boolean} [unbind] Whether the event should be added or removed
141
+ * @param {boolean} [skipPool] Whether events pool should be skipped
142
+ */_toggleListener(t,e,s,n,o,a){if(!t)return;const r=o?"removeEventListener":"addEventListener";const h=e.split(" ");h.forEach((e=>{if(e){a||(o?this._pool=this._pool.filter((i=>i.type!==e||i.listener!==s||i.target!==t)):this._pool.push({target:t,type:e,listener:s,passive:n}));const h=!!i&&{passive:n||false};t[r](e,s,h)}}))}}
143
+ /** @typedef {import('../photoswipe.js').PhotoSwipeOptions} PhotoSwipeOptions */
144
+ /** @typedef {import('../core/base.js').default} PhotoSwipeBase */
145
+ /** @typedef {import('../photoswipe.js').Point} Point */
146
+ /** @typedef {import('../slide/slide.js').SlideData} SlideData */
147
+ /**
148
+ * @param {PhotoSwipeOptions} options
149
+ * @param {PhotoSwipeBase} pswp
150
+ * @returns {Point}
151
+ */function getViewportSize(t,e){if(t.getViewportSizeFn){const i=t.getViewportSizeFn(t,e);if(i)return i}return{x:document.documentElement.clientWidth,y:window.innerHeight}}
152
+ /**
153
+ * Parses padding option.
154
+ * Supported formats:
155
+ *
156
+ * // Object
157
+ * padding: {
158
+ * top: 0,
159
+ * bottom: 0,
160
+ * left: 0,
161
+ * right: 0
162
+ * }
163
+ *
164
+ * // A function that returns the object
165
+ * paddingFn: (viewportSize, itemData, index) => {
166
+ * return {
167
+ * top: 0,
168
+ * bottom: 0,
169
+ * left: 0,
170
+ * right: 0
171
+ * };
172
+ * }
173
+ *
174
+ * // Legacy variant
175
+ * paddingLeft: 0,
176
+ * paddingRight: 0,
177
+ * paddingTop: 0,
178
+ * paddingBottom: 0,
179
+ *
180
+ * @param {'left' | 'top' | 'bottom' | 'right'} prop
181
+ * @param {PhotoSwipeOptions} options PhotoSwipe options
182
+ * @param {Point} viewportSize PhotoSwipe viewport size, for example: { x:800, y:600 }
183
+ * @param {SlideData} itemData Data about the slide
184
+ * @param {number} index Slide index
185
+ * @returns {number}
186
+ */function parsePaddingOption(t,e,i,s,n){let o=0;if(e.paddingFn)o=e.paddingFn(i,s,n)[t];else if(e.padding)o=e.padding[t];else{const i="padding"+t[0].toUpperCase()+t.slice(1);e[i]&&(o=e[i])}return Number(o)||0}
187
+ /**
188
+ * @param {PhotoSwipeOptions} options
189
+ * @param {Point} viewportSize
190
+ * @param {SlideData} itemData
191
+ * @param {number} index
192
+ * @returns {Point}
193
+ */function getPanAreaSize(t,e,i,s){return{x:e.x-parsePaddingOption("left",t,e,i,s)-parsePaddingOption("right",t,e,i,s),y:e.y-parsePaddingOption("top",t,e,i,s)-parsePaddingOption("bottom",t,e,i,s)}}
194
+ /** @typedef {import('./slide.js').default} Slide */
195
+ /** @typedef {Record<Axis, number>} Point */
196
+ /** @typedef {'x' | 'y'} Axis */class PanBounds{
197
+ /**
198
+ * @param {Slide} slide
199
+ */
200
+ constructor(t){this.slide=t;this.currZoomLevel=1;this.center=
201
+ /** @type {Point} */
202
+ {x:0,y:0};this.max=
203
+ /** @type {Point} */
204
+ {x:0,y:0};this.min=
205
+ /** @type {Point} */
206
+ {x:0,y:0}}
207
+ /**
208
+ * _getItemBounds
209
+ *
210
+ * @param {number} currZoomLevel
211
+ */update(t){this.currZoomLevel=t;if(this.slide.width){this._updateAxis("x");this._updateAxis("y");this.slide.pswp.dispatch("calcBounds",{slide:this.slide})}else this.reset()}
212
+ /**
213
+ * _calculateItemBoundsForAxis
214
+ *
215
+ * @param {Axis} axis
216
+ */_updateAxis(t){const{pswp:e}=this.slide;const i=this.slide[t==="x"?"width":"height"]*this.currZoomLevel;const s=t==="x"?"left":"top";const n=parsePaddingOption(s,e.options,e.viewportSize,this.slide.data,this.slide.index);const o=this.slide.panAreaSize[t];this.center[t]=Math.round((o-i)/2)+n;this.max[t]=i>o?Math.round(o-i)+n:this.center[t];this.min[t]=i>o?n:this.center[t]}reset(){this.center.x=0;this.center.y=0;this.max.x=0;this.max.y=0;this.min.x=0;this.min.y=0}
217
+ /**
218
+ * Correct pan position if it's beyond the bounds
219
+ *
220
+ * @param {Axis} axis x or y
221
+ * @param {number} panOffset
222
+ * @returns {number}
223
+ */correctPan(t,e){return clamp(e,this.max[t],this.min[t])}}const s=4e3;
224
+ /** @typedef {import('../photoswipe.js').default} PhotoSwipe */
225
+ /** @typedef {import('../photoswipe.js').PhotoSwipeOptions} PhotoSwipeOptions */
226
+ /** @typedef {import('../photoswipe.js').Point} Point */
227
+ /** @typedef {import('../slide/slide.js').SlideData} SlideData */
228
+ /** @typedef {'fit' | 'fill' | number | ((zoomLevelObject: ZoomLevel) => number)} ZoomLevelOption */class ZoomLevel{
229
+ /**
230
+ * @param {PhotoSwipeOptions} options PhotoSwipe options
231
+ * @param {SlideData} itemData Slide data
232
+ * @param {number} index Slide index
233
+ * @param {PhotoSwipe} [pswp] PhotoSwipe instance, can be undefined if not initialized yet
234
+ */
235
+ constructor(t,e,i,s){this.pswp=s;this.options=t;this.itemData=e;this.index=i;
236
+ /** @type { Point | null } */this.panAreaSize=null;
237
+ /** @type { Point | null } */this.elementSize=null;this.fit=1;this.fill=1;this.vFill=1;this.initial=1;this.secondary=1;this.max=1;this.min=1}
238
+ /**
239
+ * Calculate initial, secondary and maximum zoom level for the specified slide.
240
+ *
241
+ * It should be called when either image or viewport size changes.
242
+ *
243
+ * @param {number} maxWidth
244
+ * @param {number} maxHeight
245
+ * @param {Point} panAreaSize
246
+ */update(t,e,i){
247
+ /** @type {Point} */
248
+ const s={x:t,y:e};this.elementSize=s;this.panAreaSize=i;const n=i.x/s.x;const o=i.y/s.y;this.fit=Math.min(1,n<o?n:o);this.fill=Math.min(1,n>o?n:o);this.vFill=Math.min(1,o);this.initial=this._getInitial();this.secondary=this._getSecondary();this.max=Math.max(this.initial,this.secondary,this._getMax());this.min=Math.min(this.fit,this.initial,this.secondary);this.pswp&&this.pswp.dispatch("zoomLevelsUpdate",{zoomLevels:this,slideData:this.itemData})}
249
+ /**
250
+ * Parses user-defined zoom option.
251
+ *
252
+ * @private
253
+ * @param {'initial' | 'secondary' | 'max'} optionPrefix Zoom level option prefix (initial, secondary, max)
254
+ * @returns { number | undefined }
255
+ */_parseZoomLevelOption(t){const e=
256
+ /** @type {'initialZoomLevel' | 'secondaryZoomLevel' | 'maxZoomLevel'} */
257
+ t+"ZoomLevel";const i=this.options[e];if(i)return typeof i==="function"?i(this):i==="fill"?this.fill:i==="fit"?this.fit:Number(i)}_getSecondary(){let t=this._parseZoomLevelOption("secondary");if(t)return t;t=Math.min(1,this.fit*3);this.elementSize&&t*this.elementSize.x>s&&(t=s/this.elementSize.x);return t}_getInitial(){return this._parseZoomLevelOption("initial")||this.fit}_getMax(){return this._parseZoomLevelOption("max")||Math.max(1,this.fit*4)}}
258
+ /** @typedef {import('../photoswipe.js').default} PhotoSwipe */class Slide{
259
+ /**
260
+ * @param {SlideData} data
261
+ * @param {number} index
262
+ * @param {PhotoSwipe} pswp
263
+ */
264
+ constructor(t,e,i){this.data=t;this.index=e;this.pswp=i;this.isActive=e===i.currIndex;this.currentResolution=0;
265
+ /** @type {Point} */this.panAreaSize={x:0,y:0};
266
+ /** @type {Point} */this.pan={x:0,y:0};this.isFirstSlide=this.isActive&&!i.opener.isOpen;this.zoomLevels=new ZoomLevel(i.options,t,e,i);this.pswp.dispatch("gettingData",{slide:this,data:this.data,index:e});this.content=this.pswp.contentLoader.getContentBySlide(this);this.container=createElement("pswp__zoom-wrap","div");
267
+ /** @type {HTMLElement | null} */this.holderElement=null;this.currZoomLevel=1;
268
+ /** @type {number} */this.width=this.content.width;
269
+ /** @type {number} */this.height=this.content.height;this.heavyAppended=false;this.bounds=new PanBounds(this);this.prevDisplayedWidth=-1;this.prevDisplayedHeight=-1;this.pswp.dispatch("slideInit",{slide:this})}
270
+ /**
271
+ * If this slide is active/current/visible
272
+ *
273
+ * @param {boolean} isActive
274
+ */setIsActive(t){t&&!this.isActive?this.activate():!t&&this.isActive&&this.deactivate()}
275
+ /**
276
+ * Appends slide content to DOM
277
+ *
278
+ * @param {HTMLElement} holderElement
279
+ */append(t){this.holderElement=t;this.container.style.transformOrigin="0 0";if(this.data){this.calculateSize();this.load();this.updateContentSize();this.appendHeavy();this.holderElement.appendChild(this.container);this.zoomAndPanToInitial();this.pswp.dispatch("firstZoomPan",{slide:this});this.applyCurrentZoomPan();this.pswp.dispatch("afterSetContent",{slide:this});this.isActive&&this.activate()}}load(){this.content.load(false);this.pswp.dispatch("slideLoad",{slide:this})}appendHeavy(){const{pswp:t}=this;const e=true;if(!this.heavyAppended&&t.opener.isOpen&&!t.mainScroll.isShifted()&&(this.isActive||e)&&!this.pswp.dispatch("appendHeavy",{slide:this}).defaultPrevented){this.heavyAppended=true;this.content.append();this.pswp.dispatch("appendHeavyContent",{slide:this})}}activate(){this.isActive=true;this.appendHeavy();this.content.activate();this.pswp.dispatch("slideActivate",{slide:this})}deactivate(){this.isActive=false;this.content.deactivate();this.currZoomLevel!==this.zoomLevels.initial&&this.calculateSize();this.currentResolution=0;this.zoomAndPanToInitial();this.applyCurrentZoomPan();this.updateContentSize();this.pswp.dispatch("slideDeactivate",{slide:this})}destroy(){this.content.hasSlide=false;this.content.remove();this.container.remove();this.pswp.dispatch("slideDestroy",{slide:this})}resize(){if(this.currZoomLevel!==this.zoomLevels.initial&&this.isActive){this.calculateSize();this.bounds.update(this.currZoomLevel);this.panTo(this.pan.x,this.pan.y)}else{this.calculateSize();this.currentResolution=0;this.zoomAndPanToInitial();this.applyCurrentZoomPan();this.updateContentSize()}}
280
+ /**
281
+ * Apply size to current slide content,
282
+ * based on the current resolution and scale.
283
+ *
284
+ * @param {boolean} [force] if size should be updated even if dimensions weren't changed
285
+ */updateContentSize(t){const e=this.currentResolution||this.zoomLevels.initial;if(!e)return;const i=Math.round(this.width*e)||this.pswp.viewportSize.x;const s=Math.round(this.height*e)||this.pswp.viewportSize.y;(this.sizeChanged(i,s)||t)&&this.content.setDisplayedSize(i,s)}
286
+ /**
287
+ * @param {number} width
288
+ * @param {number} height
289
+ */sizeChanged(t,e){if(t!==this.prevDisplayedWidth||e!==this.prevDisplayedHeight){this.prevDisplayedWidth=t;this.prevDisplayedHeight=e;return true}return false}
290
+ /** @returns {HTMLImageElement | HTMLDivElement | null | undefined} */getPlaceholderElement(){var t;return(t=this.content.placeholder)===null||t===void 0?void 0:t.element}
291
+ /**
292
+ * Zoom current slide image to...
293
+ *
294
+ * @param {number} destZoomLevel Destination zoom level.
295
+ * @param {Point} [centerPoint]
296
+ * Transform origin center point, or false if viewport center should be used.
297
+ * @param {number | false} [transitionDuration] Transition duration, may be set to 0.
298
+ * @param {boolean} [ignoreBounds] Minimum and maximum zoom levels will be ignored.
299
+ */zoomTo(t,e,i,s){const{pswp:n}=this;if(!this.isZoomable()||n.mainScroll.isShifted())return;n.dispatch("beforeZoomTo",{destZoomLevel:t,centerPoint:e,transitionDuration:i});n.animations.stopAllPan();const o=this.currZoomLevel;s||(t=clamp(t,this.zoomLevels.min,this.zoomLevels.max));this.setZoomLevel(t);this.pan.x=this.calculateZoomToPanOffset("x",e,o);this.pan.y=this.calculateZoomToPanOffset("y",e,o);roundPoint(this.pan);const finishTransition=()=>{this._setResolution(t);this.applyCurrentZoomPan()};i?n.animations.startTransition({isPan:true,name:"zoomTo",target:this.container,transform:this.getCurrentTransform(),onComplete:finishTransition,duration:i,easing:n.options.easing}):finishTransition()}
300
+ /**
301
+ * @param {Point} [centerPoint]
302
+ */toggleZoom(t){this.zoomTo(this.currZoomLevel===this.zoomLevels.initial?this.zoomLevels.secondary:this.zoomLevels.initial,t,this.pswp.options.zoomAnimationDuration)}
303
+ /**
304
+ * Updates zoom level property and recalculates new pan bounds,
305
+ * unlike zoomTo it does not apply transform (use applyCurrentZoomPan)
306
+ *
307
+ * @param {number} currZoomLevel
308
+ */setZoomLevel(t){this.currZoomLevel=t;this.bounds.update(this.currZoomLevel)}
309
+ /**
310
+ * Get pan position after zoom at a given `point`.
311
+ *
312
+ * Always call setZoomLevel(newZoomLevel) beforehand to recalculate
313
+ * pan bounds according to the new zoom level.
314
+ *
315
+ * @param {'x' | 'y'} axis
316
+ * @param {Point} [point]
317
+ * point based on which zoom is performed, usually refers to the current mouse position,
318
+ * if false - viewport center will be used.
319
+ * @param {number} [prevZoomLevel] Zoom level before new zoom was applied.
320
+ * @returns {number}
321
+ */calculateZoomToPanOffset(t,e,i){const s=this.bounds.max[t]-this.bounds.min[t];if(s===0)return this.bounds.center[t];e||(e=this.pswp.getViewportCenterPoint());i||(i=this.zoomLevels.initial);const n=this.currZoomLevel/i;return this.bounds.correctPan(t,(this.pan[t]-e[t])*n+e[t])}
322
+ /**
323
+ * Apply pan and keep it within bounds.
324
+ *
325
+ * @param {number} panX
326
+ * @param {number} panY
327
+ */panTo(t,e){this.pan.x=this.bounds.correctPan("x",t);this.pan.y=this.bounds.correctPan("y",e);this.applyCurrentZoomPan()}
328
+ /**
329
+ * If the slide in the current state can be panned by the user
330
+ * @returns {boolean}
331
+ */isPannable(){return Boolean(this.width)&&this.currZoomLevel>this.zoomLevels.fit}
332
+ /**
333
+ * If the slide can be zoomed
334
+ * @returns {boolean}
335
+ */isZoomable(){return Boolean(this.width)&&this.content.isZoomable()}applyCurrentZoomPan(){this._applyZoomTransform(this.pan.x,this.pan.y,this.currZoomLevel);this===this.pswp.currSlide&&this.pswp.dispatch("zoomPanUpdate",{slide:this})}zoomAndPanToInitial(){this.currZoomLevel=this.zoomLevels.initial;this.bounds.update(this.currZoomLevel);equalizePoints(this.pan,this.bounds.center);this.pswp.dispatch("initialZoomPan",{slide:this})}
336
+ /**
337
+ * Set translate and scale based on current resolution
338
+ *
339
+ * @param {number} x
340
+ * @param {number} y
341
+ * @param {number} zoom
342
+ * @private
343
+ */_applyZoomTransform(t,e,i){i/=this.currentResolution||this.zoomLevels.initial;setTransform(this.container,t,e,i)}calculateSize(){const{pswp:t}=this;equalizePoints(this.panAreaSize,getPanAreaSize(t.options,t.viewportSize,this.data,this.index));this.zoomLevels.update(this.width,this.height,this.panAreaSize);t.dispatch("calcSlideSize",{slide:this})}
344
+ /** @returns {string} */getCurrentTransform(){const t=this.currZoomLevel/(this.currentResolution||this.zoomLevels.initial);return toTransformString(this.pan.x,this.pan.y,t)}
345
+ /**
346
+ * Set resolution and re-render the image.
347
+ *
348
+ * For example, if the real image size is 2000x1500,
349
+ * and resolution is 0.5 - it will be rendered as 1000x750.
350
+ *
351
+ * Image with zoom level 2 and resolution 0.5 is
352
+ * the same as image with zoom level 1 and resolution 1.
353
+ *
354
+ * Used to optimize animations and make
355
+ * sure that browser renders image in the highest quality.
356
+ * Also used by responsive images to load the correct one.
357
+ *
358
+ * @param {number} newResolution
359
+ */_setResolution(t){if(t!==this.currentResolution){this.currentResolution=t;this.updateContentSize();this.pswp.dispatch("resolutionChanged")}}}
360
+ /** @typedef {import('../photoswipe.js').Point} Point */
361
+ /** @typedef {import('./gestures.js').default} Gestures */const n=.35;const o=.6;const a=.4;const r=.5;
362
+ /**
363
+ * @param {number} initialVelocity
364
+ * @param {number} decelerationRate
365
+ * @returns {number}
366
+ */function project(t,e){return t*e/(1-e)}class DragHandler{
367
+ /**
368
+ * @param {Gestures} gestures
369
+ */
370
+ constructor(t){this.gestures=t;this.pswp=t.pswp;
371
+ /** @type {Point} */this.startPan={x:0,y:0}}start(){this.pswp.currSlide&&equalizePoints(this.startPan,this.pswp.currSlide.pan);this.pswp.animations.stopAll()}change(){const{p1:t,prevP1:e,dragAxis:i}=this.gestures;const{currSlide:s}=this.pswp;if(i==="y"&&this.pswp.options.closeOnVerticalDrag&&s&&s.currZoomLevel<=s.zoomLevels.fit&&!this.gestures.isMultitouch){const i=s.pan.y+(t.y-e.y);if(!this.pswp.dispatch("verticalDrag",{panY:i}).defaultPrevented){this._setPanWithFriction("y",i,o);const t=1-Math.abs(this._getVerticalDragRatio(s.pan.y));this.pswp.applyBgOpacity(t);s.applyCurrentZoomPan()}}else{const t=this._panOrMoveMainScroll("x");if(!t){this._panOrMoveMainScroll("y");if(s){roundPoint(s.pan);s.applyCurrentZoomPan()}}}}end(){const{velocity:t}=this.gestures;const{mainScroll:e,currSlide:i}=this.pswp;let s=0;this.pswp.animations.stopAll();if(e.isShifted()){const i=e.x-e.getCurrSlideX();const n=i/this.pswp.viewportSize.x;if(t.x<-r&&n<0||t.x<.1&&n<-.5){s=1;t.x=Math.min(t.x,0)}else if(t.x>r&&n>0||t.x>-.1&&n>.5){s=-1;t.x=Math.max(t.x,0)}e.moveIndexBy(s,true,t.x)}if(i&&i.currZoomLevel>i.zoomLevels.max||this.gestures.isMultitouch)this.gestures.zoomLevels.correctZoomPan(true);else{this._finishPanGestureForAxis("x");this._finishPanGestureForAxis("y")}}
372
+ /**
373
+ * @private
374
+ * @param {'x' | 'y'} axis
375
+ */_finishPanGestureForAxis(t){const{velocity:e}=this.gestures;const{currSlide:i}=this.pswp;if(!i)return;const{pan:s,bounds:n}=i;const o=s[t];const r=this.pswp.bgOpacity<1&&t==="y";const h=.995;const l=o+project(e[t],h);if(r){const t=this._getVerticalDragRatio(o);const e=this._getVerticalDragRatio(l);if(t<0&&e<-a||t>0&&e>a){this.pswp.close();return}}const p=n.correctPan(t,l);if(o===p)return;const d=p===l?1:.82;const c=this.pswp.bgOpacity;const u=p-o;this.pswp.animations.startSpring({name:"panGesture"+t,isPan:true,start:o,end:p,velocity:e[t],dampingRatio:d,onUpdate:e=>{if(r&&this.pswp.bgOpacity<1){const t=1-(p-e)/u;this.pswp.applyBgOpacity(clamp(c+(1-c)*t,0,1))}s[t]=Math.floor(e);i.applyCurrentZoomPan()}})}
376
+ /**
377
+ * Update position of the main scroll,
378
+ * or/and update pan position of the current slide.
379
+ *
380
+ * Should return true if it changes (or can change) main scroll.
381
+ *
382
+ * @private
383
+ * @param {'x' | 'y'} axis
384
+ * @returns {boolean}
385
+ */_panOrMoveMainScroll(t){const{p1:e,dragAxis:i,prevP1:s,isMultitouch:n}=this.gestures;const{currSlide:o,mainScroll:a}=this.pswp;const r=e[t]-s[t];const h=a.x+r;if(!r||!o)return false;if(t==="x"&&!o.isPannable()&&!n){a.moveTo(h,true);return true}const{bounds:l}=o;const p=o.pan[t]+r;if(this.pswp.options.allowPanToNext&&i==="x"&&t==="x"&&!n){const e=a.getCurrSlideX();const i=a.x-e;const s=r>0;const n=!s;if(p>l.min[t]&&s){const e=l.min[t]<=this.startPan[t];if(e){a.moveTo(h,true);return true}this._setPanWithFriction(t,p)}else if(p<l.max[t]&&n){const e=this.startPan[t]<=l.max[t];if(e){a.moveTo(h,true);return true}this._setPanWithFriction(t,p)}else if(i!==0){if(i>0){a.moveTo(Math.max(h,e),true);return true}if(i<0){a.moveTo(Math.min(h,e),true);return true}}else this._setPanWithFriction(t,p)}else t==="y"&&(a.isShifted()||l.min.y===l.max.y)||this._setPanWithFriction(t,p);return false}
386
+ /**
387
+ * Relation between pan Y position and third of viewport height.
388
+ *
389
+ * When we are at initial position (center bounds) - the ratio is 0,
390
+ * if position is shifted upwards - the ratio is negative,
391
+ * if position is shifted downwards - the ratio is positive.
392
+ *
393
+ * @private
394
+ * @param {number} panY The current pan Y position.
395
+ * @returns {number}
396
+ */
397
+ _getVerticalDragRatio(t){var e,i;return(t-((e=(i=this.pswp.currSlide)===null||i===void 0?void 0:i.bounds.center.y)!==null&&e!==void 0?e:0))/(this.pswp.viewportSize.y/3)}
398
+ /**
399
+ * Set pan position of the current slide.
400
+ * Apply friction if the position is beyond the pan bounds,
401
+ * or if custom friction is defined.
402
+ *
403
+ * @private
404
+ * @param {'x' | 'y'} axis
405
+ * @param {number} potentialPan
406
+ * @param {number} [customFriction] (0.1 - 1)
407
+ */_setPanWithFriction(t,e,i){const{currSlide:s}=this.pswp;if(!s)return;const{pan:o,bounds:a}=s;const r=a.correctPan(t,e);if(r!==e||i){const s=Math.round(e-o[t]);o[t]+=s*(i||n)}else o[t]=e}}
408
+ /** @typedef {import('../photoswipe.js').Point} Point */
409
+ /** @typedef {import('./gestures.js').default} Gestures */const h=.05;const l=.15;
410
+ /**
411
+ * Get center point between two points
412
+ *
413
+ * @param {Point} p
414
+ * @param {Point} p1
415
+ * @param {Point} p2
416
+ * @returns {Point}
417
+ */function getZoomPointsCenter(t,e,i){t.x=(e.x+i.x)/2;t.y=(e.y+i.y)/2;return t}class ZoomHandler{
418
+ /**
419
+ * @param {Gestures} gestures
420
+ */
421
+ constructor(t){this.gestures=t;
422
+ /**
423
+ * @private
424
+ * @type {Point}
425
+ */this._startPan={x:0,y:0};
426
+ /**
427
+ * @private
428
+ * @type {Point}
429
+ */this._startZoomPoint={x:0,y:0};
430
+ /**
431
+ * @private
432
+ * @type {Point}
433
+ */this._zoomPoint={x:0,y:0};this._wasOverFitZoomLevel=false;this._startZoomLevel=1}start(){const{currSlide:t}=this.gestures.pswp;if(t){this._startZoomLevel=t.currZoomLevel;equalizePoints(this._startPan,t.pan)}this.gestures.pswp.animations.stopAllPan();this._wasOverFitZoomLevel=false}change(){const{p1:t,startP1:e,p2:i,startP2:s,pswp:n}=this.gestures;const{currSlide:o}=n;if(!o)return;const a=o.zoomLevels.min;const r=o.zoomLevels.max;if(!o.isZoomable()||n.mainScroll.isShifted())return;getZoomPointsCenter(this._startZoomPoint,e,s);getZoomPointsCenter(this._zoomPoint,t,i);let p=1/getDistanceBetween(e,s)*getDistanceBetween(t,i)*this._startZoomLevel;p>o.zoomLevels.initial+o.zoomLevels.initial/15&&(this._wasOverFitZoomLevel=true);if(p<a)if(n.options.pinchToClose&&!this._wasOverFitZoomLevel&&this._startZoomLevel<=o.zoomLevels.initial){const t=1-(a-p)/(a/1.2);n.dispatch("pinchClose",{bgOpacity:t}).defaultPrevented||n.applyBgOpacity(t)}else p=a-(a-p)*l;else p>r&&(p=r+(p-r)*h);o.pan.x=this._calculatePanForZoomLevel("x",p);o.pan.y=this._calculatePanForZoomLevel("y",p);o.setZoomLevel(p);o.applyCurrentZoomPan()}end(){const{pswp:t}=this.gestures;const{currSlide:e}=t;(!e||e.currZoomLevel<e.zoomLevels.initial)&&!this._wasOverFitZoomLevel&&t.options.pinchToClose?t.close():this.correctZoomPan()}
434
+ /**
435
+ * @private
436
+ * @param {'x' | 'y'} axis
437
+ * @param {number} currZoomLevel
438
+ * @returns {number}
439
+ */_calculatePanForZoomLevel(t,e){const i=e/this._startZoomLevel;return this._zoomPoint[t]-(this._startZoomPoint[t]-this._startPan[t])*i}
440
+ /**
441
+ * Correct currZoomLevel and pan if they are
442
+ * beyond minimum or maximum values.
443
+ * With animation.
444
+ *
445
+ * @param {boolean} [ignoreGesture]
446
+ * Wether gesture coordinates should be ignored when calculating destination pan position.
447
+ */correctZoomPan(t){const{pswp:e}=this.gestures;const{currSlide:i}=e;if(!(i!==null&&i!==void 0&&i.isZoomable()))return;this._zoomPoint.x===0&&(t=true);const s=i.currZoomLevel;
448
+ /** @type {number} */let n;let o=true;if(s<i.zoomLevels.initial)n=i.zoomLevels.initial;else if(s>i.zoomLevels.max)n=i.zoomLevels.max;else{o=false;n=s}const a=e.bgOpacity;const r=e.bgOpacity<1;const h=equalizePoints({x:0,y:0},i.pan);let l=equalizePoints({x:0,y:0},h);if(t){this._zoomPoint.x=0;this._zoomPoint.y=0;this._startZoomPoint.x=0;this._startZoomPoint.y=0;this._startZoomLevel=s;equalizePoints(this._startPan,h)}o&&(l={x:this._calculatePanForZoomLevel("x",n),y:this._calculatePanForZoomLevel("y",n)});i.setZoomLevel(n);l={x:i.bounds.correctPan("x",l.x),y:i.bounds.correctPan("y",l.y)};i.setZoomLevel(s);const p=!pointsEqual(l,h);if(p||o||r){e.animations.stopAllPan();e.animations.startSpring({isPan:true,start:0,end:1e3,velocity:0,dampingRatio:1,naturalFrequency:40,onUpdate:t=>{t/=1e3;if(p||o){if(p){i.pan.x=h.x+(l.x-h.x)*t;i.pan.y=h.y+(l.y-h.y)*t}if(o){const e=s+(n-s)*t;i.setZoomLevel(e)}i.applyCurrentZoomPan()}r&&e.bgOpacity<1&&e.applyBgOpacity(clamp(a+(1-a)*t,0,1))},onComplete:()=>{i._setResolution(n);i.applyCurrentZoomPan()}})}else{i._setResolution(n);i.applyCurrentZoomPan()}}}
449
+ /**
450
+ * @template {string} T
451
+ * @template {string} P
452
+ * @typedef {import('../types.js').AddPostfix<T, P>} AddPostfix<T, P>
453
+ */
454
+ /** @typedef {import('./gestures.js').default} Gestures */
455
+ /** @typedef {import('../photoswipe.js').Point} Point */
456
+ /** @typedef {'imageClick' | 'bgClick' | 'tap' | 'doubleTap'} Actions */
457
+ /**
458
+ * Whether the tap was performed on the main slide
459
+ * (rather than controls or caption).
460
+ *
461
+ * @param {PointerEvent} event
462
+ * @returns {boolean}
463
+ */function didTapOnMainContent(t){return!!
464
+ /** @type {HTMLElement} */
465
+ t.target.closest(".pswp__container")}class TapHandler{
466
+ /**
467
+ * @param {Gestures} gestures
468
+ */
469
+ constructor(t){this.gestures=t}
470
+ /**
471
+ * @param {Point} point
472
+ * @param {PointerEvent} originalEvent
473
+ */click(t,e){const i=
474
+ /** @type {HTMLElement} */
475
+ e.target.classList;const s=i.contains("pswp__img");const n=i.contains("pswp__item")||i.contains("pswp__zoom-wrap");s?this._doClickOrTapAction("imageClick",t,e):n&&this._doClickOrTapAction("bgClick",t,e)}
476
+ /**
477
+ * @param {Point} point
478
+ * @param {PointerEvent} originalEvent
479
+ */tap(t,e){didTapOnMainContent(e)&&this._doClickOrTapAction("tap",t,e)}
480
+ /**
481
+ * @param {Point} point
482
+ * @param {PointerEvent} originalEvent
483
+ */doubleTap(t,e){didTapOnMainContent(e)&&this._doClickOrTapAction("doubleTap",t,e)}
484
+ /**
485
+ * @private
486
+ * @param {Actions} actionName
487
+ * @param {Point} point
488
+ * @param {PointerEvent} originalEvent
489
+ */_doClickOrTapAction(t,e,i){var s;const{pswp:n}=this.gestures;const{currSlide:o}=n;const a=
490
+ /** @type {AddPostfix<Actions, 'Action'>} */
491
+ t+"Action";const r=n.options[a];if(!n.dispatch(a,{point:e,originalEvent:i}).defaultPrevented)if(typeof r!=="function")switch(r){case"close":case"next":n[r]();break;case"zoom":o===null||o===void 0||o.toggleZoom(e);break;case"zoom-or-close":o!==null&&o!==void 0&&o.isZoomable()&&o.zoomLevels.secondary!==o.zoomLevels.initial?o.toggleZoom(e):n.options.clickToCloseNonZoomable&&n.close();break;case"toggle-controls":(s=this.gestures.pswp.element)===null||s===void 0||s.classList.toggle("pswp--ui-visible");break}else r.call(n,e,i)}}
492
+ /** @typedef {import('../photoswipe.js').default} PhotoSwipe */
493
+ /** @typedef {import('../photoswipe.js').Point} Point */const p=10;const d=300;const c=25;class Gestures{
494
+ /**
495
+ * @param {PhotoSwipe} pswp
496
+ */
497
+ constructor(t){this.pswp=t;
498
+ /** @type {'x' | 'y' | null} */this.dragAxis=null;
499
+ /** @type {Point} */this.p1={x:0,y:0};
500
+ /** @type {Point} */this.p2={x:0,y:0};
501
+ /** @type {Point} */this.prevP1={x:0,y:0};
502
+ /** @type {Point} */this.prevP2={x:0,y:0};
503
+ /** @type {Point} */this.startP1={x:0,y:0};
504
+ /** @type {Point} */this.startP2={x:0,y:0};
505
+ /** @type {Point} */this.velocity={x:0,y:0};
506
+ /** @type {Point}
507
+ * @private
508
+ */this._lastStartP1={x:0,y:0};
509
+ /** @type {Point}
510
+ * @private
511
+ */this._intervalP1={x:0,y:0};this._numActivePoints=0;
512
+ /** @type {Point[]}
513
+ * @private
514
+ */this._ongoingPointers=[];this._touchEventEnabled="ontouchstart"in window;this._pointerEventEnabled=!!window.PointerEvent;this.supportsTouch=this._touchEventEnabled||this._pointerEventEnabled&&navigator.maxTouchPoints>1;this._numActivePoints=0;this._intervalTime=0;this._velocityCalculated=false;this.isMultitouch=false;this.isDragging=false;this.isZooming=false;
515
+ /** @type {number | null} */this.raf=null;
516
+ /** @type {NodeJS.Timeout | null}
517
+ * @private
518
+ */this._tapTimer=null;this.supportsTouch||(t.options.allowPanToNext=false);this.drag=new DragHandler(this);this.zoomLevels=new ZoomHandler(this);this.tapHandler=new TapHandler(this);t.on("bindEvents",(()=>{t.events.add(t.scrollWrap,"click",
519
+ /** @type EventListener */
520
+ this._onClick.bind(this));if(this._pointerEventEnabled)this._bindEvents("pointer","down","up","cancel");else if(this._touchEventEnabled){this._bindEvents("touch","start","end","cancel");if(t.scrollWrap){t.scrollWrap.ontouchmove=()=>{};t.scrollWrap.ontouchend=()=>{}}}else this._bindEvents("mouse","down","up")}))}
521
+ /**
522
+ * @private
523
+ * @param {'mouse' | 'touch' | 'pointer'} pref
524
+ * @param {'down' | 'start'} down
525
+ * @param {'up' | 'end'} up
526
+ * @param {'cancel'} [cancel]
527
+ */_bindEvents(t,e,i,s){const{pswp:n}=this;const{events:o}=n;const a=s?t+s:"";o.add(n.scrollWrap,t+e,
528
+ /** @type EventListener */
529
+ this.onPointerDown.bind(this));o.add(window,t+"move",
530
+ /** @type EventListener */
531
+ this.onPointerMove.bind(this));o.add(window,t+i,
532
+ /** @type EventListener */
533
+ this.onPointerUp.bind(this));a&&o.add(n.scrollWrap,a,
534
+ /** @type EventListener */
535
+ this.onPointerUp.bind(this))}
536
+ /**
537
+ * @param {PointerEvent} e
538
+ */onPointerDown(t){const e=t.type==="mousedown"||t.pointerType==="mouse";if(e&&t.button>0)return;const{pswp:i}=this;if(i.opener.isOpen){if(!i.dispatch("pointerDown",{originalEvent:t}).defaultPrevented){if(e){i.mouseDetected();this._preventPointerEventBehaviour(t,"down")}i.animations.stopAll();this._updatePoints(t,"down");if(this._numActivePoints===1){this.dragAxis=null;equalizePoints(this.startP1,this.p1)}if(this._numActivePoints>1){this._clearTapTimer();this.isMultitouch=true}else this.isMultitouch=false}}else t.preventDefault()}
539
+ /**
540
+ * @param {PointerEvent} e
541
+ */onPointerMove(t){this._preventPointerEventBehaviour(t,"move");if(this._numActivePoints){this._updatePoints(t,"move");if(!this.pswp.dispatch("pointerMove",{originalEvent:t}).defaultPrevented)if(this._numActivePoints!==1||this.isDragging){if(this._numActivePoints>1&&!this.isZooming){this._finishDrag();this.isZooming=true;this._updateStartPoints();this.zoomLevels.start();this._rafStopLoop();this._rafRenderLoop()}}else{this.dragAxis||this._calculateDragDirection();if(this.dragAxis&&!this.isDragging){if(this.isZooming){this.isZooming=false;this.zoomLevels.end()}this.isDragging=true;this._clearTapTimer();this._updateStartPoints();this._intervalTime=Date.now();this._velocityCalculated=false;equalizePoints(this._intervalP1,this.p1);this.velocity.x=0;this.velocity.y=0;this.drag.start();this._rafStopLoop();this._rafRenderLoop()}}}}_finishDrag(){if(this.isDragging){this.isDragging=false;this._velocityCalculated||this._updateVelocity(true);this.drag.end();this.dragAxis=null}}
542
+ /**
543
+ * @param {PointerEvent} e
544
+ */onPointerUp(t){if(this._numActivePoints){this._updatePoints(t,"up");if(!this.pswp.dispatch("pointerUp",{originalEvent:t}).defaultPrevented){if(this._numActivePoints===0){this._rafStopLoop();this.isDragging?this._finishDrag():this.isZooming||this.isMultitouch||this._finishTap(t)}if(this._numActivePoints<2&&this.isZooming){this.isZooming=false;this.zoomLevels.end();if(this._numActivePoints===1){this.dragAxis=null;this._updateStartPoints()}}}}}_rafRenderLoop(){if(this.isDragging||this.isZooming){this._updateVelocity();this.isDragging?pointsEqual(this.p1,this.prevP1)||this.drag.change():pointsEqual(this.p1,this.prevP1)&&pointsEqual(this.p2,this.prevP2)||this.zoomLevels.change();this._updatePrevPoints();this.raf=requestAnimationFrame(this._rafRenderLoop.bind(this))}}
545
+ /**
546
+ * Update velocity at 50ms interval
547
+ *
548
+ * @private
549
+ * @param {boolean} [force]
550
+ */_updateVelocity(t){const e=Date.now();const i=e-this._intervalTime;if(!(i<50)||t){this.velocity.x=this._getVelocity("x",i);this.velocity.y=this._getVelocity("y",i);this._intervalTime=e;equalizePoints(this._intervalP1,this.p1);this._velocityCalculated=true}}
551
+ /**
552
+ * @private
553
+ * @param {PointerEvent} e
554
+ */_finishTap(t){const{mainScroll:e}=this.pswp;if(e.isShifted()){e.moveIndexBy(0,true);return}if(t.type.indexOf("cancel")>0)return;if(t.type==="mouseup"||t.pointerType==="mouse"){this.tapHandler.click(this.startP1,t);return}const i=this.pswp.options.doubleTapAction?d:0;if(this._tapTimer){this._clearTapTimer();getDistanceBetween(this._lastStartP1,this.startP1)<c&&this.tapHandler.doubleTap(this.startP1,t)}else{equalizePoints(this._lastStartP1,this.startP1);this._tapTimer=setTimeout((()=>{this.tapHandler.tap(this.startP1,t);this._clearTapTimer()}),i)}}_clearTapTimer(){if(this._tapTimer){clearTimeout(this._tapTimer);this._tapTimer=null}}
555
+ /**
556
+ * Get velocity for axis
557
+ *
558
+ * @private
559
+ * @param {'x' | 'y'} axis
560
+ * @param {number} duration
561
+ * @returns {number}
562
+ */_getVelocity(t,e){const i=this.p1[t]-this._intervalP1[t];return Math.abs(i)>1&&e>5?i/e:0}_rafStopLoop(){if(this.raf){cancelAnimationFrame(this.raf);this.raf=null}}
563
+ /**
564
+ * @private
565
+ * @param {PointerEvent} e
566
+ * @param {'up' | 'down' | 'move'} pointerType Normalized pointer type
567
+ */_preventPointerEventBehaviour(t,e){const i=this.pswp.applyFilters("preventPointerEvent",true,t,e);i&&t.preventDefault()}
568
+ /**
569
+ * Parses and normalizes points from the touch, mouse or pointer event.
570
+ * Updates p1 and p2.
571
+ *
572
+ * @private
573
+ * @param {PointerEvent | TouchEvent} e
574
+ * @param {'up' | 'down' | 'move'} pointerType Normalized pointer type
575
+ */_updatePoints(t,e){if(this._pointerEventEnabled){const i=
576
+ /** @type {PointerEvent} */
577
+ t;const s=this._ongoingPointers.findIndex((t=>t.id===i.pointerId));e==="up"&&s>-1?this._ongoingPointers.splice(s,1):e==="down"&&s===-1?this._ongoingPointers.push(this._convertEventPosToPoint(i,{x:0,y:0})):s>-1&&this._convertEventPosToPoint(i,this._ongoingPointers[s]);this._numActivePoints=this._ongoingPointers.length;this._numActivePoints>0&&equalizePoints(this.p1,this._ongoingPointers[0]);this._numActivePoints>1&&equalizePoints(this.p2,this._ongoingPointers[1])}else{const i=
578
+ /** @type {TouchEvent} */
579
+ t;this._numActivePoints=0;if(i.type.indexOf("touch")>-1){if(i.touches&&i.touches.length>0){this._convertEventPosToPoint(i.touches[0],this.p1);this._numActivePoints++;if(i.touches.length>1){this._convertEventPosToPoint(i.touches[1],this.p2);this._numActivePoints++}}}else{this._convertEventPosToPoint(
580
+ /** @type {PointerEvent} */
581
+ t,this.p1);e==="up"?this._numActivePoints=0:this._numActivePoints++}}}_updatePrevPoints(){equalizePoints(this.prevP1,this.p1);equalizePoints(this.prevP2,this.p2)}_updateStartPoints(){equalizePoints(this.startP1,this.p1);equalizePoints(this.startP2,this.p2);this._updatePrevPoints()}_calculateDragDirection(){if(this.pswp.mainScroll.isShifted())this.dragAxis="x";else{const t=Math.abs(this.p1.x-this.startP1.x)-Math.abs(this.p1.y-this.startP1.y);if(t!==0){const e=t>0?"x":"y";Math.abs(this.p1[e]-this.startP1[e])>=p&&(this.dragAxis=e)}}}
582
+ /**
583
+ * Converts touch, pointer or mouse event
584
+ * to PhotoSwipe point.
585
+ *
586
+ * @private
587
+ * @param {Touch | PointerEvent} e
588
+ * @param {Point} p
589
+ * @returns {Point}
590
+ */_convertEventPosToPoint(t,e){e.x=t.pageX-this.pswp.offset.x;e.y=t.pageY-this.pswp.offset.y;"pointerId"in t?e.id=t.pointerId:t.identifier!==void 0&&(e.id=t.identifier);return e}
591
+ /**
592
+ * @private
593
+ * @param {PointerEvent} e
594
+ */_onClick(t){if(this.pswp.mainScroll.isShifted()){t.preventDefault();t.stopPropagation()}}}
595
+ /** @typedef {import('./photoswipe.js').default} PhotoSwipe */
596
+ /** @typedef {import('./slide/slide.js').default} Slide */
597
+ /** @typedef {{ el: HTMLDivElement; slide?: Slide }} ItemHolder */const u=.35;class MainScroll{
598
+ /**
599
+ * @param {PhotoSwipe} pswp
600
+ */
601
+ constructor(t){this.pswp=t;this.x=0;this.slideWidth=0;this._currPositionIndex=0;this._prevPositionIndex=0;this._containerShiftIndex=-1;
602
+ /** @type {ItemHolder[]} */this.itemHolders=[]}
603
+ /**
604
+ * Position the scroller and slide containers
605
+ * according to viewport size.
606
+ *
607
+ * @param {boolean} [resizeSlides] Whether slides content should resized
608
+ */resize(t){const{pswp:e}=this;const i=Math.round(e.viewportSize.x+e.viewportSize.x*e.options.spacing);const s=i!==this.slideWidth;if(s){this.slideWidth=i;this.moveTo(this.getCurrSlideX())}this.itemHolders.forEach(((e,i)=>{s&&setTransform(e.el,(i+this._containerShiftIndex)*this.slideWidth);t&&e.slide&&e.slide.resize()}))}resetPosition(){this._currPositionIndex=0;this._prevPositionIndex=0;this.slideWidth=0;this._containerShiftIndex=-1}appendHolders(){this.itemHolders=[];for(let t=0;t<3;t++){const e=createElement("pswp__item","div",this.pswp.container);e.setAttribute("role","group");e.setAttribute("aria-roledescription","slide");e.setAttribute("aria-hidden","true");e.style.display=t===1?"block":"none";this.itemHolders.push({el:e})}}
609
+ /**
610
+ * Whether the main scroll can be horizontally swiped to the next or previous slide.
611
+ * @returns {boolean}
612
+ */canBeSwiped(){return this.pswp.getNumItems()>1}
613
+ /**
614
+ * Move main scroll by X amount of slides.
615
+ * For example:
616
+ * `-1` will move to the previous slide,
617
+ * `0` will reset the scroll position of the current slide,
618
+ * `3` will move three slides forward
619
+ *
620
+ * If loop option is enabled - index will be automatically looped too,
621
+ * (for example `-1` will move to the last slide of the gallery).
622
+ *
623
+ * @param {number} diff
624
+ * @param {boolean} [animate]
625
+ * @param {number} [velocityX]
626
+ * @returns {boolean} whether index was changed or not
627
+ */moveIndexBy(t,e,i){const{pswp:s}=this;let n=s.potentialIndex+t;const o=s.getNumItems();if(s.canLoop()){n=s.getLoopedIndex(n);const e=(t+o)%o;t=e<=o/2?e:e-o}else{n<0?n=0:n>=o&&(n=o-1);t=n-s.potentialIndex}s.potentialIndex=n;this._currPositionIndex-=t;s.animations.stopMainScroll();const a=this.getCurrSlideX();if(e){s.animations.startSpring({isMainScroll:true,start:this.x,end:a,velocity:i||0,naturalFrequency:30,dampingRatio:1,onUpdate:t=>{this.moveTo(t)},onComplete:()=>{this.updateCurrItem();s.appendHeavy()}});let t=s.potentialIndex-s.currIndex;if(s.canLoop()){const e=(t+o)%o;t=e<=o/2?e:e-o}Math.abs(t)>1&&this.updateCurrItem()}else{this.moveTo(a);this.updateCurrItem()}return Boolean(t)}
628
+ /**
629
+ * X position of the main scroll for the current slide
630
+ * (ignores position during dragging)
631
+ * @returns {number}
632
+ */getCurrSlideX(){return this.slideWidth*this._currPositionIndex}
633
+ /**
634
+ * Whether scroll position is shifted.
635
+ * For example, it will return true if the scroll is being dragged or animated.
636
+ * @returns {boolean}
637
+ */isShifted(){return this.x!==this.getCurrSlideX()}updateCurrItem(){var t;const{pswp:e}=this;const i=this._prevPositionIndex-this._currPositionIndex;if(!i)return;this._prevPositionIndex=this._currPositionIndex;e.currIndex=e.potentialIndex;let s=Math.abs(i);
638
+ /** @type {ItemHolder | undefined} */let n;if(s>=3){this._containerShiftIndex+=i+(i>0?-3:3);s=3;this.itemHolders.forEach((t=>{var e;(e=t.slide)===null||e===void 0||e.destroy();t.slide=void 0}))}for(let t=0;t<s;t++)if(i>0){n=this.itemHolders.shift();if(n){this.itemHolders[2]=n;this._containerShiftIndex++;setTransform(n.el,(this._containerShiftIndex+2)*this.slideWidth);e.setContent(n,e.currIndex-s+t+2)}}else{n=this.itemHolders.pop();if(n){this.itemHolders.unshift(n);this._containerShiftIndex--;setTransform(n.el,this._containerShiftIndex*this.slideWidth);e.setContent(n,e.currIndex+s-t-2)}}if(Math.abs(this._containerShiftIndex)>50&&!this.isShifted()){this.resetPosition();this.resize()}e.animations.stopAllPan();this.itemHolders.forEach(((t,e)=>{t.slide&&t.slide.setIsActive(e===1)}));e.currSlide=(t=this.itemHolders[1])===null||t===void 0?void 0:t.slide;e.contentLoader.updateLazy(i);e.currSlide&&e.currSlide.applyCurrentZoomPan();e.dispatch("change")}
639
+ /**
640
+ * Move the X position of the main scroll container
641
+ *
642
+ * @param {number} x
643
+ * @param {boolean} [dragging]
644
+ */moveTo(t,e){if(!this.pswp.canLoop()&&e){let e=(this.slideWidth*this._currPositionIndex-t)/this.slideWidth;e+=this.pswp.currIndex;const i=Math.round(t-this.x);(e<0&&i>0||e>=this.pswp.getNumItems()-1&&i<0)&&(t=this.x+i*u)}this.x=t;this.pswp.container&&setTransform(this.pswp.container,t);this.pswp.dispatch("moveMainScroll",{x:t,dragging:e!==null&&e!==void 0&&e})}}
645
+ /** @typedef {import('./photoswipe.js').default} PhotoSwipe */
646
+ /**
647
+ * @template T
648
+ * @typedef {import('./types.js').Methods<T>} Methods<T>
649
+ */const m={Escape:27,z:90,ArrowLeft:37,ArrowUp:38,ArrowRight:39,ArrowDown:40,Tab:9};
650
+ /**
651
+ * @template {keyof KeyboardKeyCodesMap} T
652
+ * @param {T} key
653
+ * @param {boolean} isKeySupported
654
+ * @returns {T | number | undefined}
655
+ */const getKeyboardEventKey=(t,e)=>e?t:m[t];class Keyboard{
656
+ /**
657
+ * @param {PhotoSwipe} pswp
658
+ */
659
+ constructor(t){this.pswp=t;this._wasFocused=false;t.on("bindEvents",(()=>{if(t.options.trapFocus){t.options.initialPointerPos||this._focusRoot();t.events.add(document,"focusin",
660
+ /** @type EventListener */
661
+ this._onFocusIn.bind(this))}t.events.add(document,"keydown",
662
+ /** @type EventListener */
663
+ this._onKeyDown.bind(this))}));const e=
664
+ /** @type {HTMLElement} */
665
+ document.activeElement;t.on("destroy",(()=>{t.options.returnFocus&&e&&this._wasFocused&&e.focus()}))}_focusRoot(){if(!this._wasFocused&&this.pswp.element){this.pswp.element.focus();this._wasFocused=true}}
666
+ /**
667
+ * @private
668
+ * @param {KeyboardEvent} e
669
+ */_onKeyDown(t){const{pswp:e}=this;if(e.dispatch("keydown",{originalEvent:t}).defaultPrevented)return;if(specialKeyUsed(t))return;
670
+ /** @type {Methods<PhotoSwipe> | undefined} */let i;
671
+ /** @type {'x' | 'y' | undefined} */let s;let n=false;const o="key"in t;switch(o?t.key:t.keyCode){case getKeyboardEventKey("Escape",o):e.options.escKey&&(i="close");break;case getKeyboardEventKey("z",o):i="toggleZoom";break;case getKeyboardEventKey("ArrowLeft",o):s="x";break;case getKeyboardEventKey("ArrowUp",o):s="y";break;case getKeyboardEventKey("ArrowRight",o):s="x";n=true;break;case getKeyboardEventKey("ArrowDown",o):n=true;s="y";break;case getKeyboardEventKey("Tab",o):this._focusRoot();break}if(s){t.preventDefault();const{currSlide:o}=e;if(e.options.arrowKeys&&s==="x"&&e.getNumItems()>1)i=n?"next":"prev";else if(o&&o.currZoomLevel>o.zoomLevels.fit){o.pan[s]+=n?-80:80;o.panTo(o.pan.x,o.pan.y)}}if(i){t.preventDefault();e[i]()}}
672
+ /**
673
+ * Trap focus inside photoswipe
674
+ *
675
+ * @private
676
+ * @param {FocusEvent} e
677
+ */_onFocusIn(t){const{template:e}=this.pswp;e&&document!==t.target&&e!==t.target&&!e.contains(
678
+ /** @type {Node} */
679
+ t.target)&&e.focus()}}const f="cubic-bezier(.4,0,.22,1)";
680
+ /** @typedef {import('./animations.js').SharedAnimationProps} SharedAnimationProps */
681
+ /** @typedef {Object} DefaultCssAnimationProps
682
+ *
683
+ * @prop {HTMLElement} target
684
+ * @prop {number} [duration]
685
+ * @prop {string} [easing]
686
+ * @prop {string} [transform]
687
+ * @prop {string} [opacity]
688
+ * */
689
+ /** @typedef {SharedAnimationProps & DefaultCssAnimationProps} CssAnimationProps */class CSSAnimation{
690
+ /**
691
+ * onComplete can be unpredictable, be careful about current state
692
+ *
693
+ * @param {CssAnimationProps} props
694
+ */
695
+ constructor(t){var e;this.props=t;const{target:i,onComplete:s,transform:n,onFinish:o=(()=>{}),duration:a=333,easing:r=f}=t;this.onFinish=o;const h=n?"transform":"opacity";const l=(e=t[h])!==null&&e!==void 0?e:"";this._target=i;this._onComplete=s;this._finished=false;this._onTransitionEnd=this._onTransitionEnd.bind(this);this._helperTimeout=setTimeout((()=>{setTransitionStyle(i,h,a,r);this._helperTimeout=setTimeout((()=>{i.addEventListener("transitionend",this._onTransitionEnd,false);i.addEventListener("transitioncancel",this._onTransitionEnd,false);this._helperTimeout=setTimeout((()=>{this._finalizeAnimation()}),a+500);i.style[h]=l}),30)}),0)}
696
+ /**
697
+ * @private
698
+ * @param {TransitionEvent} e
699
+ */_onTransitionEnd(t){t.target===this._target&&this._finalizeAnimation()}_finalizeAnimation(){if(!this._finished){this._finished=true;this.onFinish();this._onComplete&&this._onComplete()}}destroy(){this._helperTimeout&&clearTimeout(this._helperTimeout);removeTransitionStyle(this._target);this._target.removeEventListener("transitionend",this._onTransitionEnd,false);this._target.removeEventListener("transitioncancel",this._onTransitionEnd,false);this._finished||this._finalizeAnimation()}}const v=12;const g=.75;class SpringEaser{
700
+ /**
701
+ * @param {number} initialVelocity Initial velocity, px per ms.
702
+ *
703
+ * @param {number} [dampingRatio]
704
+ * Determines how bouncy animation will be.
705
+ * From 0 to 1, 0 - always overshoot, 1 - do not overshoot.
706
+ * "overshoot" refers to part of animation that
707
+ * goes beyond the final value.
708
+ *
709
+ * @param {number} [naturalFrequency]
710
+ * Determines how fast animation will slow down.
711
+ * The higher value - the stiffer the transition will be,
712
+ * and the faster it will slow down.
713
+ * Recommended value from 10 to 50
714
+ */
715
+ constructor(t,e,i){this.velocity=t*1e3;this._dampingRatio=e||g;this._naturalFrequency=i||v;this._dampedFrequency=this._naturalFrequency;this._dampingRatio<1&&(this._dampedFrequency*=Math.sqrt(1-this._dampingRatio*this._dampingRatio))}
716
+ /**
717
+ * @param {number} deltaPosition Difference between current and end position of the animation
718
+ * @param {number} deltaTime Frame duration in milliseconds
719
+ *
720
+ * @returns {number} Displacement, relative to the end position.
721
+ */easeFrame(t,e){let i=0;let s;e/=1e3;const n=Math.E**(-this._dampingRatio*this._naturalFrequency*e);if(this._dampingRatio===1){s=this.velocity+this._naturalFrequency*t;i=(t+s*e)*n;this.velocity=i*-this._naturalFrequency+s*n}else if(this._dampingRatio<1){s=1/this._dampedFrequency*(this._dampingRatio*this._naturalFrequency*t+this.velocity);const o=Math.cos(this._dampedFrequency*e);const a=Math.sin(this._dampedFrequency*e);i=n*(t*o+s*a);this.velocity=i*-this._naturalFrequency*this._dampingRatio+n*(-this._dampedFrequency*t*a+this._dampedFrequency*s*o)}return i}}
722
+ /** @typedef {import('./animations.js').SharedAnimationProps} SharedAnimationProps */
723
+ /**
724
+ * @typedef {Object} DefaultSpringAnimationProps
725
+ *
726
+ * @prop {number} start
727
+ * @prop {number} end
728
+ * @prop {number} velocity
729
+ * @prop {number} [dampingRatio]
730
+ * @prop {number} [naturalFrequency]
731
+ * @prop {(end: number) => void} onUpdate
732
+ */
733
+ /** @typedef {SharedAnimationProps & DefaultSpringAnimationProps} SpringAnimationProps */class SpringAnimation{
734
+ /**
735
+ * @param {SpringAnimationProps} props
736
+ */
737
+ constructor(t){this.props=t;this._raf=0;const{start:e,end:i,velocity:s,onUpdate:n,onComplete:o,onFinish:a=(()=>{}),dampingRatio:r,naturalFrequency:h}=t;this.onFinish=a;const l=new SpringEaser(s,r,h);let p=Date.now();let d=e-i;const animationLoop=()=>{if(this._raf){d=l.easeFrame(d,Date.now()-p);if(Math.abs(d)<1&&Math.abs(l.velocity)<50){n(i);o&&o();this.onFinish()}else{p=Date.now();n(d+i);this._raf=requestAnimationFrame(animationLoop)}}};this._raf=requestAnimationFrame(animationLoop)}destroy(){this._raf>=0&&cancelAnimationFrame(this._raf);this._raf=0}}
738
+ /** @typedef {import('./css-animation.js').CssAnimationProps} CssAnimationProps */
739
+ /** @typedef {import('./spring-animation.js').SpringAnimationProps} SpringAnimationProps */
740
+ /** @typedef {Object} SharedAnimationProps
741
+ * @prop {string} [name]
742
+ * @prop {boolean} [isPan]
743
+ * @prop {boolean} [isMainScroll]
744
+ * @prop {VoidFunction} [onComplete]
745
+ * @prop {VoidFunction} [onFinish]
746
+ */
747
+ /** @typedef {SpringAnimation | CSSAnimation} Animation */
748
+ /** @typedef {SpringAnimationProps | CssAnimationProps} AnimationProps */class Animations{constructor(){
749
+ /** @type {Animation[]} */
750
+ this.activeAnimations=[]}
751
+ /**
752
+ * @param {SpringAnimationProps} props
753
+ */startSpring(t){this._start(t,true)}
754
+ /**
755
+ * @param {CssAnimationProps} props
756
+ */startTransition(t){this._start(t)}
757
+ /**
758
+ * @private
759
+ * @param {AnimationProps} props
760
+ * @param {boolean} [isSpring]
761
+ * @returns {Animation}
762
+ */_start(t,e){const i=e?new SpringAnimation(
763
+ /** @type SpringAnimationProps */
764
+ t):new CSSAnimation(
765
+ /** @type CssAnimationProps */
766
+ t);this.activeAnimations.push(i);i.onFinish=()=>this.stop(i);return i}
767
+ /**
768
+ * @param {Animation} animation
769
+ */stop(t){t.destroy();const e=this.activeAnimations.indexOf(t);e>-1&&this.activeAnimations.splice(e,1)}stopAll(){this.activeAnimations.forEach((t=>{t.destroy()}));this.activeAnimations=[]}stopAllPan(){this.activeAnimations=this.activeAnimations.filter((t=>{if(t.props.isPan){t.destroy();return false}return true}))}stopMainScroll(){this.activeAnimations=this.activeAnimations.filter((t=>{if(t.props.isMainScroll){t.destroy();return false}return true}))}isPanRunning(){return this.activeAnimations.some((t=>t.props.isPan))}}
770
+ /** @typedef {import('./photoswipe.js').default} PhotoSwipe */class ScrollWheel{
771
+ /**
772
+ * @param {PhotoSwipe} pswp
773
+ */
774
+ constructor(t){this.pswp=t;t.events.add(t.element,"wheel",
775
+ /** @type EventListener */
776
+ this._onWheel.bind(this))}
777
+ /**
778
+ * @private
779
+ * @param {WheelEvent} e
780
+ */_onWheel(t){t.preventDefault();const{currSlide:e}=this.pswp;let{deltaX:i,deltaY:s}=t;if(e&&!this.pswp.dispatch("wheel",{originalEvent:t}).defaultPrevented)if(t.ctrlKey||this.pswp.options.wheelToZoom){if(e.isZoomable()){let i=-s;t.deltaMode===1?i*=.05:i*=t.deltaMode?1:.002;i=2**i;const n=e.currZoomLevel*i;e.zoomTo(n,{x:t.clientX,y:t.clientY})}}else if(e.isPannable()){if(t.deltaMode===1){i*=18;s*=18}e.panTo(e.pan.x-i,e.pan.y-s)}}}
781
+ /** @typedef {import('../photoswipe.js').default} PhotoSwipe */
782
+ /**
783
+ * @template T
784
+ * @typedef {import('../types.js').Methods<T>} Methods<T>
785
+ */
786
+ /**
787
+ * @typedef {Object} UIElementMarkupProps
788
+ * @prop {boolean} [isCustomSVG]
789
+ * @prop {string} inner
790
+ * @prop {string} [outlineID]
791
+ * @prop {number | string} [size]
792
+ */
793
+ /**
794
+ * @typedef {Object} UIElementData
795
+ * @prop {DefaultUIElements | string} [name]
796
+ * @prop {string} [className]
797
+ * @prop {UIElementMarkup} [html]
798
+ * @prop {boolean} [isButton]
799
+ * @prop {keyof HTMLElementTagNameMap} [tagName]
800
+ * @prop {string} [title]
801
+ * @prop {string} [ariaLabel]
802
+ * @prop {(element: HTMLElement, pswp: PhotoSwipe) => void} [onInit]
803
+ * @prop {Methods<PhotoSwipe> | ((e: MouseEvent, element: HTMLElement, pswp: PhotoSwipe) => void)} [onClick]
804
+ * @prop {'bar' | 'wrapper' | 'root'} [appendTo]
805
+ * @prop {number} [order]
806
+ */
807
+ /** @typedef {'arrowPrev' | 'arrowNext' | 'close' | 'zoom' | 'counter'} DefaultUIElements */
808
+ /** @typedef {string | UIElementMarkupProps} UIElementMarkup */
809
+ /**
810
+ * @param {UIElementMarkup} [htmlData]
811
+ * @returns {string}
812
+ */function addElementHTML(t){if(typeof t==="string")return t;if(!t||!t.isCustomSVG)return"";const e=t;let i='<svg aria-hidden="true" class="pswp__icn" viewBox="0 0 %d %d" width="%d" height="%d">';i=i.split("%d").join(
813
+ /** @type {string} */
814
+ e.size||32);e.outlineID&&(i+='<use class="pswp__icn-shadow" xlink:href="#'+e.outlineID+'"/>');i+=e.inner;i+="</svg>";return i}class UIElement{
815
+ /**
816
+ * @param {PhotoSwipe} pswp
817
+ * @param {UIElementData} data
818
+ */
819
+ constructor(t,e){var i;const s=e.name||e.className;let n=e.html;if(t.options[s]===false)return;typeof t.options[s+"SVG"]==="string"&&(n=t.options[s+"SVG"]);t.dispatch("uiElementCreate",{data:e});let o="";if(e.isButton){o+="pswp__button ";o+=e.className||`pswp__button--${e.name}`}else o+=e.className||`pswp__${e.name}`;let a=e.isButton?e.tagName||"button":e.tagName||"div";a=
820
+ /** @type {keyof HTMLElementTagNameMap} */
821
+ a.toLowerCase();
822
+ /** @type {HTMLElement} */const r=createElement(o,a);if(e.isButton){a==="button"&&(
823
+ /** @type {HTMLButtonElement} */
824
+ r.type="button");let{title:i}=e;const{ariaLabel:n}=e;typeof t.options[s+"Title"]==="string"&&(i=t.options[s+"Title"]);i&&(r.title=i);const o=n||i;o&&r.setAttribute("aria-label",o)}r.innerHTML=addElementHTML(n);e.onInit&&e.onInit(r,t);e.onClick&&(r.onclick=i=>{typeof e.onClick==="string"?t[e.onClick]():typeof e.onClick==="function"&&e.onClick(i,r,t)});const h=e.appendTo||"bar";
825
+ /** @type {HTMLElement | undefined} root element by default */let l=t.element;if(h==="bar"){t.topBar||(t.topBar=createElement("pswp__top-bar pswp__hide-on-close","div",t.scrollWrap));l=t.topBar}else{r.classList.add("pswp__hide-on-close");h==="wrapper"&&(l=t.scrollWrap)}(i=l)===null||i===void 0||i.appendChild(t.applyFilters("uiElement",r,e))}}
826
+ /** @typedef {import('./ui-element.js').UIElementData} UIElementData */
827
+ /** @typedef {import('../photoswipe.js').default} PhotoSwipe */
828
+ /**
829
+ *
830
+ * @param {HTMLElement} element
831
+ * @param {PhotoSwipe} pswp
832
+ * @param {boolean} [isNextButton]
833
+ */function initArrowButton(t,e,i){t.classList.add("pswp__button--arrow");t.setAttribute("aria-controls","pswp__items");e.on("change",(()=>{e.options.loop||(
834
+ /** @type {HTMLButtonElement} */
835
+ t.disabled=i?!(e.currIndex<e.getNumItems()-1):!(e.currIndex>0))}))}
836
+ /** @type {UIElementData} */const _={name:"arrowPrev",className:"pswp__button--arrow--prev",title:"Previous",order:10,isButton:true,appendTo:"wrapper",html:{isCustomSVG:true,size:60,inner:'<path d="M29 43l-3 3-16-16 16-16 3 3-13 13 13 13z" id="pswp__icn-arrow"/>',outlineID:"pswp__icn-arrow"},onClick:"prev",onInit:initArrowButton};
837
+ /** @type {UIElementData} */const y={name:"arrowNext",className:"pswp__button--arrow--next",title:"Next",order:11,isButton:true,appendTo:"wrapper",html:{isCustomSVG:true,size:60,inner:'<use xlink:href="#pswp__icn-arrow"/>',outlineID:"pswp__icn-arrow"},onClick:"next",onInit:(t,e)=>{initArrowButton(t,e,true)}};
838
+ /** @type {import('./ui-element.js').UIElementData} UIElementData */const w={name:"close",title:"Close",order:20,isButton:true,html:{isCustomSVG:true,inner:'<path d="M24 10l-2-2-6 6-6-6-2 2 6 6-6 6 2 2 6-6 6 6 2-2-6-6z" id="pswp__icn-close"/>',outlineID:"pswp__icn-close"},onClick:"close"};
839
+ /** @type {import('./ui-element.js').UIElementData} UIElementData */const P={name:"zoom",title:"Zoom",order:10,isButton:true,html:{isCustomSVG:true,inner:'<path d="M17.426 19.926a6 6 0 1 1 1.5-1.5L23 22.5 21.5 24l-4.074-4.074z" id="pswp__icn-zoom"/><path fill="currentColor" class="pswp__zoom-icn-bar-h" d="M11 16v-2h6v2z"/><path fill="currentColor" class="pswp__zoom-icn-bar-v" d="M13 12h2v6h-2z"/>',outlineID:"pswp__icn-zoom"},onClick:"toggleZoom"};
840
+ /** @type {import('./ui-element.js').UIElementData} UIElementData */const S={name:"preloader",appendTo:"bar",order:7,html:{isCustomSVG:true,inner:'<path fill-rule="evenodd" clip-rule="evenodd" d="M21.2 16a5.2 5.2 0 1 1-5.2-5.2V8a8 8 0 1 0 8 8h-2.8Z" id="pswp__icn-loading"/>',outlineID:"pswp__icn-loading"},onInit:(t,e)=>{
841
+ /** @type {boolean | undefined} */
842
+ let i;
843
+ /** @type {NodeJS.Timeout | null} */let s=null;
844
+ /**
845
+ * @param {string} className
846
+ * @param {boolean} add
847
+ */const toggleIndicatorClass=(e,i)=>{t.classList.toggle("pswp__preloader--"+e,i)};
848
+ /**
849
+ * @param {boolean} visible
850
+ */const setIndicatorVisibility=t=>{if(i!==t){i=t;toggleIndicatorClass("active",t)}};const updatePreloaderVisibility=()=>{var t;if((t=e.currSlide)!==null&&t!==void 0&&t.content.isLoading())s||(s=setTimeout((()=>{var t;setIndicatorVisibility(Boolean((t=e.currSlide)===null||t===void 0?void 0:t.content.isLoading()));s=null}),e.options.preloaderDelay));else{setIndicatorVisibility(false);if(s){clearTimeout(s);s=null}}};e.on("change",updatePreloaderVisibility);e.on("loadComplete",(t=>{e.currSlide===t.slide&&updatePreloaderVisibility()}));e.ui&&(e.ui.updatePreloaderVisibility=updatePreloaderVisibility)}};
851
+ /** @type {import('./ui-element.js').UIElementData} UIElementData */const x={name:"counter",order:5,onInit:(t,e)=>{e.on("change",(()=>{t.innerText=e.currIndex+1+e.options.indexIndicatorSep+e.getNumItems()}))}};
852
+ /** @typedef {import('../photoswipe.js').default} PhotoSwipe */
853
+ /** @typedef {import('./ui-element.js').UIElementData} UIElementData */
854
+ /**
855
+ * Set special class on element when image is zoomed.
856
+ *
857
+ * By default, it is used to adjust
858
+ * zoom icon and zoom cursor via CSS.
859
+ *
860
+ * @param {HTMLElement} el
861
+ * @param {boolean} isZoomedIn
862
+ */function setZoomedIn(t,e){t.classList.toggle("pswp--zoomed-in",e)}class UI{
863
+ /**
864
+ * @param {PhotoSwipe} pswp
865
+ */
866
+ constructor(t){this.pswp=t;this.isRegistered=false;
867
+ /** @type {UIElementData[]} */this.uiElementsData=[];
868
+ /** @type {(UIElement | UIElementData)[]} */this.items=[];
869
+ /** @type {() => void} */this.updatePreloaderVisibility=()=>{};
870
+ /**
871
+ * @private
872
+ * @type {number | undefined}
873
+ */this._lastUpdatedZoomLevel=void 0}init(){const{pswp:t}=this;this.isRegistered=false;this.uiElementsData=[w,_,y,P,S,x];t.dispatch("uiRegister");this.uiElementsData.sort(((t,e)=>(t.order||0)-(e.order||0)));this.items=[];this.isRegistered=true;this.uiElementsData.forEach((t=>{this.registerElement(t)}));t.on("change",(()=>{var e;(e=t.element)===null||e===void 0||e.classList.toggle("pswp--one-slide",t.getNumItems()===1)}));t.on("zoomPanUpdate",(()=>this._onZoomPanUpdate()))}
874
+ /**
875
+ * @param {UIElementData} elementData
876
+ */registerElement(t){this.isRegistered?this.items.push(new UIElement(this.pswp,t)):this.uiElementsData.push(t)}_onZoomPanUpdate(){const{template:t,currSlide:e,options:i}=this.pswp;if(this.pswp.opener.isClosing||!t||!e)return;let{currZoomLevel:s}=e;this.pswp.opener.isOpen||(s=e.zoomLevels.initial);if(s===this._lastUpdatedZoomLevel)return;this._lastUpdatedZoomLevel=s;const n=e.zoomLevels.initial-e.zoomLevels.secondary;if(Math.abs(n)<.01||!e.isZoomable()){setZoomedIn(t,false);t.classList.remove("pswp--zoom-allowed");return}t.classList.add("pswp--zoom-allowed");const o=s===e.zoomLevels.initial?e.zoomLevels.secondary:e.zoomLevels.initial;setZoomedIn(t,o<=s);i.imageClickAction!=="zoom"&&i.imageClickAction!=="zoom-or-close"||t.classList.add("pswp--click-to-zoom")}}
877
+ /** @typedef {import('./slide.js').SlideData} SlideData */
878
+ /** @typedef {import('../photoswipe.js').default} PhotoSwipe */
879
+ /** @typedef {{ x: number; y: number; w: number; innerRect?: { w: number; h: number; x: number; y: number } }} Bounds */
880
+ /**
881
+ * @param {HTMLElement} el
882
+ * @returns Bounds
883
+ */function getBoundsByElement(t){const e=t.getBoundingClientRect();return{x:e.left,y:e.top,w:e.width}}
884
+ /**
885
+ * @param {HTMLElement} el
886
+ * @param {number} imageWidth
887
+ * @param {number} imageHeight
888
+ * @returns Bounds
889
+ */function getCroppedBoundsByElement(t,e,i){const s=t.getBoundingClientRect();const n=s.width/e;const o=s.height/i;const a=n>o?n:o;const r=(s.width-e*a)/2;const h=(s.height-i*a)/2;
890
+ /**
891
+ * Coordinates of the image,
892
+ * as if it was not cropped,
893
+ * height is calculated automatically
894
+ *
895
+ * @type {Bounds}
896
+ */const l={x:s.left+r,y:s.top+h,w:e*a};l.innerRect={w:s.width,h:s.height,x:r,y:h};return l}
897
+ /**
898
+ * Get dimensions of thumbnail image
899
+ * (click on which opens photoswipe or closes photoswipe to)
900
+ *
901
+ * @param {number} index
902
+ * @param {SlideData} itemData
903
+ * @param {PhotoSwipe} instance PhotoSwipe instance
904
+ * @returns {Bounds | undefined}
905
+ */function getThumbBounds(t,e,i){const s=i.dispatch("thumbBounds",{index:t,itemData:e,instance:i});if(s.thumbBounds)return s.thumbBounds;const{element:n}=e;
906
+ /** @type {Bounds | undefined} */let o;
907
+ /** @type {HTMLElement | null | undefined} */let a;if(n&&i.options.thumbSelector!==false){const t=i.options.thumbSelector||"img";a=n.matches(t)?n:
908
+ /** @type {HTMLElement | null} */
909
+ n.querySelector(t)}a=i.applyFilters("thumbEl",a,e,t);a&&(o=e.thumbCropped?getCroppedBoundsByElement(a,e.width||e.w||0,e.height||e.h||0):getBoundsByElement(a));return i.applyFilters("thumbBounds",o,e,t)}
910
+ /** @typedef {import('../lightbox/lightbox.js').default} PhotoSwipeLightbox */
911
+ /** @typedef {import('../photoswipe.js').default} PhotoSwipe */
912
+ /** @typedef {import('../photoswipe.js').PhotoSwipeOptions} PhotoSwipeOptions */
913
+ /** @typedef {import('../photoswipe.js').DataSource} DataSource */
914
+ /** @typedef {import('../ui/ui-element.js').UIElementData} UIElementData */
915
+ /** @typedef {import('../slide/content.js').default} ContentDefault */
916
+ /** @typedef {import('../slide/slide.js').default} Slide */
917
+ /** @typedef {import('../slide/slide.js').SlideData} SlideData */
918
+ /** @typedef {import('../slide/zoom-level.js').default} ZoomLevel */
919
+ /** @typedef {import('../slide/get-thumb-bounds.js').Bounds} Bounds */
920
+ /**
921
+ * Allow adding an arbitrary props to the Content
922
+ * https://photoswipe.com/custom-content/#using-webp-image-format
923
+ * @typedef {ContentDefault & Record<string, any>} Content
924
+ */
925
+ /** @typedef {{ x?: number; y?: number }} Point */
926
+ /**
927
+ * @typedef {Object} PhotoSwipeEventsMap https://photoswipe.com/events/
928
+ *
929
+ *
930
+ * https://photoswipe.com/adding-ui-elements/
931
+ *
932
+ * @prop {undefined} uiRegister
933
+ * @prop {{ data: UIElementData }} uiElementCreate
934
+ *
935
+ *
936
+ * https://photoswipe.com/events/#initialization-events
937
+ *
938
+ * @prop {undefined} beforeOpen
939
+ * @prop {undefined} firstUpdate
940
+ * @prop {undefined} initialLayout
941
+ * @prop {undefined} change
942
+ * @prop {undefined} afterInit
943
+ * @prop {undefined} bindEvents
944
+ *
945
+ *
946
+ * https://photoswipe.com/events/#opening-or-closing-transition-events
947
+ *
948
+ * @prop {undefined} openingAnimationStart
949
+ * @prop {undefined} openingAnimationEnd
950
+ * @prop {undefined} closingAnimationStart
951
+ * @prop {undefined} closingAnimationEnd
952
+ *
953
+ *
954
+ * https://photoswipe.com/events/#closing-events
955
+ *
956
+ * @prop {undefined} close
957
+ * @prop {undefined} destroy
958
+ *
959
+ *
960
+ * https://photoswipe.com/events/#pointer-and-gesture-events
961
+ *
962
+ * @prop {{ originalEvent: PointerEvent }} pointerDown
963
+ * @prop {{ originalEvent: PointerEvent }} pointerMove
964
+ * @prop {{ originalEvent: PointerEvent }} pointerUp
965
+ * @prop {{ bgOpacity: number }} pinchClose can be default prevented
966
+ * @prop {{ panY: number }} verticalDrag can be default prevented
967
+ *
968
+ *
969
+ * https://photoswipe.com/events/#slide-content-events
970
+ *
971
+ * @prop {{ content: Content }} contentInit
972
+ * @prop {{ content: Content; isLazy: boolean }} contentLoad can be default prevented
973
+ * @prop {{ content: Content; isLazy: boolean }} contentLoadImage can be default prevented
974
+ * @prop {{ content: Content; slide: Slide; isError?: boolean }} loadComplete
975
+ * @prop {{ content: Content; slide: Slide }} loadError
976
+ * @prop {{ content: Content; width: number; height: number }} contentResize can be default prevented
977
+ * @prop {{ content: Content; width: number; height: number; slide: Slide }} imageSizeChange
978
+ * @prop {{ content: Content }} contentLazyLoad can be default prevented
979
+ * @prop {{ content: Content }} contentAppend can be default prevented
980
+ * @prop {{ content: Content }} contentActivate can be default prevented
981
+ * @prop {{ content: Content }} contentDeactivate can be default prevented
982
+ * @prop {{ content: Content }} contentRemove can be default prevented
983
+ * @prop {{ content: Content }} contentDestroy can be default prevented
984
+ *
985
+ *
986
+ * undocumented
987
+ *
988
+ * @prop {{ point: Point; originalEvent: PointerEvent }} imageClickAction can be default prevented
989
+ * @prop {{ point: Point; originalEvent: PointerEvent }} bgClickAction can be default prevented
990
+ * @prop {{ point: Point; originalEvent: PointerEvent }} tapAction can be default prevented
991
+ * @prop {{ point: Point; originalEvent: PointerEvent }} doubleTapAction can be default prevented
992
+ *
993
+ * @prop {{ originalEvent: KeyboardEvent }} keydown can be default prevented
994
+ * @prop {{ x: number; dragging: boolean }} moveMainScroll
995
+ * @prop {{ slide: Slide }} firstZoomPan
996
+ * @prop {{ slide: Slide | undefined, data: SlideData, index: number }} gettingData
997
+ * @prop {undefined} beforeResize
998
+ * @prop {undefined} resize
999
+ * @prop {undefined} viewportSize
1000
+ * @prop {undefined} updateScrollOffset
1001
+ * @prop {{ slide: Slide }} slideInit
1002
+ * @prop {{ slide: Slide }} afterSetContent
1003
+ * @prop {{ slide: Slide }} slideLoad
1004
+ * @prop {{ slide: Slide }} appendHeavy can be default prevented
1005
+ * @prop {{ slide: Slide }} appendHeavyContent
1006
+ * @prop {{ slide: Slide }} slideActivate
1007
+ * @prop {{ slide: Slide }} slideDeactivate
1008
+ * @prop {{ slide: Slide }} slideDestroy
1009
+ * @prop {{ destZoomLevel: number, centerPoint: Point | undefined, transitionDuration: number | false | undefined }} beforeZoomTo
1010
+ * @prop {{ slide: Slide }} zoomPanUpdate
1011
+ * @prop {{ slide: Slide }} initialZoomPan
1012
+ * @prop {{ slide: Slide }} calcSlideSize
1013
+ * @prop {undefined} resolutionChanged
1014
+ * @prop {{ originalEvent: WheelEvent }} wheel can be default prevented
1015
+ * @prop {{ content: Content }} contentAppendImage can be default prevented
1016
+ * @prop {{ index: number; itemData: SlideData }} lazyLoadSlide can be default prevented
1017
+ * @prop {undefined} lazyLoad
1018
+ * @prop {{ slide: Slide }} calcBounds
1019
+ * @prop {{ zoomLevels: ZoomLevel, slideData: SlideData }} zoomLevelsUpdate
1020
+ *
1021
+ *
1022
+ * legacy
1023
+ *
1024
+ * @prop {undefined} init
1025
+ * @prop {undefined} initialZoomIn
1026
+ * @prop {undefined} initialZoomOut
1027
+ * @prop {undefined} initialZoomInEnd
1028
+ * @prop {undefined} initialZoomOutEnd
1029
+ * @prop {{ dataSource: DataSource | undefined, numItems: number }} numItems
1030
+ * @prop {{ itemData: SlideData; index: number }} itemData
1031
+ * @prop {{ index: number, itemData: SlideData, instance: PhotoSwipe }} thumbBounds
1032
+ */
1033
+ /**
1034
+ * @typedef {Object} PhotoSwipeFiltersMap https://photoswipe.com/filters/
1035
+ *
1036
+ * @prop {(numItems: number, dataSource: DataSource | undefined) => number} numItems
1037
+ * Modify the total amount of slides. Example on Data sources page.
1038
+ * https://photoswipe.com/filters/#numitems
1039
+ *
1040
+ * @prop {(itemData: SlideData, index: number) => SlideData} itemData
1041
+ * Modify slide item data. Example on Data sources page.
1042
+ * https://photoswipe.com/filters/#itemdata
1043
+ *
1044
+ * @prop {(itemData: SlideData, element: HTMLElement, linkEl: HTMLAnchorElement) => SlideData} domItemData
1045
+ * Modify item data when it's parsed from DOM element. Example on Data sources page.
1046
+ * https://photoswipe.com/filters/#domitemdata
1047
+ *
1048
+ * @prop {(clickedIndex: number, e: MouseEvent, instance: PhotoSwipeLightbox) => number} clickedIndex
1049
+ * Modify clicked gallery item index.
1050
+ * https://photoswipe.com/filters/#clickedindex
1051
+ *
1052
+ * @prop {(placeholderSrc: string | false, content: Content) => string | false} placeholderSrc
1053
+ * Modify placeholder image source.
1054
+ * https://photoswipe.com/filters/#placeholdersrc
1055
+ *
1056
+ * @prop {(isContentLoading: boolean, content: Content) => boolean} isContentLoading
1057
+ * Modify if the content is currently loading.
1058
+ * https://photoswipe.com/filters/#iscontentloading
1059
+ *
1060
+ * @prop {(isContentZoomable: boolean, content: Content) => boolean} isContentZoomable
1061
+ * Modify if the content can be zoomed.
1062
+ * https://photoswipe.com/filters/#iscontentzoomable
1063
+ *
1064
+ * @prop {(useContentPlaceholder: boolean, content: Content) => boolean} useContentPlaceholder
1065
+ * Modify if the placeholder should be used for the content.
1066
+ * https://photoswipe.com/filters/#usecontentplaceholder
1067
+ *
1068
+ * @prop {(isKeepingPlaceholder: boolean, content: Content) => boolean} isKeepingPlaceholder
1069
+ * Modify if the placeholder should be kept after the content is loaded.
1070
+ * https://photoswipe.com/filters/#iskeepingplaceholder
1071
+ *
1072
+ *
1073
+ * @prop {(contentErrorElement: HTMLElement, content: Content) => HTMLElement} contentErrorElement
1074
+ * Modify an element when the content has error state (for example, if image cannot be loaded).
1075
+ * https://photoswipe.com/filters/#contenterrorelement
1076
+ *
1077
+ * @prop {(element: HTMLElement, data: UIElementData) => HTMLElement} uiElement
1078
+ * Modify a UI element that's being created.
1079
+ * https://photoswipe.com/filters/#uielement
1080
+ *
1081
+ * @prop {(thumbnail: HTMLElement | null | undefined, itemData: SlideData, index: number) => HTMLElement} thumbEl
1082
+ * Modify the thumbnail element from which opening zoom animation starts or ends.
1083
+ * https://photoswipe.com/filters/#thumbel
1084
+ *
1085
+ * @prop {(thumbBounds: Bounds | undefined, itemData: SlideData, index: number) => Bounds} thumbBounds
1086
+ * Modify the thumbnail bounds from which opening zoom animation starts or ends.
1087
+ * https://photoswipe.com/filters/#thumbbounds
1088
+ *
1089
+ * @prop {(srcsetSizesWidth: number, content: Content) => number} srcsetSizesWidth
1090
+ *
1091
+ * @prop {(preventPointerEvent: boolean, event: PointerEvent, pointerType: string) => boolean} preventPointerEvent
1092
+ *
1093
+ */
1094
+ /**
1095
+ * @template {keyof PhotoSwipeFiltersMap} T
1096
+ * @typedef {{ fn: PhotoSwipeFiltersMap[T], priority: number }} Filter
1097
+ */
1098
+ /**
1099
+ * @template {keyof PhotoSwipeEventsMap} T
1100
+ * @typedef {PhotoSwipeEventsMap[T] extends undefined ? PhotoSwipeEvent<T> : PhotoSwipeEvent<T> & PhotoSwipeEventsMap[T]} AugmentedEvent
1101
+ */
1102
+ /**
1103
+ * @template {keyof PhotoSwipeEventsMap} T
1104
+ * @typedef {(event: AugmentedEvent<T>) => void} EventCallback
1105
+ */
1106
+ /**
1107
+ * Base PhotoSwipe event object
1108
+ *
1109
+ * @template {keyof PhotoSwipeEventsMap} T
1110
+ */class PhotoSwipeEvent{
1111
+ /**
1112
+ * @param {T} type
1113
+ * @param {PhotoSwipeEventsMap[T]} [details]
1114
+ */
1115
+ constructor(t,e){this.type=t;this.defaultPrevented=false;e&&Object.assign(this,e)}preventDefault(){this.defaultPrevented=true}}class Eventable{constructor(){
1116
+ /**
1117
+ * @type {{ [T in keyof PhotoSwipeEventsMap]?: ((event: AugmentedEvent<T>) => void)[] }}
1118
+ */
1119
+ this._listeners={};
1120
+ /**
1121
+ * @type {{ [T in keyof PhotoSwipeFiltersMap]?: Filter<T>[] }}
1122
+ */this._filters={};
1123
+ /** @type {PhotoSwipe | undefined} */this.pswp=void 0;
1124
+ /** @type {PhotoSwipeOptions | undefined} */this.options=void 0}
1125
+ /**
1126
+ * @template {keyof PhotoSwipeFiltersMap} T
1127
+ * @param {T} name
1128
+ * @param {PhotoSwipeFiltersMap[T]} fn
1129
+ * @param {number} priority
1130
+ */addFilter(t,e,i=100){var s,n,o;this._filters[t]||(this._filters[t]=[]);(s=this._filters[t])===null||s===void 0||s.push({fn:e,priority:i});(n=this._filters[t])===null||n===void 0||n.sort(((t,e)=>t.priority-e.priority));(o=this.pswp)===null||o===void 0||o.addFilter(t,e,i)}
1131
+ /**
1132
+ * @template {keyof PhotoSwipeFiltersMap} T
1133
+ * @param {T} name
1134
+ * @param {PhotoSwipeFiltersMap[T]} fn
1135
+ */removeFilter(t,e){this._filters[t]&&(this._filters[t]=this._filters[t].filter((t=>t.fn!==e)));this.pswp&&this.pswp.removeFilter(t,e)}
1136
+ /**
1137
+ * @template {keyof PhotoSwipeFiltersMap} T
1138
+ * @param {T} name
1139
+ * @param {Parameters<PhotoSwipeFiltersMap[T]>} args
1140
+ * @returns {Parameters<PhotoSwipeFiltersMap[T]>[0]}
1141
+ */applyFilters(t,...e){var i;(i=this._filters[t])===null||i===void 0||i.forEach((t=>{e[0]=t.fn.apply(this,e)}));return e[0]}
1142
+ /**
1143
+ * @template {keyof PhotoSwipeEventsMap} T
1144
+ * @param {T} name
1145
+ * @param {EventCallback<T>} fn
1146
+ */on(t,e){var i,s;this._listeners[t]||(this._listeners[t]=[]);(i=this._listeners[t])===null||i===void 0||i.push(e);(s=this.pswp)===null||s===void 0||s.on(t,e)}
1147
+ /**
1148
+ * @template {keyof PhotoSwipeEventsMap} T
1149
+ * @param {T} name
1150
+ * @param {EventCallback<T>} fn
1151
+ */off(t,e){var i;this._listeners[t]&&(this._listeners[t]=this._listeners[t].filter((t=>e!==t)));(i=this.pswp)===null||i===void 0||i.off(t,e)}
1152
+ /**
1153
+ * @template {keyof PhotoSwipeEventsMap} T
1154
+ * @param {T} name
1155
+ * @param {PhotoSwipeEventsMap[T]} [details]
1156
+ * @returns {AugmentedEvent<T>}
1157
+ */dispatch(t,e){var i;if(this.pswp)return this.pswp.dispatch(t,e);const s=
1158
+ /** @type {AugmentedEvent<T>} */
1159
+ new PhotoSwipeEvent(t,e);(i=this._listeners[t])===null||i===void 0||i.forEach((t=>{t.call(this,s)}));return s}}class Placeholder{
1160
+ /**
1161
+ * @param {string | false} imageSrc
1162
+ * @param {HTMLElement} container
1163
+ */
1164
+ constructor(t,e){
1165
+ /** @type {HTMLImageElement | HTMLDivElement | null} */
1166
+ this.element=createElement("pswp__img pswp__img--placeholder",t?"img":"div",e);if(t){const e=
1167
+ /** @type {HTMLImageElement} */
1168
+ this.element;e.decoding="async";e.alt="";e.src=t;e.setAttribute("role","presentation")}this.element.setAttribute("aria-hidden","true")}
1169
+ /**
1170
+ * @param {number} width
1171
+ * @param {number} height
1172
+ */setDisplayedSize(t,e){if(this.element)if(this.element.tagName==="IMG"){setWidthHeight(this.element,250,"auto");this.element.style.transformOrigin="0 0";this.element.style.transform=toTransformString(0,0,t/250)}else setWidthHeight(this.element,t,e)}destroy(){var t;(t=this.element)!==null&&t!==void 0&&t.parentNode&&this.element.remove();this.element=null}}
1173
+ /** @typedef {import('./slide.js').default} Slide */
1174
+ /** @typedef {import('./slide.js').SlideData} SlideData */
1175
+ /** @typedef {import('../core/base.js').default} PhotoSwipeBase */
1176
+ /** @typedef {import('../util/util.js').LoadState} LoadState */class Content{
1177
+ /**
1178
+ * @param {SlideData} itemData Slide data
1179
+ * @param {PhotoSwipeBase} instance PhotoSwipe or PhotoSwipeLightbox instance
1180
+ * @param {number} index
1181
+ */
1182
+ constructor(t,i,s){this.instance=i;this.data=t;this.index=s;
1183
+ /** @type {HTMLImageElement | HTMLDivElement | undefined} */this.element=void 0;
1184
+ /** @type {Placeholder | undefined} */this.placeholder=void 0;
1185
+ /** @type {Slide | undefined} */this.slide=void 0;this.displayedImageWidth=0;this.displayedImageHeight=0;this.width=Number(this.data.w)||Number(this.data.width)||0;this.height=Number(this.data.h)||Number(this.data.height)||0;this.isAttached=false;this.hasSlide=false;this.isDecoding=false;
1186
+ /** @type {LoadState} */this.state=e.IDLE;this.data.type?this.type=this.data.type:this.data.src?this.type="image":this.type="html";this.instance.dispatch("contentInit",{content:this})}removePlaceholder(){this.placeholder&&!this.keepPlaceholder()&&setTimeout((()=>{if(this.placeholder){this.placeholder.destroy();this.placeholder=void 0}}),1e3)}
1187
+ /**
1188
+ * Preload content
1189
+ *
1190
+ * @param {boolean} isLazy
1191
+ * @param {boolean} [reload]
1192
+ */load(t,e){if(this.slide&&this.usePlaceholder())if(this.placeholder){const t=this.placeholder.element;t&&!t.parentElement&&this.slide.container.prepend(t)}else{const t=this.instance.applyFilters("placeholderSrc",!(!this.data.msrc||!this.slide.isFirstSlide)&&this.data.msrc,this);this.placeholder=new Placeholder(t,this.slide.container)}if((!this.element||e)&&!this.instance.dispatch("contentLoad",{content:this,isLazy:t}).defaultPrevented){if(this.isImageContent()){this.element=createElement("pswp__img","img");this.displayedImageWidth&&this.loadImage(t)}else{this.element=createElement("pswp__content","div");this.element.innerHTML=this.data.html||""}e&&this.slide&&this.slide.updateContentSize(true)}}
1193
+ /**
1194
+ * Preload image
1195
+ *
1196
+ * @param {boolean} isLazy
1197
+ */loadImage(t){var i,s;if(!this.isImageContent()||!this.element||this.instance.dispatch("contentLoadImage",{content:this,isLazy:t}).defaultPrevented)return;const n=
1198
+ /** @type HTMLImageElement */
1199
+ this.element;this.updateSrcsetSizes();this.data.srcset&&(n.srcset=this.data.srcset);n.src=(i=this.data.src)!==null&&i!==void 0?i:"";n.alt=(s=this.data.alt)!==null&&s!==void 0?s:"";this.state=e.LOADING;if(n.complete)this.onLoaded();else{n.onload=()=>{this.onLoaded()};n.onerror=()=>{this.onError()}}}
1200
+ /**
1201
+ * Assign slide to content
1202
+ *
1203
+ * @param {Slide} slide
1204
+ */setSlide(t){this.slide=t;this.hasSlide=true;this.instance=t.pswp}onLoaded(){this.state=e.LOADED;if(this.slide&&this.element){this.instance.dispatch("loadComplete",{slide:this.slide,content:this});if(this.slide.isActive&&this.slide.heavyAppended&&!this.element.parentNode){this.append();this.slide.updateContentSize(true)}this.state!==e.LOADED&&this.state!==e.ERROR||this.removePlaceholder()}}onError(){this.state=e.ERROR;if(this.slide){this.displayError();this.instance.dispatch("loadComplete",{slide:this.slide,isError:true,content:this});this.instance.dispatch("loadError",{slide:this.slide,content:this})}}
1205
+ /**
1206
+ * @returns {Boolean} If the content is currently loading
1207
+ */isLoading(){return this.instance.applyFilters("isContentLoading",this.state===e.LOADING,this)}
1208
+ /**
1209
+ * @returns {Boolean} If the content is in error state
1210
+ */isError(){return this.state===e.ERROR}
1211
+ /**
1212
+ * @returns {boolean} If the content is image
1213
+ */isImageContent(){return this.type==="image"}
1214
+ /**
1215
+ * Update content size
1216
+ *
1217
+ * @param {Number} width
1218
+ * @param {Number} height
1219
+ */setDisplayedSize(t,e){if(this.element){this.placeholder&&this.placeholder.setDisplayedSize(t,e);if(!this.instance.dispatch("contentResize",{content:this,width:t,height:e}).defaultPrevented){setWidthHeight(this.element,t,e);if(this.isImageContent()&&!this.isError()){const i=!this.displayedImageWidth&&t;this.displayedImageWidth=t;this.displayedImageHeight=e;i?this.loadImage(false):this.updateSrcsetSizes();this.slide&&this.instance.dispatch("imageSizeChange",{slide:this.slide,width:t,height:e,content:this})}}}}
1220
+ /**
1221
+ * @returns {boolean} If the content can be zoomed
1222
+ */isZoomable(){return this.instance.applyFilters("isContentZoomable",this.isImageContent()&&this.state!==e.ERROR,this)}updateSrcsetSizes(){if(!this.isImageContent()||!this.element||!this.data.srcset)return;const t=
1223
+ /** @type HTMLImageElement */
1224
+ this.element;const e=this.instance.applyFilters("srcsetSizesWidth",this.displayedImageWidth,this);if(!t.dataset.largestUsedSize||e>parseInt(t.dataset.largestUsedSize,10)){t.sizes=e+"px";t.dataset.largestUsedSize=String(e)}}
1225
+ /**
1226
+ * @returns {boolean} If content should use a placeholder (from msrc by default)
1227
+ */usePlaceholder(){return this.instance.applyFilters("useContentPlaceholder",this.isImageContent(),this)}lazyLoad(){this.instance.dispatch("contentLazyLoad",{content:this}).defaultPrevented||this.load(true)}
1228
+ /**
1229
+ * @returns {boolean} If placeholder should be kept after content is loaded
1230
+ */keepPlaceholder(){return this.instance.applyFilters("isKeepingPlaceholder",this.isLoading(),this)}destroy(){this.hasSlide=false;this.slide=void 0;if(!this.instance.dispatch("contentDestroy",{content:this}).defaultPrevented){this.remove();if(this.placeholder){this.placeholder.destroy();this.placeholder=void 0}if(this.isImageContent()&&this.element){this.element.onload=null;this.element.onerror=null;this.element=void 0}}}displayError(){if(this.slide){var t,e;let i=createElement("pswp__error-msg","div");i.innerText=(t=(e=this.instance.options)===null||e===void 0?void 0:e.errorMsg)!==null&&t!==void 0?t:"";i=
1231
+ /** @type {HTMLDivElement} */
1232
+ this.instance.applyFilters("contentErrorElement",i,this);this.element=createElement("pswp__content pswp__error-msg-container","div");this.element.appendChild(i);this.slide.container.innerText="";this.slide.container.appendChild(this.element);this.slide.updateContentSize(true);this.removePlaceholder()}}append(){if(this.isAttached||!this.element)return;this.isAttached=true;if(this.state===e.ERROR){this.displayError();return}if(this.instance.dispatch("contentAppend",{content:this}).defaultPrevented)return;const t="decode"in this.element;if(this.isImageContent())if(t&&this.slide&&(!this.slide.isActive||isSafari())){this.isDecoding=true;
1233
+ /** @type {HTMLImageElement} */this.element.decode().catch((()=>{})).finally((()=>{this.isDecoding=false;this.appendImage()}))}else this.appendImage();else this.slide&&!this.element.parentNode&&this.slide.container.appendChild(this.element)}activate(){if(!this.instance.dispatch("contentActivate",{content:this}).defaultPrevented&&this.slide){this.isImageContent()&&this.isDecoding&&!isSafari()?this.appendImage():this.isError()&&this.load(false,true);this.slide.holderElement&&this.slide.holderElement.setAttribute("aria-hidden","false")}}deactivate(){this.instance.dispatch("contentDeactivate",{content:this});this.slide&&this.slide.holderElement&&this.slide.holderElement.setAttribute("aria-hidden","true")}remove(){this.isAttached=false;if(!this.instance.dispatch("contentRemove",{content:this}).defaultPrevented){this.element&&this.element.parentNode&&this.element.remove();this.placeholder&&this.placeholder.element&&this.placeholder.element.remove()}}appendImage(){if(this.isAttached&&!this.instance.dispatch("contentAppendImage",{content:this}).defaultPrevented){this.slide&&this.element&&!this.element.parentNode&&this.slide.container.appendChild(this.element);this.state!==e.LOADED&&this.state!==e.ERROR||this.removePlaceholder()}}}
1234
+ /** @typedef {import('./content.js').default} Content */
1235
+ /** @typedef {import('./slide.js').default} Slide */
1236
+ /** @typedef {import('./slide.js').SlideData} SlideData */
1237
+ /** @typedef {import('../core/base.js').default} PhotoSwipeBase */
1238
+ /** @typedef {import('../photoswipe.js').default} PhotoSwipe */const z=5;
1239
+ /**
1240
+ * Lazy-load an image
1241
+ * This function is used both by Lightbox and PhotoSwipe core,
1242
+ * thus it can be called before dialog is opened.
1243
+ *
1244
+ * @param {SlideData} itemData Data about the slide
1245
+ * @param {PhotoSwipeBase} instance PhotoSwipe or PhotoSwipeLightbox instance
1246
+ * @param {number} index
1247
+ * @returns {Content} Image that is being decoded or false.
1248
+ */function lazyLoadData(t,e,i){const s=e.createContentFromData(t,i);
1249
+ /** @type {ZoomLevel | undefined} */let n;const{options:o}=e;if(o){n=new ZoomLevel(o,t,-1);let a;a=e.pswp?e.pswp.viewportSize:getViewportSize(o,e);const r=getPanAreaSize(o,a,t,i);n.update(s.width,s.height,r)}s.lazyLoad();n&&s.setDisplayedSize(Math.ceil(s.width*n.initial),Math.ceil(s.height*n.initial));return s}
1250
+ /**
1251
+ * Lazy-loads specific slide.
1252
+ * This function is used both by Lightbox and PhotoSwipe core,
1253
+ * thus it can be called before dialog is opened.
1254
+ *
1255
+ * By default, it loads image based on viewport size and initial zoom level.
1256
+ *
1257
+ * @param {number} index Slide index
1258
+ * @param {PhotoSwipeBase} instance PhotoSwipe or PhotoSwipeLightbox eventable instance
1259
+ * @returns {Content | undefined}
1260
+ */function lazyLoadSlide(t,e){const i=e.getItemData(t);if(!e.dispatch("lazyLoadSlide",{index:t,itemData:i}).defaultPrevented)return lazyLoadData(i,e,t)}class ContentLoader{
1261
+ /**
1262
+ * @param {PhotoSwipe} pswp
1263
+ */
1264
+ constructor(t){this.pswp=t;this.limit=Math.max(t.options.preload[0]+t.options.preload[1]+1,z);
1265
+ /** @type {Content[]} */this._cachedItems=[]}
1266
+ /**
1267
+ * Lazy load nearby slides based on `preload` option.
1268
+ *
1269
+ * @param {number} [diff] Difference between slide indexes that was changed recently, or 0.
1270
+ */updateLazy(t){const{pswp:e}=this;if(e.dispatch("lazyLoad").defaultPrevented)return;const{preload:i}=e.options;const s=t===void 0||t>=0;let n;for(n=0;n<=i[1];n++)this.loadSlideByIndex(e.currIndex+(s?n:-n));for(n=1;n<=i[0];n++)this.loadSlideByIndex(e.currIndex+(s?-n:n))}
1271
+ /**
1272
+ * @param {number} initialIndex
1273
+ */loadSlideByIndex(t){const e=this.pswp.getLoopedIndex(t);let i=this.getContentByIndex(e);if(!i){i=lazyLoadSlide(e,this.pswp);i&&this.addToCache(i)}}
1274
+ /**
1275
+ * @param {Slide} slide
1276
+ * @returns {Content}
1277
+ */getContentBySlide(t){let e=this.getContentByIndex(t.index);if(!e){e=this.pswp.createContentFromData(t.data,t.index);this.addToCache(e)}e.setSlide(t);return e}
1278
+ /**
1279
+ * @param {Content} content
1280
+ */addToCache(t){this.removeByIndex(t.index);this._cachedItems.push(t);if(this._cachedItems.length>this.limit){const t=this._cachedItems.findIndex((t=>!t.isAttached&&!t.hasSlide));if(t!==-1){const e=this._cachedItems.splice(t,1)[0];e.destroy()}}}
1281
+ /**
1282
+ * Removes an image from cache, does not destroy() it, just removes.
1283
+ *
1284
+ * @param {number} index
1285
+ */removeByIndex(t){const e=this._cachedItems.findIndex((e=>e.index===t));e!==-1&&this._cachedItems.splice(e,1)}
1286
+ /**
1287
+ * @param {number} index
1288
+ * @returns {Content | undefined}
1289
+ */getContentByIndex(t){return this._cachedItems.find((e=>e.index===t))}destroy(){this._cachedItems.forEach((t=>t.destroy()));this._cachedItems=[]}}
1290
+ /** @typedef {import("../photoswipe.js").default} PhotoSwipe */
1291
+ /** @typedef {import("../slide/slide.js").SlideData} SlideData */class PhotoSwipeBase extends Eventable{
1292
+ /**
1293
+ * Get total number of slides
1294
+ *
1295
+ * @returns {number}
1296
+ */
1297
+ getNumItems(){var t;let e=0;const i=(t=this.options)===null||t===void 0?void 0:t.dataSource;if(i&&"length"in i)e=i.length;else if(i&&"gallery"in i){i.items||(i.items=this._getGalleryDOMElements(i.gallery));i.items&&(e=i.items.length)}const s=this.dispatch("numItems",{dataSource:i,numItems:e});return this.applyFilters("numItems",s.numItems,i)}
1298
+ /**
1299
+ * @param {SlideData} slideData
1300
+ * @param {number} index
1301
+ * @returns {Content}
1302
+ */createContentFromData(t,e){return new Content(t,this,e)}
1303
+ /**
1304
+ * Get item data by index.
1305
+ *
1306
+ * "item data" should contain normalized information that PhotoSwipe needs to generate a slide.
1307
+ * For example, it may contain properties like
1308
+ * `src`, `srcset`, `w`, `h`, which will be used to generate a slide with image.
1309
+ *
1310
+ * @param {number} index
1311
+ * @returns {SlideData}
1312
+ */getItemData(t){var e;const i=(e=this.options)===null||e===void 0?void 0:e.dataSource;
1313
+ /** @type {SlideData | HTMLElement} */let s={};if(Array.isArray(i))s=i[t];else if(i&&"gallery"in i){i.items||(i.items=this._getGalleryDOMElements(i.gallery));s=i.items[t]}let n=s;n instanceof Element&&(n=this._domElementToItemData(n));const o=this.dispatch("itemData",{itemData:n||{},index:t});return this.applyFilters("itemData",o.itemData,t)}
1314
+ /**
1315
+ * Get array of gallery DOM elements,
1316
+ * based on childSelector and gallery element.
1317
+ *
1318
+ * @param {HTMLElement} galleryElement
1319
+ * @returns {HTMLElement[]}
1320
+ */_getGalleryDOMElements(t){var e,i;return(e=this.options)!==null&&e!==void 0&&e.children||(i=this.options)!==null&&i!==void 0&&i.childSelector?getElementsFromOption(this.options.children,this.options.childSelector,t)||[]:[t]}
1321
+ /**
1322
+ * Converts DOM element to item data object.
1323
+ *
1324
+ * @param {HTMLElement} element DOM element
1325
+ * @returns {SlideData}
1326
+ */_domElementToItemData(t){
1327
+ /** @type {SlideData} */
1328
+ const e={element:t};const i=
1329
+ /** @type {HTMLAnchorElement} */
1330
+ t.tagName==="A"?t:t.querySelector("a");if(i){e.src=i.dataset.pswpSrc||i.href;i.dataset.pswpSrcset&&(e.srcset=i.dataset.pswpSrcset);e.width=i.dataset.pswpWidth?parseInt(i.dataset.pswpWidth,10):0;e.height=i.dataset.pswpHeight?parseInt(i.dataset.pswpHeight,10):0;e.w=e.width;e.h=e.height;i.dataset.pswpType&&(e.type=i.dataset.pswpType);const n=t.querySelector("img");if(n){var s;e.msrc=n.currentSrc||n.src;e.alt=(s=n.getAttribute("alt"))!==null&&s!==void 0?s:""}(i.dataset.pswpCropped||i.dataset.cropped)&&(e.thumbCropped=true)}return this.applyFilters("domItemData",e,t,i)}
1331
+ /**
1332
+ * Lazy-load by slide data
1333
+ *
1334
+ * @param {SlideData} itemData Data about the slide
1335
+ * @param {number} index
1336
+ * @returns {Content} Image that is being decoded or false.
1337
+ */lazyLoadData(t,e){return lazyLoadData(t,this,e)}}
1338
+ /** @typedef {import('./photoswipe.js').default} PhotoSwipe */
1339
+ /** @typedef {import('./slide/get-thumb-bounds.js').Bounds} Bounds */
1340
+ /** @typedef {import('./util/animations.js').AnimationProps} AnimationProps */const b=.003;class Opener{
1341
+ /**
1342
+ * @param {PhotoSwipe} pswp
1343
+ */
1344
+ constructor(t){this.pswp=t;this.isClosed=true;this.isOpen=false;this.isClosing=false;this.isOpening=false;
1345
+ /**
1346
+ * @private
1347
+ * @type {number | false | undefined}
1348
+ */this._duration=void 0;this._useAnimation=false;this._croppedZoom=false;this._animateRootOpacity=false;this._animateBgOpacity=false;
1349
+ /**
1350
+ * @private
1351
+ * @type { HTMLDivElement | HTMLImageElement | null | undefined }
1352
+ */this._placeholder=void 0;
1353
+ /**
1354
+ * @private
1355
+ * @type { HTMLDivElement | undefined }
1356
+ */this._opacityElement=void 0;
1357
+ /**
1358
+ * @private
1359
+ * @type { HTMLDivElement | undefined }
1360
+ */this._cropContainer1=void 0;
1361
+ /**
1362
+ * @private
1363
+ * @type { HTMLElement | null | undefined }
1364
+ */this._cropContainer2=void 0;
1365
+ /**
1366
+ * @private
1367
+ * @type {Bounds | undefined}
1368
+ */this._thumbBounds=void 0;this._prepareOpen=this._prepareOpen.bind(this);t.on("firstZoomPan",this._prepareOpen)}open(){this._prepareOpen();this._start()}close(){if(this.isClosed||this.isClosing||this.isOpening)return;const t=this.pswp.currSlide;this.isOpen=false;this.isOpening=false;this.isClosing=true;this._duration=this.pswp.options.hideAnimationDuration;t&&t.currZoomLevel*t.width>=this.pswp.options.maxWidthToAnimate&&(this._duration=0);this._applyStartProps();setTimeout((()=>{this._start()}),this._croppedZoom?30:0)}_prepareOpen(){this.pswp.off("firstZoomPan",this._prepareOpen);if(!this.isOpening){const t=this.pswp.currSlide;this.isOpening=true;this.isClosing=false;this._duration=this.pswp.options.showAnimationDuration;t&&t.zoomLevels.initial*t.width>=this.pswp.options.maxWidthToAnimate&&(this._duration=0);this._applyStartProps()}}_applyStartProps(){const{pswp:t}=this;const e=this.pswp.currSlide;const{options:i}=t;if(i.showHideAnimationType==="fade"){i.showHideOpacity=true;this._thumbBounds=void 0}else if(i.showHideAnimationType==="none"){i.showHideOpacity=false;this._duration=0;this._thumbBounds=void 0}else this.isOpening&&t._initialThumbBounds?this._thumbBounds=t._initialThumbBounds:this._thumbBounds=this.pswp.getThumbBounds();this._placeholder=e===null||e===void 0?void 0:e.getPlaceholderElement();t.animations.stopAll();this._useAnimation=Boolean(this._duration&&this._duration>50);this._animateZoom=Boolean(this._thumbBounds)&&(e===null||e===void 0?void 0:e.content.usePlaceholder())&&(!this.isClosing||!t.mainScroll.isShifted());if(this._animateZoom){var s;this._animateRootOpacity=(s=i.showHideOpacity)!==null&&s!==void 0&&s}else{this._animateRootOpacity=true;if(this.isOpening&&e){e.zoomAndPanToInitial();e.applyCurrentZoomPan()}}this._animateBgOpacity=!this._animateRootOpacity&&this.pswp.options.bgOpacity>b;this._opacityElement=this._animateRootOpacity?t.element:t.bg;if(this._useAnimation){if(this._animateZoom&&this._thumbBounds&&this._thumbBounds.innerRect){var n;this._croppedZoom=true;this._cropContainer1=this.pswp.container;this._cropContainer2=(n=this.pswp.currSlide)===null||n===void 0?void 0:n.holderElement;if(t.container){t.container.style.overflow="hidden";t.container.style.width=t.viewportSize.x+"px"}}else this._croppedZoom=false;if(this.isOpening){if(this._animateRootOpacity){t.element&&(t.element.style.opacity=String(b));t.applyBgOpacity(1)}else{this._animateBgOpacity&&t.bg&&(t.bg.style.opacity=String(b));t.element&&(t.element.style.opacity="1")}if(this._animateZoom){this._setClosedStateZoomPan();if(this._placeholder){this._placeholder.style.willChange="transform";this._placeholder.style.opacity=String(b)}}}else if(this.isClosing){t.mainScroll.itemHolders[0]&&(t.mainScroll.itemHolders[0].el.style.display="none");t.mainScroll.itemHolders[2]&&(t.mainScroll.itemHolders[2].el.style.display="none");if(this._croppedZoom&&t.mainScroll.x!==0){t.mainScroll.resetPosition();t.mainScroll.resize()}}}else{this._duration=0;this._animateZoom=false;this._animateBgOpacity=false;this._animateRootOpacity=true;if(this.isOpening){t.element&&(t.element.style.opacity=String(b));t.applyBgOpacity(1)}}}_start(){this.isOpening&&this._useAnimation&&this._placeholder&&this._placeholder.tagName==="IMG"?new Promise((t=>{let e=false;let i=true;decodeImage(
1369
+ /** @type {HTMLImageElement} */
1370
+ this._placeholder).finally((()=>{e=true;i||t(true)}));setTimeout((()=>{i=false;e&&t(true)}),50);setTimeout(t,250)})).finally((()=>this._initiate())):this._initiate()}_initiate(){var t,e;(t=this.pswp.element)===null||t===void 0||t.style.setProperty("--pswp-transition-duration",this._duration+"ms");this.pswp.dispatch(this.isOpening?"openingAnimationStart":"closingAnimationStart");this.pswp.dispatch(
1371
+ /** @type {'initialZoomIn' | 'initialZoomOut'} */
1372
+ "initialZoom"+(this.isOpening?"In":"Out"));(e=this.pswp.element)===null||e===void 0||e.classList.toggle("pswp--ui-visible",this.isOpening);if(this.isOpening){this._placeholder&&(this._placeholder.style.opacity="1");this._animateToOpenState()}else this.isClosing&&this._animateToClosedState();this._useAnimation||this._onAnimationComplete()}_onAnimationComplete(){const{pswp:t}=this;this.isOpen=this.isOpening;this.isClosed=this.isClosing;this.isOpening=false;this.isClosing=false;t.dispatch(this.isOpen?"openingAnimationEnd":"closingAnimationEnd");t.dispatch(
1373
+ /** @type {'initialZoomInEnd' | 'initialZoomOutEnd'} */
1374
+ "initialZoom"+(this.isOpen?"InEnd":"OutEnd"));if(this.isClosed)t.destroy();else if(this.isOpen){var e;if(this._animateZoom&&t.container){t.container.style.overflow="visible";t.container.style.width="100%"}(e=t.currSlide)===null||e===void 0||e.applyCurrentZoomPan()}}_animateToOpenState(){const{pswp:t}=this;if(this._animateZoom){if(this._croppedZoom&&this._cropContainer1&&this._cropContainer2){this._animateTo(this._cropContainer1,"transform","translate3d(0,0,0)");this._animateTo(this._cropContainer2,"transform","none")}if(t.currSlide){t.currSlide.zoomAndPanToInitial();this._animateTo(t.currSlide.container,"transform",t.currSlide.getCurrentTransform())}}this._animateBgOpacity&&t.bg&&this._animateTo(t.bg,"opacity",String(t.options.bgOpacity));this._animateRootOpacity&&t.element&&this._animateTo(t.element,"opacity","1")}_animateToClosedState(){const{pswp:t}=this;this._animateZoom&&this._setClosedStateZoomPan(true);this._animateBgOpacity&&t.bgOpacity>.01&&t.bg&&this._animateTo(t.bg,"opacity","0");this._animateRootOpacity&&t.element&&this._animateTo(t.element,"opacity","0")}
1375
+ /**
1376
+ * @private
1377
+ * @param {boolean} [animate]
1378
+ */_setClosedStateZoomPan(t){if(!this._thumbBounds)return;const{pswp:e}=this;const{innerRect:i}=this._thumbBounds;const{currSlide:s,viewportSize:n}=e;if(this._croppedZoom&&i&&this._cropContainer1&&this._cropContainer2){const e=-n.x+(this._thumbBounds.x-i.x)+i.w;const s=-n.y+(this._thumbBounds.y-i.y)+i.h;const o=n.x-i.w;const a=n.y-i.h;if(t){this._animateTo(this._cropContainer1,"transform",toTransformString(e,s));this._animateTo(this._cropContainer2,"transform",toTransformString(o,a))}else{setTransform(this._cropContainer1,e,s);setTransform(this._cropContainer2,o,a)}}if(s){equalizePoints(s.pan,i||this._thumbBounds);s.currZoomLevel=this._thumbBounds.w/s.width;t?this._animateTo(s.container,"transform",s.getCurrentTransform()):s.applyCurrentZoomPan()}}
1379
+ /**
1380
+ * @private
1381
+ * @param {HTMLElement} target
1382
+ * @param {'transform' | 'opacity'} prop
1383
+ * @param {string} propValue
1384
+ */_animateTo(t,e,i){if(!this._duration){t.style[e]=i;return}const{animations:s}=this.pswp;
1385
+ /** @type {AnimationProps} */const n={duration:this._duration,easing:this.pswp.options.easing,onComplete:()=>{s.activeAnimations.length||this._onAnimationComplete()},target:t};n[e]=i;s.startTransition(n)}}
1386
+ /**
1387
+ * @template T
1388
+ * @typedef {import('./types.js').Type<T>} Type<T>
1389
+ */
1390
+ /** @typedef {import('./slide/slide.js').SlideData} SlideData */
1391
+ /** @typedef {import('./slide/zoom-level.js').ZoomLevelOption} ZoomLevelOption */
1392
+ /** @typedef {import('./ui/ui-element.js').UIElementData} UIElementData */
1393
+ /** @typedef {import('./main-scroll.js').ItemHolder} ItemHolder */
1394
+ /** @typedef {import('./core/eventable.js').PhotoSwipeEventsMap} PhotoSwipeEventsMap */
1395
+ /** @typedef {import('./core/eventable.js').PhotoSwipeFiltersMap} PhotoSwipeFiltersMap */
1396
+ /** @typedef {import('./slide/get-thumb-bounds').Bounds} Bounds */
1397
+ /**
1398
+ * @template {keyof PhotoSwipeEventsMap} T
1399
+ * @typedef {import('./core/eventable.js').EventCallback<T>} EventCallback<T>
1400
+ */
1401
+ /**
1402
+ * @template {keyof PhotoSwipeEventsMap} T
1403
+ * @typedef {import('./core/eventable.js').AugmentedEvent<T>} AugmentedEvent<T>
1404
+ */
1405
+ /** @typedef {{ x: number; y: number; id?: string | number }} Point */
1406
+ /** @typedef {{ top: number; bottom: number; left: number; right: number }} Padding */
1407
+ /** @typedef {SlideData[]} DataSourceArray */
1408
+ /** @typedef {{ gallery: HTMLElement; items?: HTMLElement[] }} DataSourceObject */
1409
+ /** @typedef {DataSourceArray | DataSourceObject} DataSource */
1410
+ /** @typedef {(point: Point, originalEvent: PointerEvent) => void} ActionFn */
1411
+ /** @typedef {'close' | 'next' | 'zoom' | 'zoom-or-close' | 'toggle-controls'} ActionType */
1412
+ /** @typedef {Type<PhotoSwipe> | { default: Type<PhotoSwipe> }} PhotoSwipeModule */
1413
+ /** @typedef {PhotoSwipeModule | Promise<PhotoSwipeModule> | (() => Promise<PhotoSwipeModule>)} PhotoSwipeModuleOption */
1414
+ /**
1415
+ * @typedef {string | NodeListOf<HTMLElement> | HTMLElement[] | HTMLElement} ElementProvider
1416
+ */
1417
+ /** @typedef {Partial<PreparedPhotoSwipeOptions>} PhotoSwipeOptions https://photoswipe.com/options/ */
1418
+ /**
1419
+ * @typedef {Object} PreparedPhotoSwipeOptions
1420
+ *
1421
+ * @prop {DataSource} [dataSource]
1422
+ * Pass an array of any items via dataSource option. Its length will determine amount of slides
1423
+ * (which may be modified further from numItems event).
1424
+ *
1425
+ * Each item should contain data that you need to generate slide
1426
+ * (for image slide it would be src (image URL), width (image width), height, srcset, alt).
1427
+ *
1428
+ * If these properties are not present in your initial array, you may "pre-parse" each item from itemData filter.
1429
+ *
1430
+ * @prop {number} bgOpacity
1431
+ * Background backdrop opacity, always define it via this option and not via CSS rgba color.
1432
+ *
1433
+ * @prop {number} spacing
1434
+ * Spacing between slides. Defined as ratio relative to the viewport width (0.1 = 10% of viewport).
1435
+ *
1436
+ * @prop {boolean} allowPanToNext
1437
+ * Allow swipe navigation to the next slide when the current slide is zoomed. Does not apply to mouse events.
1438
+ *
1439
+ * @prop {boolean} loop
1440
+ * If set to true you'll be able to swipe from the last to the first image.
1441
+ * Option is always false when there are less than 3 slides.
1442
+ *
1443
+ * @prop {boolean} [wheelToZoom]
1444
+ * By default PhotoSwipe zooms image with ctrl-wheel, if you enable this option - image will zoom just via wheel.
1445
+ *
1446
+ * @prop {boolean} pinchToClose
1447
+ * Pinch touch gesture to close the gallery.
1448
+ *
1449
+ * @prop {boolean} closeOnVerticalDrag
1450
+ * Vertical drag gesture to close the PhotoSwipe.
1451
+ *
1452
+ * @prop {Padding} [padding]
1453
+ * Slide area padding (in pixels).
1454
+ *
1455
+ * @prop {(viewportSize: Point, itemData: SlideData, index: number) => Padding} [paddingFn]
1456
+ * The option is checked frequently, so make sure it's performant. Overrides padding option if defined. For example:
1457
+ *
1458
+ * @prop {number | false} hideAnimationDuration
1459
+ * Transition duration in milliseconds, can be 0.
1460
+ *
1461
+ * @prop {number | false} showAnimationDuration
1462
+ * Transition duration in milliseconds, can be 0.
1463
+ *
1464
+ * @prop {number | false} zoomAnimationDuration
1465
+ * Transition duration in milliseconds, can be 0.
1466
+ *
1467
+ * @prop {string} easing
1468
+ * String, 'cubic-bezier(.4,0,.22,1)'. CSS easing function for open/close/zoom transitions.
1469
+ *
1470
+ * @prop {boolean} escKey
1471
+ * Esc key to close.
1472
+ *
1473
+ * @prop {boolean} arrowKeys
1474
+ * Left/right arrow keys for navigation.
1475
+ *
1476
+ * @prop {boolean} trapFocus
1477
+ * Trap focus within PhotoSwipe element while it's open.
1478
+ *
1479
+ * @prop {boolean} returnFocus
1480
+ * Restore focus the last active element after PhotoSwipe is closed.
1481
+ *
1482
+ * @prop {boolean} clickToCloseNonZoomable
1483
+ * If image is not zoomable (for example, smaller than viewport) it can be closed by clicking on it.
1484
+ *
1485
+ * @prop {ActionType | ActionFn | false} imageClickAction
1486
+ * Refer to click and tap actions page.
1487
+ *
1488
+ * @prop {ActionType | ActionFn | false} bgClickAction
1489
+ * Refer to click and tap actions page.
1490
+ *
1491
+ * @prop {ActionType | ActionFn | false} tapAction
1492
+ * Refer to click and tap actions page.
1493
+ *
1494
+ * @prop {ActionType | ActionFn | false} doubleTapAction
1495
+ * Refer to click and tap actions page.
1496
+ *
1497
+ * @prop {number} preloaderDelay
1498
+ * Delay before the loading indicator will be displayed,
1499
+ * if image is loaded during it - the indicator will not be displayed at all. Can be zero.
1500
+ *
1501
+ * @prop {string} indexIndicatorSep
1502
+ * Used for slide count indicator ("1 of 10 ").
1503
+ *
1504
+ * @prop {(options: PhotoSwipeOptions, pswp: PhotoSwipeBase) => Point} [getViewportSizeFn]
1505
+ * A function that should return slide viewport width and height, in format {x: 100, y: 100}.
1506
+ *
1507
+ * @prop {string} errorMsg
1508
+ * Message to display when the image wasn't able to load. If you need to display HTML - use contentErrorElement filter.
1509
+ *
1510
+ * @prop {[number, number]} preload
1511
+ * Lazy loading of nearby slides based on direction of movement. Should be an array with two integers,
1512
+ * first one - number of items to preload before the current image, second one - after the current image.
1513
+ * Two nearby images are always loaded.
1514
+ *
1515
+ * @prop {string} [mainClass]
1516
+ * Class that will be added to the root element of PhotoSwipe, may contain multiple separated by space.
1517
+ * Example on Styling page.
1518
+ *
1519
+ * @prop {HTMLElement} [appendToEl]
1520
+ * Element to which PhotoSwipe dialog will be appended when it opens.
1521
+ *
1522
+ * @prop {number} maxWidthToAnimate
1523
+ * Maximum width of image to animate, if initial rendered image width
1524
+ * is larger than this value - the opening/closing transition will be automatically disabled.
1525
+ *
1526
+ * @prop {string} [closeTitle]
1527
+ * Translating
1528
+ *
1529
+ * @prop {string} [zoomTitle]
1530
+ * Translating
1531
+ *
1532
+ * @prop {string} [arrowPrevTitle]
1533
+ * Translating
1534
+ *
1535
+ * @prop {string} [arrowNextTitle]
1536
+ * Translating
1537
+ *
1538
+ * @prop {'zoom' | 'fade' | 'none'} [showHideAnimationType]
1539
+ * To adjust opening or closing transition type use lightbox option `showHideAnimationType` (`String`).
1540
+ * It supports three values - `zoom` (default), `fade` (default if there is no thumbnail) and `none`.
1541
+ *
1542
+ * Animations are automatically disabled if user `(prefers-reduced-motion: reduce)`.
1543
+ *
1544
+ * @prop {number} index
1545
+ * Defines start slide index.
1546
+ *
1547
+ * @prop {(e: MouseEvent) => number} [getClickedIndexFn]
1548
+ *
1549
+ * @prop {boolean} [arrowPrev]
1550
+ * @prop {boolean} [arrowNext]
1551
+ * @prop {boolean} [zoom]
1552
+ * @prop {boolean} [close]
1553
+ * @prop {boolean} [counter]
1554
+ *
1555
+ * @prop {string} [arrowPrevSVG]
1556
+ * @prop {string} [arrowNextSVG]
1557
+ * @prop {string} [zoomSVG]
1558
+ * @prop {string} [closeSVG]
1559
+ * @prop {string} [counterSVG]
1560
+ *
1561
+ * @prop {string} [arrowPrevTitle]
1562
+ * @prop {string} [arrowNextTitle]
1563
+ * @prop {string} [zoomTitle]
1564
+ * @prop {string} [closeTitle]
1565
+ * @prop {string} [counterTitle]
1566
+ *
1567
+ * @prop {ZoomLevelOption} [initialZoomLevel]
1568
+ * @prop {ZoomLevelOption} [secondaryZoomLevel]
1569
+ * @prop {ZoomLevelOption} [maxZoomLevel]
1570
+ *
1571
+ * @prop {boolean} [mouseMovePan]
1572
+ * @prop {Point | null} [initialPointerPos]
1573
+ * @prop {boolean} [showHideOpacity]
1574
+ *
1575
+ * @prop {PhotoSwipeModuleOption} [pswpModule]
1576
+ * @prop {() => Promise<any>} [openPromise]
1577
+ * @prop {boolean} [preloadFirstSlide]
1578
+ * @prop {ElementProvider} [gallery]
1579
+ * @prop {string} [gallerySelector]
1580
+ * @prop {ElementProvider} [children]
1581
+ * @prop {string} [childSelector]
1582
+ * @prop {string | false} [thumbSelector]
1583
+ */
1584
+ /** @type {PreparedPhotoSwipeOptions} */const L={allowPanToNext:true,spacing:.1,loop:true,pinchToClose:true,closeOnVerticalDrag:true,hideAnimationDuration:333,showAnimationDuration:333,zoomAnimationDuration:333,escKey:true,arrowKeys:true,trapFocus:true,returnFocus:true,maxWidthToAnimate:4e3,clickToCloseNonZoomable:true,imageClickAction:"zoom-or-close",bgClickAction:"close",tapAction:"toggle-controls",doubleTapAction:"zoom",indexIndicatorSep:" / ",preloaderDelay:2e3,bgOpacity:.8,index:0,errorMsg:"The image cannot be loaded",preload:[1,2],easing:"cubic-bezier(.4,0,.22,1)"};class PhotoSwipe extends PhotoSwipeBase{
1585
+ /**
1586
+ * @param {PhotoSwipeOptions} [options]
1587
+ */
1588
+ constructor(t){super();this.options=this._prepareOptions(t||{});
1589
+ /**
1590
+ * offset of viewport relative to document
1591
+ *
1592
+ * @type {Point}
1593
+ */this.offset={x:0,y:0};
1594
+ /**
1595
+ * @type {Point}
1596
+ * @private
1597
+ */this._prevViewportSize={x:0,y:0};
1598
+ /**
1599
+ * Size of scrollable PhotoSwipe viewport
1600
+ *
1601
+ * @type {Point}
1602
+ */this.viewportSize={x:0,y:0};this.bgOpacity=1;this.currIndex=0;this.potentialIndex=0;this.isOpen=false;this.isDestroying=false;this.hasMouse=false;
1603
+ /**
1604
+ * @private
1605
+ * @type {SlideData}
1606
+ */this._initialItemData={};
1607
+ /** @type {Bounds | undefined} */this._initialThumbBounds=void 0;
1608
+ /** @type {HTMLDivElement | undefined} */this.topBar=void 0;
1609
+ /** @type {HTMLDivElement | undefined} */this.element=void 0;
1610
+ /** @type {HTMLDivElement | undefined} */this.template=void 0;
1611
+ /** @type {HTMLDivElement | undefined} */this.container=void 0;
1612
+ /** @type {HTMLElement | undefined} */this.scrollWrap=void 0;
1613
+ /** @type {Slide | undefined} */this.currSlide=void 0;this.events=new DOMEvents;this.animations=new Animations;this.mainScroll=new MainScroll(this);this.gestures=new Gestures(this);this.opener=new Opener(this);this.keyboard=new Keyboard(this);this.contentLoader=new ContentLoader(this)}
1614
+ /** @returns {boolean} */init(){if(this.isOpen||this.isDestroying)return false;this.isOpen=true;this.dispatch("init");this.dispatch("beforeOpen");this._createMainStructure();let t="pswp--open";this.gestures.supportsTouch&&(t+=" pswp--touch");this.options.mainClass&&(t+=" "+this.options.mainClass);this.element&&(this.element.className+=" "+t);this.currIndex=this.options.index||0;this.potentialIndex=this.currIndex;this.dispatch("firstUpdate");this.scrollWheel=new ScrollWheel(this);(Number.isNaN(this.currIndex)||this.currIndex<0||this.currIndex>=this.getNumItems())&&(this.currIndex=0);this.gestures.supportsTouch||this.mouseDetected();this.updateSize();this.offset.y=window.pageYOffset;this._initialItemData=this.getItemData(this.currIndex);this.dispatch("gettingData",{index:this.currIndex,data:this._initialItemData,slide:void 0});this._initialThumbBounds=this.getThumbBounds();this.dispatch("initialLayout");this.on("openingAnimationEnd",(()=>{const{itemHolders:t}=this.mainScroll;if(t[0]){t[0].el.style.display="block";this.setContent(t[0],this.currIndex-1)}if(t[2]){t[2].el.style.display="block";this.setContent(t[2],this.currIndex+1)}this.appendHeavy();this.contentLoader.updateLazy();this.events.add(window,"resize",this._handlePageResize.bind(this));this.events.add(window,"scroll",this._updatePageScrollOffset.bind(this));this.dispatch("bindEvents")}));this.mainScroll.itemHolders[1]&&this.setContent(this.mainScroll.itemHolders[1],this.currIndex);this.dispatch("change");this.opener.open();this.dispatch("afterInit");return true}
1615
+ /**
1616
+ * Get looped slide index
1617
+ * (for example, -1 will return the last slide)
1618
+ *
1619
+ * @param {number} index
1620
+ * @returns {number}
1621
+ */getLoopedIndex(t){const e=this.getNumItems();if(this.options.loop){t>e-1&&(t-=e);t<0&&(t+=e)}return clamp(t,0,e-1)}appendHeavy(){this.mainScroll.itemHolders.forEach((t=>{var e;(e=t.slide)===null||e===void 0||e.appendHeavy()}))}
1622
+ /**
1623
+ * Change the slide
1624
+ * @param {number} index New index
1625
+ */goTo(t){this.mainScroll.moveIndexBy(this.getLoopedIndex(t)-this.potentialIndex)}next(){this.goTo(this.potentialIndex+1)}prev(){this.goTo(this.potentialIndex-1)}
1626
+ /**
1627
+ * @see slide/slide.js zoomTo
1628
+ *
1629
+ * @param {Parameters<Slide['zoomTo']>} args
1630
+ */zoomTo(...t){var e;(e=this.currSlide)===null||e===void 0||e.zoomTo(...t)}toggleZoom(){var t;(t=this.currSlide)===null||t===void 0||t.toggleZoom()}close(){if(this.opener.isOpen&&!this.isDestroying){this.isDestroying=true;this.dispatch("close");this.events.removeAll();this.opener.close()}}destroy(){var t;if(this.isDestroying){this.dispatch("destroy");this._listeners={};if(this.scrollWrap){this.scrollWrap.ontouchmove=null;this.scrollWrap.ontouchend=null}(t=this.element)===null||t===void 0||t.remove();this.mainScroll.itemHolders.forEach((t=>{var e;(e=t.slide)===null||e===void 0||e.destroy()}));this.contentLoader.destroy();this.events.removeAll()}else{this.options.showHideAnimationType="none";this.close()}}
1631
+ /**
1632
+ * Refresh/reload content of a slide by its index
1633
+ *
1634
+ * @param {number} slideIndex
1635
+ */refreshSlideContent(t){this.contentLoader.removeByIndex(t);this.mainScroll.itemHolders.forEach(((e,i)=>{var s,n;let o=((s=(n=this.currSlide)===null||n===void 0?void 0:n.index)!==null&&s!==void 0?s:0)-1+i;this.canLoop()&&(o=this.getLoopedIndex(o));if(o===t){this.setContent(e,t,true);if(i===1){var a;this.currSlide=e.slide;(a=e.slide)===null||a===void 0||a.setIsActive(true)}}}));this.dispatch("change")}
1636
+ /**
1637
+ * Set slide content
1638
+ *
1639
+ * @param {ItemHolder} holder mainScroll.itemHolders array item
1640
+ * @param {number} index Slide index
1641
+ * @param {boolean} [force] If content should be set even if index wasn't changed
1642
+ */setContent(t,e,i){this.canLoop()&&(e=this.getLoopedIndex(e));if(t.slide){if(t.slide.index===e&&!i)return;t.slide.destroy();t.slide=void 0}if(!this.canLoop()&&(e<0||e>=this.getNumItems()))return;const s=this.getItemData(e);t.slide=new Slide(s,e,this);e===this.currIndex&&(this.currSlide=t.slide);t.slide.append(t.el)}
1643
+ /** @returns {Point} */getViewportCenterPoint(){return{x:this.viewportSize.x/2,y:this.viewportSize.y/2}}
1644
+ /**
1645
+ * Update size of all elements.
1646
+ * Executed on init and on page resize.
1647
+ *
1648
+ * @param {boolean} [force] Update size even if size of viewport was not changed.
1649
+ */updateSize(t){if(this.isDestroying)return;const e=getViewportSize(this.options,this);if(t||!pointsEqual(e,this._prevViewportSize)){equalizePoints(this._prevViewportSize,e);this.dispatch("beforeResize");equalizePoints(this.viewportSize,this._prevViewportSize);this._updatePageScrollOffset();this.dispatch("viewportSize");this.mainScroll.resize(this.opener.isOpen);!this.hasMouse&&window.matchMedia("(any-hover: hover)").matches&&this.mouseDetected();this.dispatch("resize")}}
1650
+ /**
1651
+ * @param {number} opacity
1652
+ */applyBgOpacity(t){this.bgOpacity=Math.max(t,0);this.bg&&(this.bg.style.opacity=String(this.bgOpacity*this.options.bgOpacity))}mouseDetected(){if(!this.hasMouse){var t;this.hasMouse=true;(t=this.element)===null||t===void 0||t.classList.add("pswp--has_mouse")}}_handlePageResize(){this.updateSize();/iPhone|iPad|iPod/i.test(window.navigator.userAgent)&&setTimeout((()=>{this.updateSize()}),500)}_updatePageScrollOffset(){this.setScrollOffset(0,window.pageYOffset)}
1653
+ /**
1654
+ * @param {number} x
1655
+ * @param {number} y
1656
+ */setScrollOffset(t,e){this.offset.x=t;this.offset.y=e;this.dispatch("updateScrollOffset")}_createMainStructure(){this.element=createElement("pswp","div");this.element.setAttribute("tabindex","-1");this.element.setAttribute("role","dialog");this.template=this.element;this.bg=createElement("pswp__bg","div",this.element);this.scrollWrap=createElement("pswp__scroll-wrap","section",this.element);this.container=createElement("pswp__container","div",this.scrollWrap);this.scrollWrap.setAttribute("aria-roledescription","carousel");this.container.setAttribute("aria-live","off");this.container.setAttribute("id","pswp__items");this.mainScroll.appendHolders();this.ui=new UI(this);this.ui.init();(this.options.appendToEl||document.body).appendChild(this.element)}
1657
+ /**
1658
+ * Get position and dimensions of small thumbnail
1659
+ * {x:,y:,w:}
1660
+ *
1661
+ * Height is optional (calculated based on the large image)
1662
+ *
1663
+ * @returns {Bounds | undefined}
1664
+ */getThumbBounds(){return getThumbBounds(this.currIndex,this.currSlide?this.currSlide.data:this._initialItemData,this)}
1665
+ /**
1666
+ * If the PhotoSwipe can have continuous loop
1667
+ * @returns Boolean
1668
+ */canLoop(){return this.options.loop&&this.getNumItems()>2}
1669
+ /**
1670
+ * @private
1671
+ * @param {PhotoSwipeOptions} options
1672
+ * @returns {PreparedPhotoSwipeOptions}
1673
+ */_prepareOptions(t){if(window.matchMedia("(prefers-reduced-motion), (update: slow)").matches){t.showHideAnimationType="none";t.zoomAnimationDuration=0}
1674
+ /** @type {PreparedPhotoSwipeOptions} */return{...L,...t}}}export{PhotoSwipe as default};
1675
+