@salla.sa/twilight-components 2.14.500 → 2.14.502
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.
- package/dist/cjs/catalog-recommendations-Bzt0HRy8.js +94 -0
- package/dist/cjs/{filepond-B9PtMjXt.js → filepond-CIptScDL.js} +1 -1
- package/dist/cjs/{filepond-plugin-file-poster-CMd-UUZx.js → filepond-plugin-file-poster-DwHNuiWd.js} +1 -1
- package/dist/cjs/{filepond-plugin-file-validate-size-DpJalosf.js → filepond-plugin-file-validate-size-BMLUB-u0.js} +1 -1
- package/dist/cjs/{filepond-plugin-file-validate-type-CZjeYI0w.js → filepond-plugin-file-validate-type-DiRunNiR.js} +1 -1
- package/dist/cjs/{filepond-plugin-image-edit-Bl6fwgrn.js → filepond-plugin-image-edit-DujWvbF5.js} +1 -1
- package/dist/cjs/{filepond-plugin-image-exif-orientation-BeQ8iCyg.js → filepond-plugin-image-exif-orientation-CzdpRTlH.js} +1 -1
- package/dist/cjs/{filepond-plugin-image-preview-BkGKXzOB.js → filepond-plugin-image-preview-CpEEysug.js} +1 -1
- package/dist/cjs/{functions-UaOjMOb2.js → functions-DL46a-BT.js} +1 -1
- package/dist/cjs/{index-Cd5xdrCT.js → index-CeCWRg4V.js} +6 -2
- package/dist/cjs/{index-CQPk27Eg.js → index-D7i3cgiE.js} +1 -1
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/salla-accordion-body_2.cjs.entry.js +1 -1
- package/dist/cjs/salla-accordion_6.cjs.entry.js +1 -1
- package/dist/cjs/salla-add-product-button_5.cjs.entry.js +70 -30
- package/dist/cjs/salla-advertisement.cjs.entry.js +1 -1
- package/dist/cjs/salla-alert_2.cjs.entry.js +1 -1
- package/dist/cjs/salla-app-install-alert.cjs.entry.js +1 -1
- package/dist/cjs/salla-apps-icons.cjs.entry.js +1 -1
- package/dist/cjs/salla-badge.cjs.entry.js +1 -1
- package/dist/cjs/salla-basket-gap.cjs.entry.js +269 -0
- package/dist/cjs/salla-booking-field_7.cjs.entry.js +10 -10
- package/dist/cjs/salla-bullet-delivery_2.cjs.entry.js +1 -1
- package/dist/cjs/salla-cart-coupons.cjs.entry.js +1 -1
- package/dist/cjs/salla-cart-item-offers_2.cjs.entry.js +1 -1
- package/dist/cjs/salla-cart-summary-card.cjs.entry.js +1 -1
- package/dist/cjs/salla-cashback-banner.cjs.entry.js +1 -1
- package/dist/cjs/salla-comment-factors.cjs.entry.js +1 -1
- package/dist/cjs/salla-comment-form_8.cjs.entry.js +1 -1
- package/dist/cjs/salla-conditional-offer.cjs.entry.js +1 -1
- package/dist/cjs/salla-contacts.cjs.entry.js +1 -1
- package/dist/cjs/salla-cookies-bar.cjs.entry.js +1 -1
- package/dist/cjs/salla-count-down_2.cjs.entry.js +4 -3
- package/dist/cjs/salla-custom-fields.cjs.entry.js +1 -1
- package/dist/cjs/salla-delivery-promise.cjs.entry.js +1 -1
- package/dist/cjs/salla-edit-order-button.cjs.entry.js +1 -1
- package/dist/cjs/salla-filters-widget.cjs.entry.js +1 -1
- package/dist/cjs/salla-filters.cjs.entry.js +1 -1
- package/dist/cjs/salla-fulfillment-methods.cjs.entry.js +1 -1
- package/dist/cjs/salla-gifting.cjs.entry.js +1 -1
- package/dist/cjs/salla-hook.cjs.entry.js +1 -1
- package/dist/cjs/salla-infinite-scroll.cjs.entry.js +1 -1
- package/dist/cjs/salla-installment.cjs.entry.js +1 -1
- package/dist/cjs/salla-list-tile.cjs.entry.js +1 -1
- package/dist/cjs/salla-localization-modal.cjs.entry.js +1 -1
- package/dist/cjs/salla-login-modal.cjs.entry.js +1 -1
- package/dist/cjs/salla-loyalty-banner.cjs.entry.js +2 -2
- package/dist/cjs/salla-loyalty-exchange-product-card_5.cjs.entry.js +3 -3
- package/dist/cjs/salla-loyalty-hero_2.cjs.entry.js +2 -2
- package/dist/cjs/salla-loyalty-panel.cjs.entry.js +3 -3
- package/dist/cjs/salla-loyalty-points-banner.cjs.entry.js +1 -1
- package/dist/cjs/salla-loyalty-points-history.cjs.entry.js +1 -1
- package/dist/cjs/salla-loyalty-prize-item.cjs.entry.js +1 -1
- package/dist/cjs/salla-loyalty-program.cjs.entry.js +3 -3
- package/dist/cjs/salla-loyalty-reward.cjs.entry.js +2 -2
- package/dist/cjs/salla-loyalty.cjs.entry.js +1 -1
- package/dist/cjs/salla-maintenance-alert.cjs.entry.js +1 -1
- package/dist/cjs/salla-map_2.cjs.entry.js +1 -1
- package/dist/cjs/salla-menu.cjs.entry.js +1 -1
- package/dist/cjs/salla-metadata.cjs.entry.js +1 -1
- package/dist/cjs/salla-multiple-bundle-product-cart_2.cjs.entry.js +1 -1
- package/dist/cjs/salla-multiple-bundle-product-options-modal_2.cjs.entry.js +1 -1
- package/dist/cjs/salla-multiple-bundle-product.cjs.entry.js +1 -1
- package/dist/cjs/salla-next-order-coupon.cjs.entry.js +1 -1
- package/dist/cjs/salla-notification-item.cjs.entry.js +1 -1
- package/dist/cjs/salla-notifications.cjs.entry.js +1 -1
- package/dist/cjs/salla-offer-modal.cjs.entry.js +1 -1
- package/dist/cjs/salla-offer.cjs.entry.js +1 -1
- package/dist/cjs/salla-order-branch.cjs.entry.js +1 -1
- package/dist/cjs/salla-order-cancel.cjs.entry.js +1 -1
- package/dist/cjs/salla-order-details-multiple-bundle-product.cjs.entry.js +1 -1
- package/dist/cjs/salla-order-details-options.cjs.entry.js +1 -1
- package/dist/cjs/salla-order-details.cjs.entry.js +1 -1
- package/dist/cjs/salla-order-edit-item.cjs.entry.js +1 -1
- package/dist/cjs/salla-order-edit-product-card.cjs.entry.js +1 -1
- package/dist/cjs/salla-order-edit.cjs.entry.js +1 -1
- package/dist/cjs/salla-order-summary.cjs.entry.js +1 -1
- package/dist/cjs/salla-order-totals-card.cjs.entry.js +1 -1
- package/dist/cjs/salla-orders.cjs.entry.js +1 -1
- package/dist/cjs/salla-payments.cjs.entry.js +1 -1
- package/dist/cjs/salla-placeholder.cjs.entry.js +1 -1
- package/dist/cjs/salla-price-range.cjs.entry.js +1 -1
- package/dist/cjs/salla-product-card-embed.cjs.entry.js +1 -1
- package/dist/cjs/salla-product-card_2.cjs.entry.js +1 -1
- package/dist/cjs/salla-product-size-guide.cjs.entry.js +1 -1
- package/dist/cjs/salla-products-list.cjs.entry.js +1 -1
- package/dist/cjs/salla-quick-order.cjs.entry.js +1 -1
- package/dist/cjs/salla-rating-modal-v2.cjs.entry.js +1 -1
- package/dist/cjs/salla-rating-modal.cjs.entry.js +1 -1
- package/dist/cjs/salla-review-factors-tags.cjs.entry.js +1 -1
- package/dist/cjs/salla-scopes.cjs.entry.js +1 -1
- package/dist/cjs/salla-search.cjs.entry.js +1 -1
- package/dist/cjs/salla-skeleton.cjs.entry.js +1 -1
- package/dist/cjs/salla-slider.cjs.entry.js +1 -1
- package/dist/cjs/salla-social-share.cjs.entry.js +1 -1
- package/dist/cjs/salla-social.cjs.entry.js +1 -1
- package/dist/cjs/salla-tab-content_3.cjs.entry.js +1 -1
- package/dist/cjs/salla-tiered-offer.cjs.entry.js +1 -1
- package/dist/cjs/salla-tooltip.cjs.entry.js +1 -1
- package/dist/cjs/salla-trust-badges.cjs.entry.js +1 -1
- package/dist/cjs/salla-user-menu.cjs.entry.js +1 -1
- package/dist/cjs/salla-user-profile.cjs.entry.js +1 -1
- package/dist/cjs/salla-user-settings.cjs.entry.js +1 -1
- package/dist/cjs/salla-verify.cjs.entry.js +1 -1
- package/dist/cjs/salla-wallet.cjs.entry.js +1 -1
- package/dist/cjs/salla-wishlist-actions.cjs.entry.js +1 -1
- package/dist/cjs/{tracked-promise-DwUVHl1m.js → tracked-promise-DQhIwhjv.js} +1 -1
- package/dist/cjs/twilight.cjs.js +2 -2
- package/dist/cjs/{vanilla-picker-BTiOI13l.js → vanilla-picker-DlMSPnXD.js} +1 -1
- package/dist/collection/collection-manifest.json +1 -0
- package/dist/collection/components/salla-basket-gap/salla-basket-gap.css +3 -0
- package/dist/collection/components/salla-basket-gap/salla-basket-gap.js +306 -0
- package/dist/collection/components/salla-bought-together/salla-bought-together.js +5 -17
- package/dist/collection/components/salla-count-down/salla-count-down.js +3 -2
- package/dist/collection/components/salla-quick-buy/salla-quick-buy.js +87 -7
- package/dist/collection/shared/catalog-recommendations.js +89 -0
- package/dist/components/catalog-recommendations.js +91 -0
- package/dist/components/index.js +2 -2
- package/dist/components/salla-basket-gap.d.ts +11 -0
- package/dist/components/salla-basket-gap.js +402 -0
- package/dist/components/salla-bought-together.js +5 -17
- package/dist/components/salla-count-down2.js +3 -2
- package/dist/components/salla-quick-buy2.js +66 -12
- package/dist/esm/catalog-recommendations-9fzJJ_Ox.js +91 -0
- package/dist/esm/{filepond-DjtqIoeD.js → filepond--jRYda4S.js} +1 -1
- package/dist/esm/{filepond-plugin-file-poster-CFxoEHLP.js → filepond-plugin-file-poster-CckDj7tB.js} +1 -1
- package/dist/esm/{filepond-plugin-file-validate-size-BnBRYL0y.js → filepond-plugin-file-validate-size-9b6v_l6Z.js} +1 -1
- package/dist/esm/{filepond-plugin-file-validate-type-Dr5ofT9v.js → filepond-plugin-file-validate-type-CjGNB5Pv.js} +1 -1
- package/dist/esm/{filepond-plugin-image-edit-DyMeCzTZ.js → filepond-plugin-image-edit-UIthhs_A.js} +1 -1
- package/dist/esm/{filepond-plugin-image-exif-orientation-ngtve06j.js → filepond-plugin-image-exif-orientation-DPcDqfwl.js} +1 -1
- package/dist/esm/{filepond-plugin-image-preview-aqxBqAYf.js → filepond-plugin-image-preview-BWlnovlW.js} +1 -1
- package/dist/esm/{functions-Drikk4uf.js → functions-Vnk4zyHS.js} +1 -1
- package/dist/esm/{index-DuoSRdS5.js → index-BOjfFBGe.js} +6 -2
- package/dist/esm/{index-CaZkz-p0.js → index-D8XjJYaY.js} +1 -1
- package/dist/esm/loader.js +3 -3
- package/dist/esm/salla-accordion-body_2.entry.js +1 -1
- package/dist/esm/salla-accordion_6.entry.js +1 -1
- package/dist/esm/salla-add-product-button_5.entry.js +70 -30
- package/dist/esm/salla-advertisement.entry.js +1 -1
- package/dist/esm/salla-alert_2.entry.js +1 -1
- package/dist/esm/salla-app-install-alert.entry.js +1 -1
- package/dist/esm/salla-apps-icons.entry.js +1 -1
- package/dist/esm/salla-badge.entry.js +1 -1
- package/dist/esm/salla-basket-gap.entry.js +267 -0
- package/dist/esm/salla-booking-field_7.entry.js +10 -10
- package/dist/esm/salla-bullet-delivery_2.entry.js +1 -1
- package/dist/esm/salla-cart-coupons.entry.js +1 -1
- package/dist/esm/salla-cart-item-offers_2.entry.js +1 -1
- package/dist/esm/salla-cart-summary-card.entry.js +1 -1
- package/dist/esm/salla-cashback-banner.entry.js +1 -1
- package/dist/esm/salla-comment-factors.entry.js +1 -1
- package/dist/esm/salla-comment-form_8.entry.js +1 -1
- package/dist/esm/salla-conditional-offer.entry.js +1 -1
- package/dist/esm/salla-contacts.entry.js +1 -1
- package/dist/esm/salla-cookies-bar.entry.js +1 -1
- package/dist/esm/salla-count-down_2.entry.js +4 -3
- package/dist/esm/salla-custom-fields.entry.js +1 -1
- package/dist/esm/salla-delivery-promise.entry.js +1 -1
- package/dist/esm/salla-edit-order-button.entry.js +1 -1
- package/dist/esm/salla-filters-widget.entry.js +1 -1
- package/dist/esm/salla-filters.entry.js +1 -1
- package/dist/esm/salla-fulfillment-methods.entry.js +1 -1
- package/dist/esm/salla-gifting.entry.js +1 -1
- package/dist/esm/salla-hook.entry.js +1 -1
- package/dist/esm/salla-infinite-scroll.entry.js +1 -1
- package/dist/esm/salla-installment.entry.js +1 -1
- package/dist/esm/salla-list-tile.entry.js +1 -1
- package/dist/esm/salla-localization-modal.entry.js +1 -1
- package/dist/esm/salla-login-modal.entry.js +1 -1
- package/dist/esm/salla-loyalty-banner.entry.js +2 -2
- package/dist/esm/salla-loyalty-exchange-product-card_5.entry.js +3 -3
- package/dist/esm/salla-loyalty-hero_2.entry.js +2 -2
- package/dist/esm/salla-loyalty-panel.entry.js +3 -3
- package/dist/esm/salla-loyalty-points-banner.entry.js +1 -1
- package/dist/esm/salla-loyalty-points-history.entry.js +1 -1
- package/dist/esm/salla-loyalty-prize-item.entry.js +1 -1
- package/dist/esm/salla-loyalty-program.entry.js +3 -3
- package/dist/esm/salla-loyalty-reward.entry.js +2 -2
- package/dist/esm/salla-loyalty.entry.js +1 -1
- package/dist/esm/salla-maintenance-alert.entry.js +1 -1
- package/dist/esm/salla-map_2.entry.js +1 -1
- package/dist/esm/salla-menu.entry.js +1 -1
- package/dist/esm/salla-metadata.entry.js +1 -1
- package/dist/esm/salla-multiple-bundle-product-cart_2.entry.js +1 -1
- package/dist/esm/salla-multiple-bundle-product-options-modal_2.entry.js +1 -1
- package/dist/esm/salla-multiple-bundle-product.entry.js +1 -1
- package/dist/esm/salla-next-order-coupon.entry.js +1 -1
- package/dist/esm/salla-notification-item.entry.js +1 -1
- package/dist/esm/salla-notifications.entry.js +1 -1
- package/dist/esm/salla-offer-modal.entry.js +1 -1
- package/dist/esm/salla-offer.entry.js +1 -1
- package/dist/esm/salla-order-branch.entry.js +1 -1
- package/dist/esm/salla-order-cancel.entry.js +1 -1
- package/dist/esm/salla-order-details-multiple-bundle-product.entry.js +1 -1
- package/dist/esm/salla-order-details-options.entry.js +1 -1
- package/dist/esm/salla-order-details.entry.js +1 -1
- package/dist/esm/salla-order-edit-item.entry.js +1 -1
- package/dist/esm/salla-order-edit-product-card.entry.js +1 -1
- package/dist/esm/salla-order-edit.entry.js +1 -1
- package/dist/esm/salla-order-summary.entry.js +1 -1
- package/dist/esm/salla-order-totals-card.entry.js +1 -1
- package/dist/esm/salla-orders.entry.js +1 -1
- package/dist/esm/salla-payments.entry.js +1 -1
- package/dist/esm/salla-placeholder.entry.js +1 -1
- package/dist/esm/salla-price-range.entry.js +1 -1
- package/dist/esm/salla-product-card-embed.entry.js +1 -1
- package/dist/esm/salla-product-card_2.entry.js +1 -1
- package/dist/esm/salla-product-size-guide.entry.js +1 -1
- package/dist/esm/salla-products-list.entry.js +1 -1
- package/dist/esm/salla-quick-order.entry.js +1 -1
- package/dist/esm/salla-rating-modal-v2.entry.js +1 -1
- package/dist/esm/salla-rating-modal.entry.js +1 -1
- package/dist/esm/salla-review-factors-tags.entry.js +1 -1
- package/dist/esm/salla-scopes.entry.js +1 -1
- package/dist/esm/salla-search.entry.js +1 -1
- package/dist/esm/salla-skeleton.entry.js +1 -1
- package/dist/esm/salla-slider.entry.js +1 -1
- package/dist/esm/salla-social-share.entry.js +1 -1
- package/dist/esm/salla-social.entry.js +1 -1
- package/dist/esm/salla-tab-content_3.entry.js +1 -1
- package/dist/esm/salla-tiered-offer.entry.js +1 -1
- package/dist/esm/salla-tooltip.entry.js +1 -1
- package/dist/esm/salla-trust-badges.entry.js +1 -1
- package/dist/esm/salla-user-menu.entry.js +1 -1
- package/dist/esm/salla-user-profile.entry.js +1 -1
- package/dist/esm/salla-user-settings.entry.js +1 -1
- package/dist/esm/salla-verify.entry.js +1 -1
- package/dist/esm/salla-wallet.entry.js +1 -1
- package/dist/esm/salla-wishlist-actions.entry.js +1 -1
- package/dist/esm/{tracked-promise-CUM6cNiF.js → tracked-promise-DPZbMaax.js} +1 -1
- package/dist/esm/twilight.js +3 -3
- package/dist/esm/{vanilla-picker-kF8Cgi5q.js → vanilla-picker-Db2JkkPK.js} +1 -1
- package/dist/twilight/{p-74cac8a8.entry.js → p-0076e440.entry.js} +1 -1
- package/dist/twilight/{p-c3530e7a.entry.js → p-0245e2c0.entry.js} +1 -1
- package/dist/twilight/{p-00d73870.entry.js → p-05533207.entry.js} +1 -1
- package/dist/twilight/{p-a5eeb082.entry.js → p-0809ec4c.entry.js} +1 -1
- package/dist/twilight/{p-404d3645.entry.js → p-0846a39c.entry.js} +1 -1
- package/dist/twilight/{p-0604eb27.entry.js → p-0a36a8df.entry.js} +1 -1
- package/dist/twilight/{p-2c4f4539.entry.js → p-0c4b50a8.entry.js} +1 -1
- package/dist/twilight/{p-9a161a84.entry.js → p-145f51a4.entry.js} +1 -1
- package/dist/twilight/{p-a1d3a45f.entry.js → p-16060f64.entry.js} +1 -1
- package/dist/twilight/{p-cd65e560.entry.js → p-16407a84.entry.js} +1 -1
- package/dist/twilight/{p-ca0a62f9.entry.js → p-166287b8.entry.js} +1 -1
- package/dist/twilight/{p-2104f800.entry.js → p-1ad1e565.entry.js} +1 -1
- package/dist/twilight/{p-92d37b3e.entry.js → p-1d7a5517.entry.js} +1 -1
- package/dist/twilight/{p-ca52add5.entry.js → p-2495ba63.entry.js} +1 -1
- package/dist/twilight/{p-95d8a11b.entry.js → p-24af33da.entry.js} +1 -1
- package/dist/twilight/p-24cdca69.entry.js +4 -0
- package/dist/twilight/{p-4fb48be8.entry.js → p-25be867c.entry.js} +1 -1
- package/dist/twilight/{p-0daa8221.entry.js → p-27ed0bb7.entry.js} +1 -1
- package/dist/twilight/{p-d3a9573e.entry.js → p-2f0b08a4.entry.js} +1 -1
- package/dist/twilight/{p-a34c031b.entry.js → p-3075687f.entry.js} +1 -1
- package/dist/twilight/{p-0a1f28c9.entry.js → p-3330e9b1.entry.js} +1 -1
- package/dist/twilight/{p-1d75fdd9.entry.js → p-3431ad47.entry.js} +1 -1
- package/dist/twilight/{p-dc6b3dfb.entry.js → p-36d820e1.entry.js} +1 -1
- package/dist/twilight/{p-d8c9d454.entry.js → p-3ed4357e.entry.js} +1 -1
- package/dist/twilight/{p-72291ad7.entry.js → p-3f137515.entry.js} +1 -1
- package/dist/twilight/{p-67d7bd8b.entry.js → p-404e7d5b.entry.js} +1 -1
- package/dist/twilight/{p-b0437615.entry.js → p-45b6ec5f.entry.js} +1 -1
- package/dist/twilight/{p-2c9c0815.entry.js → p-490e83b7.entry.js} +1 -1
- package/dist/twilight/{p-99ff235e.entry.js → p-4a9fbb6e.entry.js} +1 -1
- package/dist/twilight/{p-d39bf8b5.entry.js → p-4cf257b2.entry.js} +1 -1
- package/dist/twilight/{p-0c1721e1.entry.js → p-4d32ef06.entry.js} +1 -1
- package/dist/twilight/{p-74e009df.entry.js → p-5259181e.entry.js} +1 -1
- package/dist/twilight/{p-f8d642b2.entry.js → p-534c5ce0.entry.js} +1 -1
- package/dist/twilight/{p-d54b75de.entry.js → p-540b7c0c.entry.js} +1 -1
- package/dist/twilight/{p-9e27778a.entry.js → p-5492fef2.entry.js} +1 -1
- package/dist/twilight/{p-0b814320.entry.js → p-558eef65.entry.js} +1 -1
- package/dist/twilight/{p-be973f87.entry.js → p-56c55c15.entry.js} +1 -1
- package/dist/twilight/{p-7df52f7b.entry.js → p-5804914e.entry.js} +1 -1
- package/dist/twilight/p-591dc47b.entry.js +4 -0
- package/dist/twilight/{p-7b9ed1e4.entry.js → p-5cbeee21.entry.js} +1 -1
- package/dist/twilight/{p-01636f53.entry.js → p-5f0565be.entry.js} +1 -1
- package/dist/twilight/{p-92ec265b.entry.js → p-5f3b36fe.entry.js} +1 -1
- package/dist/twilight/{p-51bc9c4d.entry.js → p-628fb2e7.entry.js} +1 -1
- package/dist/twilight/{p-ae83c325.entry.js → p-62d4e685.entry.js} +1 -1
- package/dist/twilight/{p-5fe29fcf.entry.js → p-648704dc.entry.js} +1 -1
- package/dist/twilight/{p-9196b7a9.entry.js → p-67d5bded.entry.js} +1 -1
- package/dist/twilight/{p-19c6d83a.entry.js → p-6bdbd0f3.entry.js} +1 -1
- package/dist/twilight/{p-5a215130.entry.js → p-71d90a27.entry.js} +1 -1
- package/dist/twilight/{p-56ba7f94.entry.js → p-73acf48f.entry.js} +1 -1
- package/dist/twilight/{p-9cc2e54c.entry.js → p-7460706e.entry.js} +1 -1
- package/dist/twilight/{p-39389b31.entry.js → p-7ab7f179.entry.js} +1 -1
- package/dist/twilight/{p-aed6d4eb.entry.js → p-7be94cc2.entry.js} +1 -1
- package/dist/twilight/{p-286d9ba3.entry.js → p-7d10ae17.entry.js} +1 -1
- package/dist/twilight/{p-5cb10852.entry.js → p-7ef4cd2e.entry.js} +1 -1
- package/dist/twilight/{p-f5ac65b4.entry.js → p-85333282.entry.js} +1 -1
- package/dist/twilight/{p-c6b82041.entry.js → p-8e298b27.entry.js} +1 -1
- package/dist/twilight/{p-a2e8a9d1.entry.js → p-9018a13b.entry.js} +1 -1
- package/dist/twilight/{p-953da0b5.entry.js → p-91853c93.entry.js} +1 -1
- package/dist/twilight/{p-15c3b0cc.entry.js → p-95e6774b.entry.js} +1 -1
- package/dist/twilight/{p-77d816b8.entry.js → p-980deae9.entry.js} +1 -1
- package/dist/twilight/{p-0e6a0989.entry.js → p-9b9eb649.entry.js} +1 -1
- package/dist/twilight/p-9fzJJ_Ox.js +4 -0
- package/dist/twilight/p-B-m0e6tL.js +4 -0
- package/dist/twilight/{p-lYj74H1f.js → p-B93EBMau.js} +1 -1
- package/dist/twilight/{p-Ca84RIBI.js → p-BI-CCdbp.js} +1 -1
- package/dist/twilight/{p-DuoSRdS5.js → p-BOjfFBGe.js} +1 -1
- package/dist/twilight/{p-DQXp-sN5.js → p-BTd4Mp32.js} +1 -1
- package/dist/twilight/{p-BYpv9A8D.js → p-Bdy-19kn.js} +1 -1
- package/dist/twilight/{p-DYcV7UW8.js → p-Be0gsl2J.js} +1 -1
- package/dist/twilight/{p-KZ7SFw0C.js → p-BeJV4WrP.js} +1 -1
- package/dist/twilight/{p-DYgnIxqR.js → p-BsrZms1J.js} +1 -1
- package/dist/twilight/{p-kflOqry6.js → p-CIW_DqnB.js} +1 -1
- package/dist/twilight/{p-DMHhYV48.js → p-CZFiZZq_.js} +1 -1
- package/dist/twilight/{p-CHOv1Smw.js → p-CkIv9zJH.js} +1 -1
- package/dist/twilight/{p-061fdc55.entry.js → p-a38b58ca.entry.js} +1 -1
- package/dist/twilight/{p-47c9e882.entry.js → p-a60c4d82.entry.js} +1 -1
- package/dist/twilight/{p-3c96d5af.entry.js → p-a6a3a2af.entry.js} +1 -1
- package/dist/twilight/{p-eb2e3e67.entry.js → p-a8683925.entry.js} +1 -1
- package/dist/twilight/{p-04fadfb3.entry.js → p-a9dd59e6.entry.js} +1 -1
- package/dist/twilight/{p-98186fb3.entry.js → p-ae1d9d25.entry.js} +1 -1
- package/dist/twilight/{p-e5c2df5a.entry.js → p-aec3c134.entry.js} +1 -1
- package/dist/twilight/{p-f9a3f3f4.entry.js → p-b879c791.entry.js} +1 -1
- package/dist/twilight/{p-bd2672ee.entry.js → p-b8875211.entry.js} +1 -1
- package/dist/twilight/{p-4fff03a8.entry.js → p-b9d30af2.entry.js} +1 -1
- package/dist/twilight/{p-5f47eb12.entry.js → p-bb4774ef.entry.js} +1 -1
- package/dist/twilight/{p-6e535738.entry.js → p-bd3b3b56.entry.js} +1 -1
- package/dist/twilight/{p-72c9cd44.entry.js → p-bf22b091.entry.js} +1 -1
- package/dist/twilight/{p-9c798a1a.entry.js → p-c23d9868.entry.js} +1 -1
- package/dist/twilight/{p-90d53c9b.entry.js → p-c2fd3800.entry.js} +1 -1
- package/dist/twilight/p-c3598ac9.entry.js +4 -0
- package/dist/twilight/{p-c6d64b53.entry.js → p-cbe499ec.entry.js} +1 -1
- package/dist/twilight/{p-ecdf7027.entry.js → p-cdc167c6.entry.js} +1 -1
- package/dist/twilight/{p-022343f3.entry.js → p-d3807e1d.entry.js} +1 -1
- package/dist/twilight/{p-f9912293.entry.js → p-d3a91c42.entry.js} +1 -1
- package/dist/twilight/{p-d49130fc.entry.js → p-d4242231.entry.js} +1 -1
- package/dist/twilight/p-d454c6ac.entry.js +4 -0
- package/dist/twilight/{p-a96e5e06.entry.js → p-d86136e7.entry.js} +1 -1
- package/dist/twilight/{p-8658fefd.entry.js → p-dfc06251.entry.js} +1 -1
- package/dist/twilight/{p-930ff69a.entry.js → p-e033c3ad.entry.js} +1 -1
- package/dist/twilight/{p-03db477f.entry.js → p-e416ee2b.entry.js} +1 -1
- package/dist/twilight/{p-7e730733.entry.js → p-ef0ff326.entry.js} +1 -1
- package/dist/twilight/{p-f4eba1d1.entry.js → p-f00e25a1.entry.js} +1 -1
- package/dist/twilight/{p-0bc04e3f.entry.js → p-f5a960be.entry.js} +1 -1
- package/dist/twilight/{p-168e3ad8.entry.js → p-f6623828.entry.js} +1 -1
- package/dist/twilight/{p-54e43314.entry.js → p-fb79a1b4.entry.js} +1 -1
- package/dist/twilight/{p-f060a3dd.entry.js → p-fb8e031a.entry.js} +1 -1
- package/dist/twilight/{p-bdda14f6.entry.js → p-fd53f57a.entry.js} +1 -1
- package/dist/twilight/twilight.esm.js +1 -1
- package/dist/types/components/salla-basket-gap/salla-basket-gap.d.ts +52 -0
- package/dist/types/components/salla-quick-buy/salla-quick-buy.d.ts +20 -0
- package/dist/types/components.d.ts +43 -0
- package/dist/types/shared/catalog-recommendations.d.ts +2 -0
- package/package.json +5 -5
- package/dist/twilight/p-25ZR4Fc8.js +0 -4
- package/dist/twilight/p-2985e01e.entry.js +0 -4
- package/dist/twilight/p-931c44fb.entry.js +0 -4
- package/dist/twilight/p-982ccb80.entry.js +0 -4
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Crafted with ❤ by Salla
|
|
3
|
+
*/
|
|
4
|
+
import { Host, h } from "@stencil/core";
|
|
5
|
+
import { fetchCartBoughtTogether } from "../../shared/catalog-recommendations";
|
|
6
|
+
export class SallaBasketGap {
|
|
7
|
+
constructor() {
|
|
8
|
+
/**
|
|
9
|
+
* Maximum number of recommendations to fetch.
|
|
10
|
+
*/
|
|
11
|
+
this.limit = 10;
|
|
12
|
+
this.products = [];
|
|
13
|
+
this.isLoading = true;
|
|
14
|
+
this.canRender = true;
|
|
15
|
+
this.title = '';
|
|
16
|
+
this.addToCartLabel = '';
|
|
17
|
+
this.weightLabel = '';
|
|
18
|
+
this.discountLabel = '';
|
|
19
|
+
this.placeholder = '';
|
|
20
|
+
this.fetchGeneration = 0;
|
|
21
|
+
this.isSyncingCart = false;
|
|
22
|
+
this.cartItemChangedHandler = (response) => {
|
|
23
|
+
const items = response?.data?.cart?.items ?? [];
|
|
24
|
+
const ids = items.map((i) => String(i.product_id)).filter(Boolean);
|
|
25
|
+
// Reflect a newly added product in the cart list without a full page refresh.
|
|
26
|
+
this.syncCartItemsDom(items);
|
|
27
|
+
this.fetchRecommendations(ids);
|
|
28
|
+
};
|
|
29
|
+
this.beforeAddItemHandler = (data) => {
|
|
30
|
+
const id = String(data?.id ?? '');
|
|
31
|
+
if (id && this.products.some((p) => String(p.id) === id) && salla.cart?.api) {
|
|
32
|
+
salla.cart.api.addToCartSource = 'basket_gap';
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
this.addButtonSuccessHandler = (event) => {
|
|
36
|
+
const productId = event?.target?.getAttribute?.('product-id');
|
|
37
|
+
if (!productId)
|
|
38
|
+
return;
|
|
39
|
+
const product = this.products.find((p) => String(p.id) === String(productId));
|
|
40
|
+
if (!product)
|
|
41
|
+
return;
|
|
42
|
+
const items = event?.detail?.data?.items ?? [];
|
|
43
|
+
const cartItem = items.find((i) => String(i.product_id) === String(product.id)) ?? items.slice(-1)[0];
|
|
44
|
+
salla.event.emit('salla-basket-gap::product.added', [{
|
|
45
|
+
product,
|
|
46
|
+
position: this.products.indexOf(product) + 1,
|
|
47
|
+
cartItem,
|
|
48
|
+
cartId: event?.detail?.data?.id,
|
|
49
|
+
source: 'basket_gap',
|
|
50
|
+
}]);
|
|
51
|
+
};
|
|
52
|
+
salla.lang.onLoaded(() => {
|
|
53
|
+
this.title = salla.lang.get('pages.cart.basket_gap_title');
|
|
54
|
+
this.addToCartLabel = salla.lang.get('pages.cart.add_to_cart');
|
|
55
|
+
this.weightLabel = salla.lang.get('pages.products.weight');
|
|
56
|
+
this.discountLabel = salla.lang.get('pages.products.discount');
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
componentWillLoad() {
|
|
60
|
+
salla.onReady().then(() => {
|
|
61
|
+
if (!salla.config.get('store.settings.cart.basket_gap')) {
|
|
62
|
+
this.canRender = false;
|
|
63
|
+
this.isLoading = false;
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
this.title = salla.lang.get('pages.cart.basket_gap_title');
|
|
67
|
+
this.addToCartLabel = salla.lang.get('pages.cart.add_to_cart');
|
|
68
|
+
this.weightLabel = salla.lang.get('pages.products.weight');
|
|
69
|
+
this.discountLabel = salla.lang.get('pages.products.discount');
|
|
70
|
+
this.placeholder = salla.url.asset(salla.config.get('theme.settings.placeholder'));
|
|
71
|
+
const cachedCart = salla.storage.get('cart');
|
|
72
|
+
const cachedIds = (cachedCart?.items ?? []).map((i) => String(i.product_id)).filter(Boolean);
|
|
73
|
+
if (cachedIds.length) {
|
|
74
|
+
return this.fetchRecommendations(cachedIds);
|
|
75
|
+
}
|
|
76
|
+
return salla.api.cart.details()
|
|
77
|
+
.then(({ data: { cart } }) => {
|
|
78
|
+
const objectIDs = (cart?.items ?? []).map((i) => String(i.product_id)).filter(Boolean);
|
|
79
|
+
return this.fetchRecommendations(objectIDs);
|
|
80
|
+
})
|
|
81
|
+
.catch(() => {
|
|
82
|
+
this.canRender = false;
|
|
83
|
+
this.isLoading = false;
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
componentDidLoad() {
|
|
88
|
+
this.positionUnderCartItems();
|
|
89
|
+
}
|
|
90
|
+
componentDidUpdate() {
|
|
91
|
+
document.lazyLoadInstance?.update(this.host.querySelectorAll('.lazy'));
|
|
92
|
+
this.positionUnderCartItems();
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Cart item rows on the storefront cart page (excluding the order-options block).
|
|
96
|
+
* Kept defensive: themes that don't use the `form[id^="item-"]` pattern return none.
|
|
97
|
+
*/
|
|
98
|
+
getCartItemForms(root = document) {
|
|
99
|
+
return Array.from(root.querySelectorAll('form[id^="item-"]'))
|
|
100
|
+
.filter((form) => !form.closest('.cart-options'));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The component is injected at the theme's `cart:items.end` hook, which may sit
|
|
104
|
+
* below the order options/offers. Move the host to render directly under the
|
|
105
|
+
* cart items. No-ops when the cart item pattern isn't present.
|
|
106
|
+
*/
|
|
107
|
+
positionUnderCartItems() {
|
|
108
|
+
const items = this.getCartItemForms();
|
|
109
|
+
const lastItem = items[items.length - 1];
|
|
110
|
+
if (lastItem && lastItem.nextElementSibling !== this.host) {
|
|
111
|
+
lastItem.after(this.host);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Reflect a newly added product in the cart list without a full page reload.
|
|
116
|
+
* The whole item list is replaced with the fresh server-rendered rows because
|
|
117
|
+
* Salla re-assigns cart line-item ids on add, so diffing by id would duplicate
|
|
118
|
+
* the existing rows. No-ops on themes without the cart item markup.
|
|
119
|
+
*/
|
|
120
|
+
syncCartItemsDom(cartItems) {
|
|
121
|
+
if (!cartItems?.length || this.isSyncingCart)
|
|
122
|
+
return;
|
|
123
|
+
const missing = cartItems.filter((item) => !document.getElementById('item-' + item.id));
|
|
124
|
+
if (!missing.length)
|
|
125
|
+
return;
|
|
126
|
+
this.isSyncingCart = true;
|
|
127
|
+
fetch(window.location.href, { headers: { 'X-Requested-With': 'XMLHttpRequest' }, credentials: 'same-origin' })
|
|
128
|
+
.then((res) => res.text())
|
|
129
|
+
.then((html) => {
|
|
130
|
+
const doc = new DOMParser().parseFromString(html, 'text/html');
|
|
131
|
+
const freshForms = this.getCartItemForms(doc);
|
|
132
|
+
const currentForms = this.getCartItemForms();
|
|
133
|
+
if (!freshForms.length || !currentForms.length)
|
|
134
|
+
return;
|
|
135
|
+
const firstCurrent = currentForms[0];
|
|
136
|
+
const parent = firstCurrent.parentElement;
|
|
137
|
+
if (!parent)
|
|
138
|
+
return;
|
|
139
|
+
// Insert the fresh rows in place of the current ones, then drop the old rows.
|
|
140
|
+
freshForms.forEach((form) => {
|
|
141
|
+
parent.insertBefore(document.importNode(form, true), firstCurrent);
|
|
142
|
+
});
|
|
143
|
+
currentForms.forEach((form) => form.remove());
|
|
144
|
+
document.lazyLoadInstance?.update?.();
|
|
145
|
+
this.positionUnderCartItems();
|
|
146
|
+
})
|
|
147
|
+
.catch(() => { })
|
|
148
|
+
.finally(() => { this.isSyncingCart = false; });
|
|
149
|
+
}
|
|
150
|
+
connectedCallback() {
|
|
151
|
+
salla.event.on('cart::item.added', this.cartItemChangedHandler);
|
|
152
|
+
salla.event.on('cart::item.deleted', this.cartItemChangedHandler);
|
|
153
|
+
// Tag adds originating from a basket-gap recommendation so the cart auto-track
|
|
154
|
+
// is suppressed in favour of our attributed `salla-basket-gap::product.added`.
|
|
155
|
+
salla.event.on('cart::before.add.item', this.beforeAddItemHandler);
|
|
156
|
+
this.host.addEventListener('success', this.addButtonSuccessHandler);
|
|
157
|
+
}
|
|
158
|
+
disconnectedCallback() {
|
|
159
|
+
salla.event.off('cart::item.added', this.cartItemChangedHandler);
|
|
160
|
+
salla.event.off('cart::item.deleted', this.cartItemChangedHandler);
|
|
161
|
+
salla.event.off('cart::before.add.item', this.beforeAddItemHandler);
|
|
162
|
+
this.host.removeEventListener('success', this.addButtonSuccessHandler);
|
|
163
|
+
}
|
|
164
|
+
// The recommendation API receives at most 5 cart product IDs, so it can return
|
|
165
|
+
// products that are already in the cart (those beyond the 5-item payload limit).
|
|
166
|
+
// We filter them out here to avoid showing items the customer already has.
|
|
167
|
+
// cartProductIds may be passed in directly from a live event payload; otherwise
|
|
168
|
+
// we fall back to storage (which can lag behind on the initial load path).
|
|
169
|
+
getCartProductIds(knownIds) {
|
|
170
|
+
if (knownIds?.length)
|
|
171
|
+
return new Set(knownIds);
|
|
172
|
+
const cart = salla.storage.get('cart');
|
|
173
|
+
return new Set((cart?.items ?? []).map((i) => String(i.product_id)).filter(Boolean));
|
|
174
|
+
}
|
|
175
|
+
fetchRecommendations(objectIDs) {
|
|
176
|
+
if (!objectIDs.length) {
|
|
177
|
+
this.canRender = false;
|
|
178
|
+
this.isLoading = false;
|
|
179
|
+
return Promise.resolve();
|
|
180
|
+
}
|
|
181
|
+
const generation = ++this.fetchGeneration;
|
|
182
|
+
return fetchCartBoughtTogether(objectIDs)
|
|
183
|
+
.then((ids) => {
|
|
184
|
+
if (generation !== this.fetchGeneration)
|
|
185
|
+
return;
|
|
186
|
+
// Pass objectIDs as the authoritative cart list so the filter is not
|
|
187
|
+
// affected by stale storage when called from a live cart event.
|
|
188
|
+
const cartIds = this.getCartProductIds(objectIDs);
|
|
189
|
+
const filteredIds = ids.filter(id => !cartIds.has(id));
|
|
190
|
+
if (!filteredIds.length) {
|
|
191
|
+
this.canRender = false;
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
return this.fetchProducts(filteredIds.slice(0, this.limit), generation);
|
|
195
|
+
})
|
|
196
|
+
.catch(() => {
|
|
197
|
+
if (generation !== this.fetchGeneration)
|
|
198
|
+
return;
|
|
199
|
+
this.canRender = false;
|
|
200
|
+
})
|
|
201
|
+
.finally(() => {
|
|
202
|
+
if (generation !== this.fetchGeneration)
|
|
203
|
+
return;
|
|
204
|
+
this.isLoading = false;
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
fetchProducts(ids, generation) {
|
|
208
|
+
return salla.api.withoutNotifier(() => salla.product.api.fetch({
|
|
209
|
+
source: 'selected',
|
|
210
|
+
source_value: ids,
|
|
211
|
+
limit: this.limit,
|
|
212
|
+
})).then((response) => {
|
|
213
|
+
if (generation !== this.fetchGeneration)
|
|
214
|
+
return;
|
|
215
|
+
this.products = response?.data ?? [];
|
|
216
|
+
this.canRender = this.products.length > 0;
|
|
217
|
+
}).catch(() => {
|
|
218
|
+
if (generation !== this.fetchGeneration)
|
|
219
|
+
return;
|
|
220
|
+
this.canRender = false;
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
getDiscountLabel(product) {
|
|
224
|
+
if (product.promotion_title)
|
|
225
|
+
return product.promotion_title;
|
|
226
|
+
if (product.is_on_sale && product.regular_price > 0 && product.sale_price > 0) {
|
|
227
|
+
const percent = Math.round((1 - product.sale_price / product.regular_price) * 100);
|
|
228
|
+
return percent > 0 ? `${this.discountLabel} ${percent}%` : null;
|
|
229
|
+
}
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
formatDate(timestamp) {
|
|
233
|
+
const d = new Date(timestamp * 1000);
|
|
234
|
+
const mm = String(d.getMonth() + 1).padStart(2, '0');
|
|
235
|
+
const dd = String(d.getDate()).padStart(2, '0');
|
|
236
|
+
return `${d.getFullYear()}-${mm}-${dd}`;
|
|
237
|
+
}
|
|
238
|
+
getSkeletonView() {
|
|
239
|
+
return (h(Host, { class: "s-basket-gap-entry" }, h("div", { class: "s-basket-gap-skeleton" }, h("salla-skeleton", { height: "16px", width: "40%", style: { marginBottom: '16px' } }), Array(3).fill(null).map((_, i) => (h("div", { key: i, class: "s-basket-gap-skeleton-card" }, h("salla-skeleton", { height: "64px", width: "64px", style: { borderRadius: '8px', flexShrink: '0' } }), h("div", { class: "s-basket-gap-skeleton-info" }, h("salla-skeleton", { height: "14px", width: "50%" }), h("salla-skeleton", { height: "12px", width: "25%", style: { marginTop: '6px' } }), h("salla-skeleton", { height: "10px", width: "35%", style: { marginTop: '4px' } })), h("salla-skeleton", { height: "36px", width: "100px", style: { borderRadius: '6px', flexShrink: '0', marginInlineStart: 'auto' } })))))));
|
|
240
|
+
}
|
|
241
|
+
getProductCard(product) {
|
|
242
|
+
const discountLabel = this.getDiscountLabel(product);
|
|
243
|
+
return (h("div", { key: product.id, class: "s-basket-gap-card" }, h("a", { href: product.url, class: "s-basket-gap-card-image" }, h("img", { class: "lazy", src: this.placeholder, "data-src": product.image?.url, alt: product.image?.alt || product.name })), h("div", { class: "s-basket-gap-card-info" }, h("h3", { class: "s-basket-gap-card-name" }, h("a", { href: product.url }, product.name)), product.is_on_sale
|
|
244
|
+
? h("div", { class: "s-basket-gap-card-sale-price" }, h("span", { innerHTML: salla.money(product.sale_price) }), h("del", { innerHTML: salla.money(product.regular_price) }))
|
|
245
|
+
: h("span", { class: "s-basket-gap-card-price", innerHTML: salla.money(product.price) }), product.weight_label && (h("span", { class: "s-basket-gap-card-weight" }, this.weightLabel, " ", product.weight_label))), (product.promotion_title || product.discount_ends || product.is_on_sale) && (h("div", { class: "s-basket-gap-card-offer" }, h("i", { class: "sicon-gift" }), discountLabel && h("span", null, discountLabel), product.discount_ends && [
|
|
246
|
+
h("salla-count-down", { date: this.formatDate(product.discount_ends), "end-of-day": true, digits: "en" }),
|
|
247
|
+
h("i", { class: "sicon-alarm" }),
|
|
248
|
+
])), h("salla-add-product-button", { class: "s-basket-gap-card-btn", "product-id": product.id, "product-status": product.status, "product-type": product.type }, this.addToCartLabel)));
|
|
249
|
+
}
|
|
250
|
+
render() {
|
|
251
|
+
if (!this.canRender)
|
|
252
|
+
return null;
|
|
253
|
+
if (this.isLoading)
|
|
254
|
+
return this.getSkeletonView();
|
|
255
|
+
if (!this.products.length)
|
|
256
|
+
return null;
|
|
257
|
+
return (h(Host, { class: "s-basket-gap-entry" }, this.title && h("h2", { class: "s-basket-gap-title" }, this.title), h("div", { class: "s-basket-gap-list" }, this.products.map(product => this.getProductCard(product)))));
|
|
258
|
+
}
|
|
259
|
+
static get is() { return "salla-basket-gap"; }
|
|
260
|
+
static get originalStyleUrls() {
|
|
261
|
+
return {
|
|
262
|
+
"$": ["salla-basket-gap.scss"]
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
static get styleUrls() {
|
|
266
|
+
return {
|
|
267
|
+
"$": ["salla-basket-gap.css"]
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
static get properties() {
|
|
271
|
+
return {
|
|
272
|
+
"limit": {
|
|
273
|
+
"type": "number",
|
|
274
|
+
"attribute": "limit",
|
|
275
|
+
"mutable": false,
|
|
276
|
+
"complexType": {
|
|
277
|
+
"original": "number",
|
|
278
|
+
"resolved": "number",
|
|
279
|
+
"references": {}
|
|
280
|
+
},
|
|
281
|
+
"required": false,
|
|
282
|
+
"optional": false,
|
|
283
|
+
"docs": {
|
|
284
|
+
"tags": [],
|
|
285
|
+
"text": "Maximum number of recommendations to fetch."
|
|
286
|
+
},
|
|
287
|
+
"getter": false,
|
|
288
|
+
"setter": false,
|
|
289
|
+
"reflect": false,
|
|
290
|
+
"defaultValue": "10"
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
static get states() {
|
|
295
|
+
return {
|
|
296
|
+
"products": {},
|
|
297
|
+
"isLoading": {},
|
|
298
|
+
"canRender": {},
|
|
299
|
+
"title": {},
|
|
300
|
+
"addToCartLabel": {},
|
|
301
|
+
"weightLabel": {},
|
|
302
|
+
"discountLabel": {}
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
static get elementRef() { return "host"; }
|
|
306
|
+
}
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
* Crafted with ❤ by Salla
|
|
3
3
|
*/
|
|
4
4
|
import { Host, h } from "@stencil/core";
|
|
5
|
-
|
|
6
|
-
const XSELL_API_KEY = 'VOL5WaZu2YROp0RplCZAr1RplhL9FFGQ';
|
|
5
|
+
import { fetchProductCustomersAlsoBought } from "../../shared/catalog-recommendations";
|
|
7
6
|
export class SallaBoughtTogether {
|
|
8
7
|
constructor() {
|
|
9
8
|
/**
|
|
@@ -39,25 +38,14 @@ export class SallaBoughtTogether {
|
|
|
39
38
|
return;
|
|
40
39
|
}
|
|
41
40
|
this.resolvedProductId = id;
|
|
42
|
-
return
|
|
43
|
-
requests: [{
|
|
44
|
-
indexName: 'products',
|
|
45
|
-
model: 'xsell-v1',
|
|
46
|
-
priceThreshold: 2,
|
|
47
|
-
objectID: String(id),
|
|
48
|
-
maxRecommendations: this.limit,
|
|
49
|
-
}]
|
|
50
|
-
}, 'post', { headers: { 'X-Algolia-Api-Key': XSELL_API_KEY, 'X-Query-Enrichment': 'false', 'X-source': 'store' } });
|
|
41
|
+
return fetchProductCustomersAlsoBought(String(id));
|
|
51
42
|
})
|
|
52
|
-
.then((
|
|
53
|
-
if (!
|
|
54
|
-
return;
|
|
55
|
-
const hits = response?.results?.[0]?.hits ?? [];
|
|
56
|
-
if (!hits.length) {
|
|
43
|
+
.then((recommendedIds) => {
|
|
44
|
+
if (!recommendedIds?.length) {
|
|
57
45
|
this.canRender = false;
|
|
58
46
|
return;
|
|
59
47
|
}
|
|
60
|
-
const ids = [String(this.resolvedProductId), ...
|
|
48
|
+
const ids = [String(this.resolvedProductId), ...recommendedIds.slice(0, this.limit)];
|
|
61
49
|
return salla.product.fetch({ source: 'selected', source_value: ids });
|
|
62
50
|
})
|
|
63
51
|
.then((response) => {
|
|
@@ -125,7 +125,8 @@ export class SallaCountDown {
|
|
|
125
125
|
return !isNaN(Date.parse(testedDate));
|
|
126
126
|
}
|
|
127
127
|
number(digit) {
|
|
128
|
-
|
|
128
|
+
const value = String(Math.max(0, Math.floor(digit))).padStart(2, '0');
|
|
129
|
+
return salla.helpers.number(value, this.digits === 'en');
|
|
129
130
|
}
|
|
130
131
|
startCountDown() {
|
|
131
132
|
const normalized = this.normalizeDate(this.date);
|
|
@@ -228,7 +229,7 @@ export class SallaCountDown {
|
|
|
228
229
|
return this.renderCountDown();
|
|
229
230
|
}
|
|
230
231
|
render() {
|
|
231
|
-
return (h(Host, { key: '
|
|
232
|
+
return (h(Host, { key: 'e2805e528a52b71ad71f4f1f16a473947dafb5bc', class: `s-count-down-wrapper ${this.preOrder && this.isValidDate(this.date) ? 's-count-down-pre-order' : ''} ${this.horizontal ? 's-count-down-horizontal' : ''} ${this.withButton ? 's-count-down-with-button' : ''} ${this.offerEnded ? 's-count-down-ended' : ''}` }, this.renderPrefixText(), this.renderContent(), this.offerEnded && this.renderOfferEnded(), this.renderButton()));
|
|
232
233
|
}
|
|
233
234
|
static get is() { return "salla-count-down"; }
|
|
234
235
|
static get originalStyleUrls() {
|
|
@@ -125,8 +125,15 @@ export class SallaQuickBuy {
|
|
|
125
125
|
currency: this.currency || 'SAR', // SAR
|
|
126
126
|
requiredShippingContactFields: this.getRequiredShippingContactFields(),
|
|
127
127
|
shippingMethods: this.isRequireShipping ? [] : undefined,
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
// Legacy BE
|
|
129
|
+
supportedNetworks: this.isLegacyBuyNowBE()
|
|
130
|
+
? salla.config.get('store.settings.buy_now.networks')
|
|
131
|
+
: ((Array.isArray(this.supportedNetworks) && this.supportedNetworks.length)
|
|
132
|
+
? this.supportedNetworks : salla.config.get('store.settings.buy_now.supportedNetworks')),
|
|
133
|
+
supportedCountries: this.isLegacyBuyNowBE()
|
|
134
|
+
? salla.config.get('store.settings.buy_now.countries')
|
|
135
|
+
: ((Array.isArray(this.supportedCountries) && this.supportedCountries.length)
|
|
136
|
+
? this.supportedCountries : salla.config.get('store.settings.buy_now.supportedCountries')),
|
|
130
137
|
countryCode: salla.config.get('store.store_country') || 'SA',
|
|
131
138
|
onStartedSession: this.handleApplePaySessionStarted,
|
|
132
139
|
validateMerchant: {
|
|
@@ -203,6 +210,35 @@ export class SallaQuickBuy {
|
|
|
203
210
|
}
|
|
204
211
|
return fields;
|
|
205
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* TEMPORARY for BE Vip sync
|
|
215
|
+
*/
|
|
216
|
+
isLegacyBuyNowBE() {
|
|
217
|
+
return salla?.config?.get?.('store.settings.buy_now.networks') != null;
|
|
218
|
+
}
|
|
219
|
+
/** Set Apple Pay amount + currency from a price payload, always keeping the pair in one currency. */
|
|
220
|
+
applyBaseCurrencyPrice(data) {
|
|
221
|
+
// Legacy BE: amount only; currency is set once in runInit.
|
|
222
|
+
if (this.isLegacyBuyNowBE()) {
|
|
223
|
+
if (data?.price != null) {
|
|
224
|
+
this.amount = data.price;
|
|
225
|
+
}
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const base = data?.base_currency_price;
|
|
229
|
+
// Unified BE base pair (regular products): charge in base currency.
|
|
230
|
+
if (base?.amount != null) {
|
|
231
|
+
this.amount = base.amount;
|
|
232
|
+
if (base?.currency) {
|
|
233
|
+
this.currency = base.currency;
|
|
234
|
+
}
|
|
235
|
+
// Display-only payload (e.g. donation { id, price }): pair amount with its display currency.
|
|
236
|
+
}
|
|
237
|
+
else if (data?.price != null) {
|
|
238
|
+
this.amount = data.price;
|
|
239
|
+
this.currency = salla.config.get('user.currency_code') || this.currency || 'SAR';
|
|
240
|
+
}
|
|
241
|
+
}
|
|
206
242
|
componentWillLoad() {
|
|
207
243
|
console.log('🍏 Pay: Quick Buy Component Loaded');
|
|
208
244
|
const canMakePayments = typeof window !== 'undefined' && !!window.ApplePaySession?.canMakePayments?.();
|
|
@@ -210,7 +246,9 @@ export class SallaQuickBuy {
|
|
|
210
246
|
const isSallaGateway = salla?.config?.get?.('store.settings.is_salla_gateway', false) ?? true;
|
|
211
247
|
this.isApplePayActive = canMakePayments && storeHasApplePay && isSallaGateway;
|
|
212
248
|
const runInit = async () => {
|
|
213
|
-
if (!this.currency && salla?.config?.get) {
|
|
249
|
+
if (this.isLegacyBuyNowBE() && !this.currency && salla?.config?.get) {
|
|
250
|
+
// Legacy BE (pre-PR): currency from the multi_currency flag. The unified BE instead
|
|
251
|
+
// sources amount + currency from `base_currency_price` (see applyBaseCurrencyPrice).
|
|
214
252
|
this.currency = salla.config.get('store.settings.buy_now.multi_currency') ? salla.config.get('user.currency_code') : 'SAR';
|
|
215
253
|
}
|
|
216
254
|
if (!this.productId && salla?.config?.get && salla.url?.is_page) {
|
|
@@ -222,7 +260,7 @@ export class SallaQuickBuy {
|
|
|
222
260
|
}
|
|
223
261
|
if ((!this.amount || !this.isRequireShipping) && this.productId && salla?.product?.getDetails) {
|
|
224
262
|
await salla.product.getDetails(this.productId, []).then((response) => {
|
|
225
|
-
this.
|
|
263
|
+
this.applyBaseCurrencyPrice(response?.data);
|
|
226
264
|
this.isRequireShipping = response?.data?.is_require_shipping || false;
|
|
227
265
|
}).catch((error) => {
|
|
228
266
|
salla?.logger?.warn?.('🍏 Pay: Failed load the quick buy, get the product details failed: ', error);
|
|
@@ -232,11 +270,11 @@ export class SallaQuickBuy {
|
|
|
232
270
|
salla.event.on('product-options::donation-changed', (data) => {
|
|
233
271
|
if (String(data.id) !== String(this.productId))
|
|
234
272
|
return;
|
|
235
|
-
this.
|
|
273
|
+
this.applyBaseCurrencyPrice(data);
|
|
236
274
|
});
|
|
237
275
|
}
|
|
238
276
|
else if (salla?.url?.is_page?.('product.single') && salla?.product?.event?.onPriceUpdated) {
|
|
239
|
-
salla.product.event.onPriceUpdated(response => { this.
|
|
277
|
+
salla.product.event.onPriceUpdated(response => { this.applyBaseCurrencyPrice(response?.data); });
|
|
240
278
|
}
|
|
241
279
|
this.isApplePayActive = (salla?.helpers?.hasApplePay?.() ?? canMakePayments)
|
|
242
280
|
&& (salla?.config?.get?.('store.settings.payments')?.includes?.('apple_pay') ?? storeHasApplePay)
|
|
@@ -259,7 +297,7 @@ export class SallaQuickBuy {
|
|
|
259
297
|
});
|
|
260
298
|
}
|
|
261
299
|
render() {
|
|
262
|
-
return h(Host, { key: '
|
|
300
|
+
return h(Host, { key: '8df291680d9b59f1627c8e1185a01cb30b92c2e4' }, this.quickBuyButton());
|
|
263
301
|
}
|
|
264
302
|
quickBuyButton() {
|
|
265
303
|
return h("apple-pay-button", { locale: salla?.config?.get?.('user.language_code') || 'ar', onClick: () => this.quickBuyHandler(), "data-quick-purchase": "applepay", class: "s-quick-buy-apple-pay", "data-is-applepay": "1", buttonstyle: "black", type: this.type });
|
|
@@ -514,6 +552,48 @@ export class SallaQuickBuy {
|
|
|
514
552
|
"getter": false,
|
|
515
553
|
"setter": false,
|
|
516
554
|
"reflect": false
|
|
555
|
+
},
|
|
556
|
+
"supportedNetworks": {
|
|
557
|
+
"type": "unknown",
|
|
558
|
+
"attribute": "supported-networks",
|
|
559
|
+
"mutable": true,
|
|
560
|
+
"complexType": {
|
|
561
|
+
"original": "string[]",
|
|
562
|
+
"resolved": "string[]",
|
|
563
|
+
"references": {}
|
|
564
|
+
},
|
|
565
|
+
"required": false,
|
|
566
|
+
"optional": false,
|
|
567
|
+
"docs": {
|
|
568
|
+
"tags": [{
|
|
569
|
+
"name": "type",
|
|
570
|
+
"text": "{string[]}"
|
|
571
|
+
}],
|
|
572
|
+
"text": "Apple Pay supported card networks. Optional array override for surfaces that already hold the\nunified backend value (e.g. mini-checkout property-binds `payments.gateways.applePay.supportedNetworks`).\nWhen unset/empty, falls back to the PDP `store.settings.buy_now.supportedNetworks` config."
|
|
573
|
+
},
|
|
574
|
+
"getter": false,
|
|
575
|
+
"setter": false
|
|
576
|
+
},
|
|
577
|
+
"supportedCountries": {
|
|
578
|
+
"type": "unknown",
|
|
579
|
+
"attribute": "supported-countries",
|
|
580
|
+
"mutable": true,
|
|
581
|
+
"complexType": {
|
|
582
|
+
"original": "string[]",
|
|
583
|
+
"resolved": "string[]",
|
|
584
|
+
"references": {}
|
|
585
|
+
},
|
|
586
|
+
"required": false,
|
|
587
|
+
"optional": false,
|
|
588
|
+
"docs": {
|
|
589
|
+
"tags": [{
|
|
590
|
+
"name": "type",
|
|
591
|
+
"text": "{string[]}"
|
|
592
|
+
}],
|
|
593
|
+
"text": "Apple Pay supported countries. Same array override/fallback semantics as `supportedNetworks`."
|
|
594
|
+
},
|
|
595
|
+
"getter": false,
|
|
596
|
+
"setter": false
|
|
517
597
|
}
|
|
518
598
|
};
|
|
519
599
|
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Crafted with ❤ by Salla
|
|
3
|
+
*/
|
|
4
|
+
const RECOMMENDATIONS_BASE_PATH = '/recommendations/v1';
|
|
5
|
+
const CART_BOUGHT_TOGETHER_MAX_PRODUCT_IDS = 5;
|
|
6
|
+
const CATALOG_RECOMMENDATIONS_API = 'https://api.salla.dev';
|
|
7
|
+
function getRecommendationsBaseUrl() {
|
|
8
|
+
const storeApi = String(salla.config.get('store.api', '') || '').replace(/\/$/, '');
|
|
9
|
+
if (storeApi.includes('api.salla.dev')) {
|
|
10
|
+
return storeApi;
|
|
11
|
+
}
|
|
12
|
+
// Recommendations proxy is on the global catalog API host (prod-only for now),
|
|
13
|
+
// not on beta preview /api/v1 paths that store.api may point to.
|
|
14
|
+
return CATALOG_RECOMMENDATIONS_API;
|
|
15
|
+
}
|
|
16
|
+
function getRecommendationsUrl(path) {
|
|
17
|
+
return `${getRecommendationsBaseUrl()}${RECOMMENDATIONS_BASE_PATH}${path}`;
|
|
18
|
+
}
|
|
19
|
+
function parseHostname(value) {
|
|
20
|
+
if (!value) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const normalized = value.startsWith('http') ? value : `https://${value}`;
|
|
25
|
+
return new URL(normalized).hostname || null;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
const hostname = String(value).replace(/^https?:\/\//i, '').split('/')[0];
|
|
29
|
+
return hostname || null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function getStoreOriginHostname() {
|
|
33
|
+
const trackUrl = salla.config.get('jitsu.track_url');
|
|
34
|
+
const trackHostname = trackUrl ? parseHostname(String(trackUrl)) : null;
|
|
35
|
+
if (trackHostname) {
|
|
36
|
+
return trackHostname;
|
|
37
|
+
}
|
|
38
|
+
for (const candidate of [salla.config.get('store.domain'), salla.config.get('store.url')]) {
|
|
39
|
+
const hostname = candidate ? parseHostname(String(candidate)) : null;
|
|
40
|
+
if (hostname && !hostname.includes('beta.salla.group')) {
|
|
41
|
+
return hostname;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return window.location.hostname;
|
|
45
|
+
}
|
|
46
|
+
function getRecommendationsRequestConfig(params) {
|
|
47
|
+
const headers = {
|
|
48
|
+
's-store-id': String(salla.config.get('store.id')),
|
|
49
|
+
origin: getStoreOriginHostname(),
|
|
50
|
+
's-source': 'store',
|
|
51
|
+
lang: salla.lang.getLocale(),
|
|
52
|
+
};
|
|
53
|
+
const scopeId = salla.api.getHeader('s-scope-id');
|
|
54
|
+
if (scopeId) {
|
|
55
|
+
headers['s-scope-id'] = String(scopeId);
|
|
56
|
+
}
|
|
57
|
+
return { params, headers };
|
|
58
|
+
}
|
|
59
|
+
function extractRecommendationIds(response) {
|
|
60
|
+
return (response?.data ?? [])
|
|
61
|
+
.map(item => item?.id)
|
|
62
|
+
.filter((id) => Boolean(id));
|
|
63
|
+
}
|
|
64
|
+
function fetchRecommendations(path, params) {
|
|
65
|
+
const url = getRecommendationsUrl(path);
|
|
66
|
+
const config = getRecommendationsRequestConfig(params);
|
|
67
|
+
// Recommendations are a non-critical, best-effort feature; suppress the global
|
|
68
|
+
// API error notifier so transient failures stay invisible and the consuming
|
|
69
|
+
// component can silently hide its section via its own .catch().
|
|
70
|
+
return salla.api.withoutNotifier(() => salla.api.request(url, config, 'get'))
|
|
71
|
+
.then((response) => extractRecommendationIds(response));
|
|
72
|
+
}
|
|
73
|
+
export function fetchCartBoughtTogether(productIds) {
|
|
74
|
+
const ids = productIds.slice(0, CART_BOUGHT_TOGETHER_MAX_PRODUCT_IDS);
|
|
75
|
+
if (!ids.length) {
|
|
76
|
+
return Promise.resolve([]);
|
|
77
|
+
}
|
|
78
|
+
return fetchRecommendations('/carts/bought-together', {
|
|
79
|
+
product_ids: ids.join(','),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
export function fetchProductCustomersAlsoBought(productId) {
|
|
83
|
+
if (!productId) {
|
|
84
|
+
return Promise.resolve([]);
|
|
85
|
+
}
|
|
86
|
+
return fetchRecommendations('/products/customers-also-bought', {
|
|
87
|
+
product_id: productId,
|
|
88
|
+
});
|
|
89
|
+
}
|