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.
- checksums.yaml +7 -0
- data/LICENSE.md +13 -0
- data/Rakefile +15 -0
- data/app/assets/config/spree_storefront_manifest.js +6 -0
- data/app/assets/stylesheets/storefront_page_builder.css +51 -0
- data/app/controllers/concerns/spree/cart_methods.rb +40 -0
- data/app/controllers/concerns/spree/locale_urls.rb +23 -0
- data/app/controllers/concerns/spree/password_protected.rb +17 -0
- data/app/controllers/concerns/spree/theme_concern.rb +29 -0
- data/app/controllers/spree/account/addresses_controller.rb +16 -0
- data/app/controllers/spree/account/base_controller.rb +20 -0
- data/app/controllers/spree/account/newsletter_controller.rb +34 -0
- data/app/controllers/spree/account/orders_controller.rb +34 -0
- data/app/controllers/spree/account/profile_controller.rb +23 -0
- data/app/controllers/spree/account/store_credits_controller.rb +23 -0
- data/app/controllers/spree/account/wished_items_controller.rb +45 -0
- data/app/controllers/spree/addresses_controller.rb +101 -0
- data/app/controllers/spree/checkout_controller.rb +365 -0
- data/app/controllers/spree/contacts_controller.rb +46 -0
- data/app/controllers/spree/digital_links_controller.rb +48 -0
- data/app/controllers/spree/home_controller.rb +5 -0
- data/app/controllers/spree/line_items_controller.rb +96 -0
- data/app/controllers/spree/newsletter_subscribers_controller.rb +43 -0
- data/app/controllers/spree/order_status_controller.rb +32 -0
- data/app/controllers/spree/orders_controller.rb +104 -0
- data/app/controllers/spree/page_sections_controller.rb +17 -0
- data/app/controllers/spree/pages_controller.rb +13 -0
- data/app/controllers/spree/password_controller.rb +21 -0
- data/app/controllers/spree/policies_controller.rb +17 -0
- data/app/controllers/spree/posts_controller.rb +76 -0
- data/app/controllers/spree/products_controller.rb +99 -0
- data/app/controllers/spree/search_controller.rb +39 -0
- data/app/controllers/spree/seo_controller.rb +25 -0
- data/app/controllers/spree/settings_controller.rb +68 -0
- data/app/controllers/spree/store_controller.rb +247 -0
- data/app/controllers/spree/taxonomies_controller.rb +30 -0
- data/app/controllers/spree/taxons_controller.rb +46 -0
- data/app/controllers/spree/wishlists_controller.rb +19 -0
- data/app/finders/spree/storefront/variant_finder.rb +80 -0
- data/app/helpers/spree/analytics_helper.rb +28 -0
- data/app/helpers/spree/cart_helper.rb +48 -0
- data/app/helpers/spree/checkout_analytics_helper.rb +77 -0
- data/app/helpers/spree/checkout_helper.rb +58 -0
- data/app/helpers/spree/filters_helper.rb +180 -0
- data/app/helpers/spree/fonts_helper.rb +58 -0
- data/app/helpers/spree/orders_helper.rb +7 -0
- data/app/helpers/spree/page_helper.rb +67 -0
- data/app/helpers/spree/posts_helper.rb +42 -0
- data/app/helpers/spree/products_helper.rb +205 -0
- data/app/helpers/spree/storefront_helper.rb +86 -0
- data/app/helpers/spree/storefront_locale_helper.rb +42 -0
- data/app/helpers/spree/theme_helper.rb +244 -0
- data/app/helpers/spree/turbo_helper.rb +13 -0
- data/app/helpers/spree/turbo_stream_actions_helper.rb +13 -0
- data/app/helpers/spree/wishlist_helper.rb +7 -0
- data/app/javascript/spree/storefront/application.js +156 -0
- data/app/javascript/spree/storefront/controllers/accordion_controller.js +25 -0
- data/app/javascript/spree/storefront/controllers/account_nav_controller.js +10 -0
- data/app/javascript/spree/storefront/controllers/card_validation_controller.js +103 -0
- data/app/javascript/spree/storefront/controllers/carousel_controller.js +44 -0
- data/app/javascript/spree/storefront/controllers/cart_controller.js +10 -0
- data/app/javascript/spree/storefront/controllers/checkout_address_book_controller.js +28 -0
- data/app/javascript/spree/storefront/controllers/checkout_delivery_controller.js +39 -0
- data/app/javascript/spree/storefront/controllers/checkout_promotions_controller.js +28 -0
- data/app/javascript/spree/storefront/controllers/checkout_summary_controller.js +46 -0
- data/app/javascript/spree/storefront/controllers/clear_input_controller.js +23 -0
- data/app/javascript/spree/storefront/controllers/copy_input_controller.js +19 -0
- data/app/javascript/spree/storefront/controllers/dropdown_controller.js +14 -0
- data/app/javascript/spree/storefront/controllers/header_controller.js +33 -0
- data/app/javascript/spree/storefront/controllers/infinite_scroll_controller.js +31 -0
- data/app/javascript/spree/storefront/controllers/lightbox_controller.js +138 -0
- data/app/javascript/spree/storefront/controllers/mobile_nav_controller.js +17 -0
- data/app/javascript/spree/storefront/controllers/modal_controller.js +15 -0
- data/app/javascript/spree/storefront/controllers/no_ui_slider_controller.js +55 -0
- data/app/javascript/spree/storefront/controllers/pdp_desktop_gallery_controller.js +28 -0
- data/app/javascript/spree/storefront/controllers/plp_variant_picker_controller.js +151 -0
- data/app/javascript/spree/storefront/controllers/product_form_controller.js +136 -0
- data/app/javascript/spree/storefront/controllers/quantity_picker_controller.js +43 -0
- data/app/javascript/spree/storefront/controllers/search_suggestions_controller.js +61 -0
- data/app/javascript/spree/storefront/controllers/searchable_list_controller.js +25 -0
- data/app/javascript/spree/storefront/controllers/slideover_controller.js +40 -0
- data/app/javascript/spree/storefront/controllers/sticky_button_controller.js +32 -0
- data/app/javascript/spree/storefront/controllers/toggle_menu_controller.js +32 -0
- data/app/javascript/spree/storefront/controllers/turbo_stream_form_controller.js +51 -0
- data/app/javascript/spree/storefront/controllers/wished_item_controller.js +69 -0
- data/app/javascript/spree/storefront/helpers/lazy_load_controllers_with_manifest.js +78 -0
- data/app/javascript/spree/storefront/helpers/show_flash_message.js +25 -0
- data/app/models/spree/color_names.rb +35 -0
- data/app/models/spree/contact.rb +24 -0
- data/app/presenters/spree/colors_preview_styles_presenter.rb +84 -0
- data/app/presenters/spree/featured_product_presenter.rb +42 -0
- data/app/presenters/spree/mega_nav_presenter.rb +55 -0
- data/app/views/devise/passwords/edit.html.erb +22 -0
- data/app/views/devise/passwords/new.html.erb +16 -0
- data/app/views/devise/registrations/_form.html.erb +21 -0
- data/app/views/devise/registrations/edit.html.erb +24 -0
- data/app/views/devise/registrations/new.html.erb +27 -0
- data/app/views/devise/sessions/new.html.erb +25 -0
- data/app/views/devise/shared/_links.html.erb +22 -0
- data/app/views/layouts/spree/checkout.html.erb +58 -0
- data/app/views/layouts/spree/password.html.erb +34 -0
- data/app/views/layouts/spree/storefront.html.erb +38 -0
- data/app/views/spree/account/wished_items/create.turbo_stream.erb +8 -0
- data/app/views/spree/account/wished_items/destroy.turbo_stream.erb +20 -0
- data/app/views/spree/addresses/destroy.turbo_stream.erb +1 -0
- data/app/views/spree/addresses/edit.html.erb +57 -0
- data/app/views/spree/addresses/new.html.erb +71 -0
- data/app/views/spree/checkout/_address.html.erb +153 -0
- data/app/views/spree/checkout/_button_processing.html.erb +7 -0
- data/app/views/spree/checkout/_coupon_code.html.erb +55 -0
- data/app/views/spree/checkout/_credit_card.html.erb +12 -0
- data/app/views/spree/checkout/_delivery.html.erb +70 -0
- data/app/views/spree/checkout/_line_item.html.erb +26 -0
- data/app/views/spree/checkout/_line_items.html.erb +7 -0
- data/app/views/spree/checkout/_missing_all_line_items.html.erb +17 -0
- data/app/views/spree/checkout/_missing_line_items.html.erb +28 -0
- data/app/views/spree/checkout/_payment.html.erb +35 -0
- data/app/views/spree/checkout/_payment_methods.html.erb +72 -0
- data/app/views/spree/checkout/_payment_sources.html.erb +24 -0
- data/app/views/spree/checkout/_quick_checkout.html.erb +1 -0
- data/app/views/spree/checkout/_sidebar.html.erb +34 -0
- data/app/views/spree/checkout/_store_credit.html.erb +21 -0
- data/app/views/spree/checkout/_summary.html.erb +116 -0
- data/app/views/spree/checkout/_user_account.html.erb +9 -0
- data/app/views/spree/checkout/apply_coupon_code.turbo_stream.erb +45 -0
- data/app/views/spree/checkout/apply_store_credit.turbo_stream.erb +19 -0
- data/app/views/spree/checkout/edit.html.erb +98 -0
- data/app/views/spree/checkout/payment/_check.html.erb +0 -0
- data/app/views/spree/checkout/payment/_gateway.html.erb +74 -0
- data/app/views/spree/checkout/payment/_store_credit.html.erb +13 -0
- data/app/views/spree/checkout/remove_coupon_code.turbo_stream.erb +34 -0
- data/app/views/spree/checkout/remove_store_credit.turbo_stream.erb +19 -0
- data/app/views/spree/checkout/update.turbo_stream.erb +25 -0
- data/app/views/spree/home/index.html.erb +1 -0
- data/app/views/spree/line_items/create.turbo_stream.erb +13 -0
- data/app/views/spree/line_items/destroy.turbo_stream.erb +11 -0
- data/app/views/spree/line_items/update.turbo_stream.erb +10 -0
- data/app/views/spree/newsletter_subscribers/create.turbo_stream.erb +7 -0
- data/app/views/spree/order_status/new.html.erb +16 -0
- data/app/views/spree/page_sections/show.html.erb +3 -0
- data/app/views/spree/pages/show.html.erb +1 -0
- data/app/views/spree/password/show.html.erb +1 -0
- data/app/views/spree/posts/index.html.erb +1 -0
- data/app/views/spree/posts/related_products.html.erb +7 -0
- data/app/views/spree/posts/show.html.erb +1 -0
- data/app/views/spree/products/index.html.erb +1 -0
- data/app/views/spree/products/index.turbo_stream.erb +1 -0
- data/app/views/spree/products/related.html.erb +3 -0
- data/app/views/spree/products/show.html.erb +1 -0
- data/app/views/spree/search/show.html.erb +6 -0
- data/app/views/spree/search/show.turbo_stream.erb +1 -0
- data/app/views/spree/search/suggestions.turbo_stream.erb +8 -0
- data/app/views/spree/seo/robots.text.erb +31 -0
- data/app/views/spree/seo/sitemap.xml.erb +25 -0
- data/app/views/spree/shared/_fonts.html.erb +14 -0
- data/app/views/spree/shared/_head.html.erb +36 -0
- data/app/views/spree/shared/_load_more_products.turbo_stream.erb +7 -0
- data/app/views/spree/shared/_product_listing_page.html.erb +11 -0
- data/app/views/spree/shared/_products.html.erb +1 -0
- data/app/views/spree/taxonomies/show.html.erb +1 -0
- data/app/views/spree/taxons/show.html.erb +1 -0
- data/app/views/spree/taxons/show.turbo_stream.erb +1 -0
- data/app/views/spree/waitlists/create.turbo_stream.erb +9 -0
- data/app/views/themes/default/kaminari/storefront/_first_page.html.erb +8 -0
- data/app/views/themes/default/kaminari/storefront/_gap.html.erb +8 -0
- data/app/views/themes/default/kaminari/storefront/_last_page.html.erb +8 -0
- data/app/views/themes/default/kaminari/storefront/_next_page.html.erb +13 -0
- data/app/views/themes/default/kaminari/storefront/_page.html.erb +10 -0
- data/app/views/themes/default/kaminari/storefront/_paginator.html.erb +27 -0
- data/app/views/themes/default/kaminari/storefront/_prev_page.html.erb +13 -0
- data/app/views/themes/default/spree/account/_account_nav.html.erb +46 -0
- data/app/views/themes/default/spree/account/_order.html.erb +39 -0
- data/app/views/themes/default/spree/account/_orders.html.erb +16 -0
- data/app/views/themes/default/spree/account/addresses/_address.html.erb +42 -0
- data/app/views/themes/default/spree/account/addresses/index.html.erb +28 -0
- data/app/views/themes/default/spree/account/newsletter/_newsletter_settings.html.erb +13 -0
- data/app/views/themes/default/spree/account/newsletter/edit.html.erb +16 -0
- data/app/views/themes/default/spree/account/newsletter/update.html.erb +1 -0
- data/app/views/themes/default/spree/account/orders/index.html.erb +24 -0
- data/app/views/themes/default/spree/account/orders/show.html.erb +22 -0
- data/app/views/themes/default/spree/account/profile/edit.html.erb +36 -0
- data/app/views/themes/default/spree/account/store_credits/_store_credit_event.html.erb +29 -0
- data/app/views/themes/default/spree/account/store_credits/index.html.erb +31 -0
- data/app/views/themes/default/spree/checkout/_footer.html.erb +10 -0
- data/app/views/themes/default/spree/checkout/complete.html.erb +84 -0
- data/app/views/themes/default/spree/contacts/new.html.erb +23 -0
- data/app/views/themes/default/spree/orders/_cart.html.erb +14 -0
- data/app/views/themes/default/spree/orders/_empty.html.erb +11 -0
- data/app/views/themes/default/spree/orders/_line_item.html.erb +47 -0
- data/app/views/themes/default/spree/orders/_line_item_quantity.html.erb +11 -0
- data/app/views/themes/default/spree/orders/_summary.html.erb +41 -0
- data/app/views/themes/default/spree/orders/edit.html.erb +18 -0
- data/app/views/themes/default/spree/orders/show.html.erb +6 -0
- data/app/views/themes/default/spree/page_sections/_announcement_bar.html.erb +10 -0
- data/app/views/themes/default/spree/page_sections/_custom_code.html.erb +5 -0
- data/app/views/themes/default/spree/page_sections/_featured_product.html.erb +136 -0
- data/app/views/themes/default/spree/page_sections/_featured_taxon.html.erb +116 -0
- data/app/views/themes/default/spree/page_sections/_featured_taxons.html.erb +71 -0
- data/app/views/themes/default/spree/page_sections/_footer.html.erb +62 -0
- data/app/views/themes/default/spree/page_sections/_header.html.erb +166 -0
- data/app/views/themes/default/spree/page_sections/_image_banner.html.erb +57 -0
- data/app/views/themes/default/spree/page_sections/_image_with_text.html.erb +66 -0
- data/app/views/themes/default/spree/page_sections/_main_password_footer.html.erb +64 -0
- data/app/views/themes/default/spree/page_sections/_main_password_header.html.erb +54 -0
- data/app/views/themes/default/spree/page_sections/_newsletter.html.erb +47 -0
- data/app/views/themes/default/spree/page_sections/_page_title.html.erb +7 -0
- data/app/views/themes/default/spree/page_sections/_post_details.html.erb +19 -0
- data/app/views/themes/default/spree/page_sections/_post_grid.html.erb +11 -0
- data/app/views/themes/default/spree/page_sections/_product_details.html.erb +102 -0
- data/app/views/themes/default/spree/page_sections/_product_grid.html.erb +52 -0
- data/app/views/themes/default/spree/page_sections/_related_products.html.erb +15 -0
- data/app/views/themes/default/spree/page_sections/_rich_text.html.erb +18 -0
- data/app/views/themes/default/spree/page_sections/_taxon_banner.html.erb +37 -0
- data/app/views/themes/default/spree/page_sections/_taxon_grid.html.erb +103 -0
- data/app/views/themes/default/spree/page_sections/_video.html.erb +27 -0
- data/app/views/themes/default/spree/page_sections/nav/_desktop.html.erb +49 -0
- data/app/views/themes/default/spree/page_sections/nav/_mobile.html.erb +136 -0
- data/app/views/themes/default/spree/policies/show.html.erb +11 -0
- data/app/views/themes/default/spree/posts/_json_ld.html.erb +20 -0
- data/app/views/themes/default/spree/posts/_pagination.html.erb +1 -0
- data/app/views/themes/default/spree/posts/_post.html.erb +13 -0
- data/app/views/themes/default/spree/products/_add_to_cart_button.html.erb +58 -0
- data/app/views/themes/default/spree/products/_add_to_waitlist.html.erb +36 -0
- data/app/views/themes/default/spree/products/_add_to_wishlist.html.erb +33 -0
- data/app/views/themes/default/spree/products/_breadcrumbs.html.erb +23 -0
- data/app/views/themes/default/spree/products/_color_picker.html.erb +19 -0
- data/app/views/themes/default/spree/products/_color_swatches.html.erb +61 -0
- data/app/views/themes/default/spree/products/_details.html.erb +55 -0
- data/app/views/themes/default/spree/products/_featured_image.html.erb +37 -0
- data/app/views/themes/default/spree/products/_filters.html.erb +45 -0
- data/app/views/themes/default/spree/products/_json_ld.html.erb +38 -0
- data/app/views/themes/default/spree/products/_json_ld_list.html.erb +9 -0
- data/app/views/themes/default/spree/products/_json_ld_variant.html.erb +10 -0
- data/app/views/themes/default/spree/products/_label.html.erb +26 -0
- data/app/views/themes/default/spree/products/_media_gallery.html.erb +94 -0
- data/app/views/themes/default/spree/products/_price.html.erb +59 -0
- data/app/views/themes/default/spree/products/_product.html.erb +62 -0
- data/app/views/themes/default/spree/products/_quantity_selector.html.erb +32 -0
- data/app/views/themes/default/spree/products/_returns_policy_modal.html.erb +22 -0
- data/app/views/themes/default/spree/products/_show_more_button.html.erb +8 -0
- data/app/views/themes/default/spree/products/_sort.html.erb +45 -0
- data/app/views/themes/default/spree/products/_swiper.html.erb +85 -0
- data/app/views/themes/default/spree/products/_tags.html.erb +0 -0
- data/app/views/themes/default/spree/products/_variant_options.html.erb +71 -0
- data/app/views/themes/default/spree/products/_variant_picker.html.erb +50 -0
- data/app/views/themes/default/spree/products/filters/_availability.html.erb +32 -0
- data/app/views/themes/default/spree/products/filters/_colors.html.erb +23 -0
- data/app/views/themes/default/spree/products/filters/_generic.html.erb +75 -0
- data/app/views/themes/default/spree/products/filters/_price.html.erb +35 -0
- data/app/views/themes/default/spree/products/filters/_taxons.erb +78 -0
- data/app/views/themes/default/spree/search/_suggestions.html.erb +92 -0
- data/app/views/themes/default/spree/settings/show.html.erb +32 -0
- data/app/views/themes/default/spree/shared/_account_pane.html.erb +28 -0
- data/app/views/themes/default/spree/shared/_address.html.erb +35 -0
- data/app/views/themes/default/spree/shared/_cart_icon.html.erb +13 -0
- data/app/views/themes/default/spree/shared/_cart_pane.html.erb +38 -0
- data/app/views/themes/default/spree/shared/_css_variables.html.erb +54 -0
- data/app/views/themes/default/spree/shared/_custom_head.html.erb +0 -0
- data/app/views/themes/default/spree/shared/_error_messages.html.erb +9 -0
- data/app/views/themes/default/spree/shared/_error_messages_without_base_attribute.html.erb +15 -0
- data/app/views/themes/default/spree/shared/_flash.html.erb +16 -0
- data/app/views/themes/default/spree/shared/_flashes.html.erb +10 -0
- data/app/views/themes/default/spree/shared/_json_ld.html.erb +32 -0
- data/app/views/themes/default/spree/shared/_line_item_options.html.erb +18 -0
- data/app/views/themes/default/spree/shared/_logo.html.erb +42 -0
- data/app/views/themes/default/spree/shared/_meta_tags.html.erb +45 -0
- data/app/views/themes/default/spree/shared/_order_details.html.erb +106 -0
- data/app/views/themes/default/spree/shared/_order_line_item.html.erb +65 -0
- data/app/views/themes/default/spree/shared/_order_shipment.html.erb +71 -0
- data/app/views/themes/default/spree/shared/_search.html.erb +32 -0
- data/app/views/themes/default/spree/shared/_title.html.erb +3 -0
- data/app/views/themes/default/spree/shared/_wishlist_icon.html.erb +13 -0
- data/app/views/themes/default/spree/shared/icons/_account.html.erb +17 -0
- data/app/views/themes/default/spree/shared/icons/_arrow-left.html.erb +8 -0
- data/app/views/themes/default/spree/shared/icons/_arrow-right.html.erb +3 -0
- data/app/views/themes/default/spree/shared/icons/_bell.html.erb +9 -0
- data/app/views/themes/default/spree/shared/icons/_cart.html.erb +10 -0
- data/app/views/themes/default/spree/shared/icons/_cart_48.html.erb +6 -0
- data/app/views/themes/default/spree/shared/icons/_check.html.erb +4 -0
- data/app/views/themes/default/spree/shared/icons/_chevron.html.erb +15 -0
- data/app/views/themes/default/spree/shared/icons/_chevron_down.html.erb +5 -0
- data/app/views/themes/default/spree/shared/icons/_chevron_right.html.erb +15 -0
- data/app/views/themes/default/spree/shared/icons/_chevron_up.html.erb +3 -0
- data/app/views/themes/default/spree/shared/icons/_close.html.erb +9 -0
- data/app/views/themes/default/spree/shared/icons/_cross.html.erb +16 -0
- data/app/views/themes/default/spree/shared/icons/_delete.html.erb +3 -0
- data/app/views/themes/default/spree/shared/icons/_delivery.html.erb +5 -0
- data/app/views/themes/default/spree/shared/icons/_disabled.html.erb +13 -0
- data/app/views/themes/default/spree/shared/icons/_edit.html.erb +3 -0
- data/app/views/themes/default/spree/shared/icons/_facebook.html.erb +16 -0
- data/app/views/themes/default/spree/shared/icons/_filter.html.erb +8 -0
- data/app/views/themes/default/spree/shared/icons/_heart.html.erb +12 -0
- data/app/views/themes/default/spree/shared/icons/_info.html.erb +7 -0
- data/app/views/themes/default/spree/shared/icons/_instagram.html.erb +18 -0
- data/app/views/themes/default/spree/shared/icons/_lock.html.erb +13 -0
- data/app/views/themes/default/spree/shared/icons/_menu.html.erb +10 -0
- data/app/views/themes/default/spree/shared/icons/_minus.html.erb +5 -0
- data/app/views/themes/default/spree/shared/icons/_pinch.html.erb +6 -0
- data/app/views/themes/default/spree/shared/icons/_pinterest.html.erb +8 -0
- data/app/views/themes/default/spree/shared/icons/_plus.html.erb +17 -0
- data/app/views/themes/default/spree/shared/icons/_return.html.erb +11 -0
- data/app/views/themes/default/spree/shared/icons/_search.html.erb +17 -0
- data/app/views/themes/default/spree/shared/icons/_spinner.html.erb +1 -0
- data/app/views/themes/default/spree/shared/icons/_spotify.html.erb +8 -0
- data/app/views/themes/default/spree/shared/icons/_tiktok.html.erb +9 -0
- data/app/views/themes/default/spree/shared/icons/_twitter.html.erb +16 -0
- data/app/views/themes/default/spree/shared/icons/_youtube.html.erb +9 -0
- data/app/views/themes/default/spree/shared/icons/_zoom.html.erb +10 -0
- data/app/views/themes/default/spree/wishlists/_no_wished_items.html.erb +10 -0
- data/app/views/themes/default/spree/wishlists/_wished_item.html.erb +38 -0
- data/app/views/themes/default/spree/wishlists/show.html.erb +17 -0
- data/config/i18n-tasks.yml +176 -0
- data/config/importmap.rb +22 -0
- data/config/initializers/assets.rb +1 -0
- data/config/initializers/heroicon.rb +10 -0
- data/config/locales/en.yml +76 -0
- data/config/routes.rb +88 -0
- data/lib/generators/spree/storefront/install/install_generator.rb +45 -0
- data/lib/generators/spree/storefront/install/templates/application.tailwind.css +1760 -0
- data/lib/generators/spree/storefront/install/templates/dev +16 -0
- data/lib/generators/spree/storefront/install/templates/tailwind.config.js +128 -0
- data/lib/generators/spree/storefront/theme/templates/model.rb.tt +12 -0
- data/lib/generators/spree/storefront/theme/theme_generator.rb +41 -0
- data/lib/spree/storefront/configuration.rb +11 -0
- data/lib/spree/storefront/engine.rb +51 -0
- data/lib/spree/storefront/testing_support/capybara_utils.rb +13 -0
- data/lib/spree/storefront.rb +16 -0
- data/lib/spree_storefront.rb +1 -0
- data/vendor/colornames.json +1 -0
- data/vendor/javascript/@kanety--stimulus-accordion.js +4 -0
- data/vendor/javascript/@stimulus-components--carousel.js +4 -0
- data/vendor/javascript/card-validator.js +4 -0
- data/vendor/javascript/credit-card-type.js +4 -0
- data/vendor/javascript/headroom.js.js +19 -0
- data/vendor/javascript/nouislider.js +4 -0
- data/vendor/javascript/photoswipe--dist--photoswipe-lightbox.esm.js.js +667 -0
- data/vendor/javascript/photoswipe.js +1675 -0
- data/vendor/javascript/stimulus-read-more.js +4 -0
- data/vendor/javascript/stimulus-scroll-to.js +4 -0
- data/vendor/javascript/swiper--bundle.js +4 -0
- 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
|
+
|