@salla.sa/twilight-components 2.14.352 → 2.14.354
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/bell-ring-BfKPinNo.js +13 -0
- package/dist/cjs/{interfaces-CX9-6aLf.js → camera-DytepEoK.js} +0 -11
- package/dist/cjs/cancel-De6vslRA.js +13 -0
- package/dist/cjs/cart-s-x1Fshk.js +13 -0
- package/dist/cjs/check-circle2-BDvlT4_n.js +13 -0
- package/dist/cjs/{check-CLRvuniI.js → check-x3w3-gpj.js} +2 -2
- package/dist/cjs/{filepond-XtsZ6xtH.js → filepond-CuKErtOy.js} +1 -1
- package/dist/cjs/{filepond-plugin-file-poster-Bj84Ypvg.js → filepond-plugin-file-poster-d-8BSuST.js} +1 -1
- package/dist/cjs/{filepond-plugin-file-validate-size-aYfb4yYH.js → filepond-plugin-file-validate-size-zgI_JcqY.js} +1 -1
- package/dist/cjs/{filepond-plugin-file-validate-type-CJsd6rXl.js → filepond-plugin-file-validate-type-Cy8IgG2P.js} +1 -1
- package/dist/cjs/{filepond-plugin-image-edit-DRlBSg36.js → filepond-plugin-image-edit-9ZAUzCvh.js} +1 -1
- package/dist/cjs/{filepond-plugin-image-exif-orientation-SY8c6DzI.js → filepond-plugin-image-exif-orientation-DzNe_tY2.js} +1 -1
- package/dist/cjs/{filepond-plugin-image-preview-iqhJmUmU.js → filepond-plugin-image-preview-Cfna6xTB.js} +1 -1
- package/dist/{esm/gift-C0JNGIpa.js → cjs/gift-CJ-3Yw_x.js} +4 -2
- package/dist/cjs/image-BoZ6Hums.js +13 -0
- package/dist/cjs/{index-Z-cyrNSM.js → index-Ce40E8tZ.js} +136 -12
- package/dist/cjs/{index-C7-280f4.js → index-ff-xJfhj.js} +1 -1
- package/dist/cjs/interfaces-CRqrf5RX.js +15 -0
- package/dist/cjs/keyboard_arrow_down-DHJ3FFZq.js +13 -0
- package/dist/cjs/keyboard_arrow_right-BayM_Il2.js +21 -0
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/minus-CCryh1qf.js +21 -0
- package/dist/cjs/salla-accordion-body_3.cjs.entry.js +775 -0
- package/dist/cjs/salla-accordion_6.cjs.entry.js +768 -0
- package/dist/cjs/salla-add-product-button_4.cjs.entry.js +2389 -0
- package/dist/cjs/salla-advertisement.cjs.entry.js +1 -1
- package/dist/cjs/salla-alert_2.cjs.entry.js +194 -0
- package/dist/cjs/salla-app-install-alert.cjs.entry.js +8 -3
- package/dist/cjs/salla-apps-icons.cjs.entry.js +1 -1
- package/dist/cjs/salla-booking-field_7.cjs.entry.js +1565 -0
- package/dist/cjs/{salla-cart-item-offers.cjs.entry.js → salla-cart-item-offers_2.cjs.entry.js} +104 -5
- package/dist/cjs/salla-comment-form_8.cjs.entry.js +1661 -0
- package/dist/cjs/salla-conditional-offer.cjs.entry.js +1 -1
- package/dist/cjs/salla-contacts.cjs.entry.js +3 -3
- package/dist/cjs/salla-count-down_2.cjs.entry.js +302 -0
- package/dist/cjs/salla-custom-fields.cjs.entry.js +4 -3
- 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-gifting.cjs.entry.js +488 -0
- package/dist/cjs/salla-hook.cjs.entry.js +1 -1
- package/dist/cjs/salla-infinite-scroll.cjs.entry.js +91 -0
- package/dist/cjs/salla-installment.cjs.entry.js +1 -1
- package/dist/cjs/salla-list-tile.cjs.entry.js +34 -0
- package/dist/cjs/salla-localization-modal.cjs.entry.js +137 -0
- package/dist/cjs/salla-login-modal.cjs.entry.js +320 -0
- 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.cjs.entry.js +211 -0
- package/dist/cjs/salla-maintenance-alert.cjs.entry.js +40 -0
- package/dist/cjs/salla-menu.cjs.entry.js +139 -0
- package/dist/cjs/salla-metadata.cjs.entry.js +1 -1
- package/dist/cjs/salla-multiple-bundle-product-cart_2.cjs.entry.js +220 -0
- package/dist/cjs/salla-multiple-bundle-product-options-modal_2.cjs.entry.js +598 -0
- package/dist/cjs/salla-multiple-bundle-product.cjs.entry.js +69 -0
- 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 +206 -0
- package/dist/cjs/salla-offer.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-summary.cjs.entry.js +3 -3
- 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 +51 -0
- package/dist/cjs/salla-price-range.cjs.entry.js +1 -1
- package/dist/cjs/salla-product-size-guide.cjs.entry.js +66 -0
- package/dist/cjs/salla-products-list.cjs.entry.js +762 -0
- package/dist/cjs/salla-products-slider.cjs.entry.js +115 -0
- package/dist/cjs/salla-progress-bar.cjs.entry.js +73 -0
- package/dist/cjs/salla-quick-order.cjs.entry.js +239 -0
- package/dist/cjs/salla-rating-modal.cjs.entry.js +453 -0
- package/dist/cjs/salla-scopes.cjs.entry.js +180 -0
- package/dist/cjs/salla-search.cjs.entry.js +153 -0
- package/dist/cjs/salla-skeleton.cjs.entry.js +36 -0
- package/dist/cjs/salla-slider.cjs.entry.js +10389 -0
- package/dist/cjs/salla-social-share.cjs.entry.js +165 -0
- package/dist/cjs/salla-social.cjs.entry.js +3 -3
- package/dist/cjs/salla-tab-content_3.cjs.entry.js +157 -0
- 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 +275 -0
- package/dist/cjs/salla-user-profile.cjs.entry.js +145 -0
- package/dist/cjs/salla-user-settings.cjs.entry.js +88 -0
- package/dist/cjs/salla-verify.cjs.entry.js +1 -1
- package/dist/cjs/salla-wallet.cjs.entry.js +1 -1
- package/dist/cjs/search-c7Aa7lM9.js +13 -0
- package/dist/cjs/{special-discount-OVG_9Kf9.js → special-discount-DC2oXurL.js} +0 -8
- package/dist/cjs/star-DGcH7Yso.js +13 -0
- package/dist/cjs/star2-R146a27p.js +13 -0
- package/dist/cjs/twilight.cjs.js +2 -2
- package/dist/cjs/{vanilla-picker-Dq7F5bE1.js → vanilla-picker-zQsXQIff.js} +1 -1
- package/dist/cjs/{whatsapp2-D7Sbg8Ey.js → whatsapp2-BdMd5Gx1.js} +2 -2
- package/dist/collection/collection-manifest.json +55 -1
- package/dist/collection/components/salla-add-product-button/salla-add-product-button.js +18 -6
- package/dist/collection/components/salla-app-install-alert/salla-app-install-alert.js +7 -2
- package/dist/collection/components/salla-color-picker/salla-color-picker.js +39 -8
- package/dist/collection/components/salla-maintenance-alert/salla-maintenance-alert.js +4 -2
- package/dist/collection/components/salla-product-options/salla-product-options.js +36 -3
- package/dist/collection/components/salla-products-list/salla-products-list.js +17 -11
- package/dist/components/index.js +2 -2
- package/dist/components/salla-add-product-button2.js +18 -6
- package/dist/components/salla-app-install-alert.js +7 -2
- package/dist/components/salla-color-picker2.js +38 -7
- package/dist/components/salla-maintenance-alert.js +4 -2
- package/dist/components/salla-product-options2.js +19 -2
- package/dist/components/salla-products-list2.js +17 -11
- package/dist/esm/bell-ring-D3mWkc-3.js +11 -0
- package/dist/esm/{interfaces-CBT_Nxny.js → camera-C6jIkM-X.js} +1 -12
- package/dist/esm/cancel-BsLF_HK7.js +11 -0
- package/dist/esm/cart-DY4LZmNP.js +11 -0
- package/dist/esm/{check-uTyAzPSy.js → check-BsXh13x8.js} +2 -2
- package/dist/esm/check-circle2-BV4kqbdL.js +11 -0
- package/dist/esm/{filepond-Dg4ZKM-u.js → filepond-DEzyRrdH.js} +1 -1
- package/dist/esm/{filepond-plugin-file-poster-BUIjdsnA.js → filepond-plugin-file-poster-DyLcCcHM.js} +1 -1
- package/dist/esm/{filepond-plugin-file-validate-size-DgZMMqmi.js → filepond-plugin-file-validate-size-Cxp5Yzea.js} +1 -1
- package/dist/esm/{filepond-plugin-file-validate-type-DA9tDSFr.js → filepond-plugin-file-validate-type-D2qNOQP4.js} +1 -1
- package/dist/esm/{filepond-plugin-image-edit-dotdnN4Z.js → filepond-plugin-image-edit-DndTlA7m.js} +1 -1
- package/dist/esm/{filepond-plugin-image-exif-orientation-oSI8aLU-.js → filepond-plugin-image-exif-orientation-CiT1CQoK.js} +1 -1
- package/dist/esm/{filepond-plugin-image-preview-DEefQK61.js → filepond-plugin-image-preview-DBG7keFZ.js} +1 -1
- package/dist/{cjs/gift-BPDUPIY_.js → esm/gift-BChI23pG.js} +2 -4
- package/dist/esm/image-C-tzSDxw.js +11 -0
- package/dist/esm/{index-D2-TtAhI.js → index-B74h9G6a.js} +137 -13
- package/dist/esm/{index-B7E8Tmgi.js → index-BLw7mdtM.js} +1 -1
- package/dist/esm/interfaces-OF8QcbMM.js +15 -0
- package/dist/esm/keyboard_arrow_down-DCZbpt2a.js +11 -0
- package/dist/esm/keyboard_arrow_right-Vqpj4CWE.js +18 -0
- package/dist/esm/loader.js +3 -3
- package/dist/esm/minus-DfeagqF1.js +18 -0
- package/dist/esm/salla-accordion-body_3.entry.js +771 -0
- package/dist/esm/salla-accordion_6.entry.js +761 -0
- package/dist/esm/salla-add-product-button_4.entry.js +2384 -0
- package/dist/esm/salla-advertisement.entry.js +1 -1
- package/dist/esm/salla-alert_2.entry.js +191 -0
- package/dist/esm/salla-app-install-alert.entry.js +8 -3
- package/dist/esm/salla-apps-icons.entry.js +1 -1
- package/dist/esm/salla-booking-field_7.entry.js +1539 -0
- package/dist/esm/{salla-cart-item-offers.entry.js → salla-cart-item-offers_2.entry.js} +104 -6
- package/dist/esm/salla-comment-form_8.entry.js +1652 -0
- package/dist/esm/salla-conditional-offer.entry.js +1 -1
- package/dist/esm/salla-contacts.entry.js +3 -3
- package/dist/esm/salla-count-down_2.entry.js +299 -0
- package/dist/esm/salla-custom-fields.entry.js +3 -2
- package/dist/esm/salla-filters-widget.entry.js +1 -1
- package/dist/esm/salla-filters.entry.js +1 -1
- package/dist/esm/salla-gifting.entry.js +486 -0
- package/dist/esm/salla-hook.entry.js +1 -1
- package/dist/esm/salla-infinite-scroll.entry.js +89 -0
- package/dist/esm/salla-installment.entry.js +1 -1
- package/dist/esm/salla-list-tile.entry.js +32 -0
- package/dist/esm/salla-localization-modal.entry.js +135 -0
- package/dist/esm/salla-login-modal.entry.js +318 -0
- 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.entry.js +209 -0
- package/dist/esm/salla-maintenance-alert.entry.js +38 -0
- package/dist/esm/salla-menu.entry.js +137 -0
- package/dist/esm/salla-metadata.entry.js +1 -1
- package/dist/esm/salla-multiple-bundle-product-cart_2.entry.js +217 -0
- package/dist/esm/salla-multiple-bundle-product-options-modal_2.entry.js +595 -0
- package/dist/esm/salla-multiple-bundle-product.entry.js +67 -0
- 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 +204 -0
- package/dist/esm/salla-offer.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-summary.entry.js +3 -3
- 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 +49 -0
- package/dist/esm/salla-price-range.entry.js +1 -1
- package/dist/esm/salla-product-size-guide.entry.js +64 -0
- package/dist/esm/salla-products-list.entry.js +760 -0
- package/dist/esm/salla-products-slider.entry.js +113 -0
- package/dist/esm/salla-progress-bar.entry.js +71 -0
- package/dist/esm/salla-quick-order.entry.js +237 -0
- package/dist/esm/salla-rating-modal.entry.js +451 -0
- package/dist/esm/salla-scopes.entry.js +178 -0
- package/dist/esm/salla-search.entry.js +151 -0
- package/dist/esm/salla-skeleton.entry.js +34 -0
- package/dist/esm/salla-slider.entry.js +10387 -0
- package/dist/esm/salla-social-share.entry.js +163 -0
- package/dist/esm/salla-social.entry.js +2 -2
- package/dist/esm/salla-tab-content_3.entry.js +153 -0
- 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 +273 -0
- package/dist/esm/salla-user-profile.entry.js +143 -0
- package/dist/esm/salla-user-settings.entry.js +86 -0
- package/dist/esm/salla-verify.entry.js +1 -1
- package/dist/esm/salla-wallet.entry.js +1 -1
- package/dist/esm/search-BscTeWDc.js +11 -0
- package/dist/esm/{special-discount-yRO-ZESF.js → special-discount-Ctkfc4K-.js} +1 -8
- package/dist/esm/star-ZT7ehBBk.js +11 -0
- package/dist/esm/star2-D4oPi1Ov.js +11 -0
- package/dist/esm/twilight.js +3 -3
- package/dist/esm/{vanilla-picker-DkUGzUrx.js → vanilla-picker-CtwkXTap.js} +1 -1
- package/dist/esm/{whatsapp2-DWksgowB.js → whatsapp2-CgR-T_ZS.js} +2 -2
- package/dist/twilight/{p-7b3ca138.entry.js → p-0134b4fd.entry.js} +1 -1
- package/dist/twilight/{p-0effc34b.entry.js → p-01daaaa6.entry.js} +1 -1
- package/dist/twilight/p-07da7390.entry.js +4 -0
- package/dist/twilight/{p-6ce3f119.entry.js → p-08badc32.entry.js} +1 -1
- package/dist/twilight/{p-4a594c06.entry.js → p-0aa5a12a.entry.js} +1 -1
- package/dist/twilight/{p-e73c28a8.entry.js → p-10dcd981.entry.js} +1 -1
- package/dist/twilight/{p-81df7a2e.entry.js → p-212a0710.entry.js} +1 -1
- package/dist/twilight/p-229275db.entry.js +4 -0
- package/dist/twilight/{p-fea62668.entry.js → p-232185ec.entry.js} +1 -1
- package/dist/twilight/{p-e5c01983.entry.js → p-2a927eac.entry.js} +1 -1
- package/dist/twilight/p-2d880232.entry.js +4 -0
- package/dist/twilight/p-2de9df64.entry.js +4 -0
- package/dist/twilight/p-309a0ba4.entry.js +4 -0
- package/dist/twilight/{p-6d886b96.entry.js → p-32732ca7.entry.js} +1 -1
- package/dist/twilight/{p-9d35196f.entry.js → p-32ca34ec.entry.js} +1 -1
- package/dist/twilight/{p-2aa0a4e2.entry.js → p-33093880.entry.js} +1 -1
- package/dist/twilight/p-3cffa4c9.entry.js +4 -0
- package/dist/twilight/p-3d0bb451.entry.js +4 -0
- package/dist/twilight/p-3e0d814c.entry.js +4 -0
- package/dist/twilight/p-4036d5dc.entry.js +4 -0
- package/dist/twilight/p-40fe4b01.entry.js +4 -0
- package/dist/twilight/p-47ac0ca5.entry.js +4 -0
- package/dist/twilight/{p-b9d0212c.entry.js → p-4cd9da44.entry.js} +1 -1
- package/dist/twilight/p-5c9281d3.entry.js +4 -0
- package/dist/twilight/p-5d044466.entry.js +4 -0
- package/dist/twilight/p-5d21334a.entry.js +4 -0
- package/dist/twilight/{p-e26cc25b.entry.js → p-654429df.entry.js} +1 -1
- package/dist/twilight/p-6b8453be.entry.js +4 -0
- package/dist/twilight/p-6be7bbb0.entry.js +4 -0
- package/dist/twilight/{p-67c327a8.entry.js → p-6c8f5c94.entry.js} +1 -1
- package/dist/twilight/{p-9b8f5399.entry.js → p-6fa02770.entry.js} +1 -1
- package/dist/twilight/p-7040ea33.entry.js +4 -0
- package/dist/twilight/p-8c189d76.entry.js +4 -0
- package/dist/twilight/p-8f1f052c.entry.js +4 -0
- package/dist/twilight/{p-6b0a03f6.entry.js → p-9051a540.entry.js} +1 -1
- package/dist/twilight/p-9f1c561f.entry.js +4 -0
- package/dist/twilight/{p-B0ba6Gec.js → p-B69XOH6h.js} +2 -2
- package/dist/twilight/{p-D2-TtAhI.js → p-B74h9G6a.js} +2 -2
- package/dist/twilight/{p-C0JNGIpa.js → p-BChI23pG.js} +1 -1
- package/dist/twilight/{p-DhcC83-2.js → p-BCxm-ISm.js} +1 -1
- package/dist/twilight/{p-Cmkcwiop.js → p-BPqZ249Z.js} +1 -1
- package/dist/twilight/p-BV4kqbdL.js +4 -0
- package/dist/twilight/p-BsLF_HK7.js +4 -0
- package/dist/twilight/{p-uTyAzPSy.js → p-BsXh13x8.js} +1 -1
- package/dist/twilight/p-BscTeWDc.js +4 -0
- package/dist/twilight/p-C-tzSDxw.js +4 -0
- package/dist/twilight/p-C6jIkM-X.js +4 -0
- package/dist/twilight/p-CO-PeZ27.js +4 -0
- package/dist/twilight/{p-DPqkW1aD.js → p-CQq81yb5.js} +2 -2
- package/dist/twilight/{p-DWksgowB.js → p-CgR-T_ZS.js} +1 -1
- package/dist/twilight/p-Ctkfc4K-.js +4 -0
- package/dist/twilight/p-D3mWkc-3.js +4 -0
- package/dist/twilight/p-D4oPi1Ov.js +4 -0
- package/dist/twilight/p-DCZbpt2a.js +4 -0
- package/dist/twilight/p-DY4LZmNP.js +4 -0
- package/dist/twilight/p-DfeagqF1.js +4 -0
- package/dist/twilight/{p-DJ557xys.js → p-DpsbV3x1.js} +1 -1
- package/dist/twilight/p-OF8QcbMM.js +4 -0
- package/dist/twilight/p-Vqpj4CWE.js +4 -0
- package/dist/twilight/p-ZT7ehBBk.js +4 -0
- package/dist/twilight/{p-q-O0srMP.js → p-_-aXm0Wb.js} +1 -1
- package/dist/twilight/p-a100bd38.entry.js +4 -0
- package/dist/twilight/{p-cf66ab4d.entry.js → p-a2756650.entry.js} +1 -1
- package/dist/twilight/{p-b1af2aca.entry.js → p-aab45a16.entry.js} +1 -1
- package/dist/twilight/p-aae761ff.entry.js +4 -0
- package/dist/twilight/p-afd61e47.entry.js +4 -0
- package/dist/twilight/p-b1fc6dfc.entry.js +4 -0
- package/dist/twilight/p-b206a0a1.entry.js +4 -0
- package/dist/twilight/p-b2332516.entry.js +4 -0
- package/dist/twilight/{p-6c2807c8.entry.js → p-b588ef46.entry.js} +1 -1
- package/dist/twilight/p-b71fc1b5.entry.js +4 -0
- package/dist/twilight/{p-_JhF_Kvb.js → p-bVqtOl1F.js} +1 -1
- package/dist/twilight/{p-a858523c.entry.js → p-bf65b263.entry.js} +1 -1
- package/dist/twilight/{p-d4faa0f6.entry.js → p-c56a47b0.entry.js} +1 -1
- package/dist/twilight/p-c73189e3.entry.js +4 -0
- package/dist/twilight/p-d1203242.entry.js +4 -0
- package/dist/twilight/p-d4edfed4.entry.js +4 -0
- package/dist/twilight/{p-f6ffc708.entry.js → p-d86ce978.entry.js} +1 -1
- package/dist/twilight/{p-8e7fa4a9.entry.js → p-d9e7973d.entry.js} +1 -1
- package/dist/twilight/p-e3e33238.entry.js +4 -0
- package/dist/twilight/p-e6bb7362.entry.js +4 -0
- package/dist/twilight/{p-30403778.entry.js → p-e7813c80.entry.js} +1 -1
- package/dist/twilight/p-ec2fd37e.entry.js +4 -0
- package/dist/twilight/{p-ed60a726.entry.js → p-ec77c523.entry.js} +1 -1
- package/dist/twilight/{p-b208650b.entry.js → p-efc18ce6.entry.js} +1 -1
- package/dist/twilight/p-f4039c40.entry.js +4 -0
- package/dist/twilight/p-f47b130c.entry.js +4 -0
- package/dist/twilight/{p-db526796.entry.js → p-f57ca123.entry.js} +1 -1
- package/dist/twilight/{p-933881d3.entry.js → p-f5ad6572.entry.js} +1 -1
- package/dist/twilight/p-fc65084f.entry.js +4 -0
- package/dist/twilight/p-fd81a311.entry.js +4 -0
- package/dist/twilight/{p-9fa5ffcf.entry.js → p-fe983809.entry.js} +1 -1
- package/dist/twilight/{p-Czq4p9Qp.js → p-i5J7XGS6.js} +1 -1
- package/dist/twilight/{p-C2bMx7q5.js → p-shFpk0H3.js} +1 -1
- package/dist/twilight/twilight.esm.js +1 -1
- package/dist/types/components/salla-add-product-button/salla-add-product-button.d.ts +5 -0
- package/dist/types/components/salla-app-install-alert/salla-app-install-alert.d.ts +3 -1
- package/dist/types/components/salla-color-picker/salla-color-picker.d.ts +10 -0
- package/dist/types/components/salla-product-options/salla-product-options.d.ts +8 -1
- package/dist/types/components/salla-products-list/salla-products-list.d.ts +2 -0
- package/dist/types/components.d.ts +4 -0
- package/package.json +5 -5
- package/dist/cjs/salla-accordion_62.cjs.entry.js +0 -22420
- package/dist/cjs/salla-review-card.cjs.entry.js +0 -183
- package/dist/cjs/salla-reviews-page.cjs.entry.js +0 -695
- package/dist/cjs/salla-reviews.cjs.entry.js +0 -106
- package/dist/esm/salla-accordion_62.entry.js +0 -22339
- package/dist/esm/salla-review-card.entry.js +0 -181
- package/dist/esm/salla-reviews-page.entry.js +0 -693
- package/dist/esm/salla-reviews.entry.js +0 -104
- package/dist/twilight/p-01bccbf2.entry.js +0 -4
- package/dist/twilight/p-22d83528.entry.js +0 -4
- package/dist/twilight/p-3a74b551.entry.js +0 -4
- package/dist/twilight/p-4e416704.entry.js +0 -4
- package/dist/twilight/p-5dbf4cec.entry.js +0 -4
- package/dist/twilight/p-CBT_Nxny.js +0 -4
- package/dist/twilight/p-Dz7o69vX.js +0 -4
- package/dist/twilight/p-a42d626d.entry.js +0 -4
- package/dist/twilight/p-yRO-ZESF.js +0 -4
- package/dist/cjs/{twitter-pOrUNjXi.js → facebook-DbXua6B9.js} +2 -2
- package/dist/esm/{twitter-Dz7o69vX.js → facebook-CO-PeZ27.js} +2 -2
|
@@ -0,0 +1,1652 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Crafted with ❤ by Salla
|
|
3
|
+
*/
|
|
4
|
+
import { r as registerInstance, h, H as Host, a as getElement, f as require_root, i as requireIsObject, j as requireIsSymbol, d as getDefaultExportFromCjs } from './index-B74h9G6a.js';
|
|
5
|
+
import { i as iconCheck } from './check-BsXh13x8.js';
|
|
6
|
+
import { a as anime } from './anime.es-CgtvEd63.js';
|
|
7
|
+
import { H as Helper } from './Helper-B5RLi6Xo.js';
|
|
8
|
+
import { S as Star } from './star2-D4oPi1Ov.js';
|
|
9
|
+
import { a as arrowLeft } from './arrow-left-BedNk7k1.js';
|
|
10
|
+
import { S as ShoppingBag } from './shopping-bag-DiKTtDW5.js';
|
|
11
|
+
|
|
12
|
+
const sallaCommentFormCss = ":host{display:block}";
|
|
13
|
+
|
|
14
|
+
const SallaCommentForm = class {
|
|
15
|
+
constructor(hostRef) {
|
|
16
|
+
registerInstance(this, hostRef);
|
|
17
|
+
this.placeholder = salla.lang.get('blocks.comments.placeholder');
|
|
18
|
+
this.submitText = salla.lang.get('blocks.comments.submit');
|
|
19
|
+
salla.lang.onLoaded(() => {
|
|
20
|
+
this.placeholder = salla.lang.get('blocks.comments.placeholder');
|
|
21
|
+
this.submitText = salla.lang.get('blocks.comments.submit');
|
|
22
|
+
});
|
|
23
|
+
salla.onReady(() => {
|
|
24
|
+
this.canComment = salla.config.get('user.can_comment');
|
|
25
|
+
this.itemId = salla.config.get('page.id');
|
|
26
|
+
this.type = salla.url.is_page('page-single') ? 'page' : salla.url.is_page('blog.single') ? 'blog' : 'product';
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
submit() {
|
|
30
|
+
if (!this.commentForm.reportValidity()) {
|
|
31
|
+
salla.log('CommentForm:: validation error!');
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
this.submitBtn.load()
|
|
35
|
+
.then(() => salla.comment.add({ id: this.itemId, comment: this.commentField.value, type: this.type }))
|
|
36
|
+
.finally(() => this.submitBtn.stop);
|
|
37
|
+
}
|
|
38
|
+
render() {
|
|
39
|
+
return (h(Host, { key: 'fbea28507c188a338ee066b5198bcf93de2fbda2' }, !!this.canComment ? h("form", { ref: frm => this.commentForm = frm }, h("div", { class: "s-comment-form-wrapper" }, this.showAvatar ?
|
|
40
|
+
h("img", { class: "s-comment-form-avatar", src: salla.config.get('user.avatar'), alt: "user avatar" }) : '', h("div", { class: "s-comment-form-content" }, h("textarea", { cols: 30, rows: 5, minlength: "4", maxlength: "500", ref: field => this.commentField = field, placeholder: this.placeholder, class: "s-comment-form-input", required: true }), h("br", null), h("div", { class: "s-comment-form-action" }, h("salla-button", { ref: btn => this.submitBtn = btn, "loader-position": 'center', onClick: () => this.submit() }, this.submitText))))) : ''));
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
SallaCommentForm.style = sallaCommentFormCss;
|
|
44
|
+
|
|
45
|
+
var Reply = `<!-- Generated by IcoMoon.io -->
|
|
46
|
+
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
|
47
|
+
<title>reply</title>
|
|
48
|
+
<path d="M20 14.667h-12.609l9.401-6.927c0.592-0.436 0.72-1.271 0.283-1.863-0.439-0.595-1.273-0.72-1.864-0.283l-12.667 9.333c-0.343 0.251-0.544 0.649-0.544 1.072s0.201 0.821 0.543 1.073l12.667 9.333c0.237 0.176 0.515 0.26 0.789 0.26 0.409 0 0.813-0.188 1.075-0.543 0.437-0.592 0.309-1.427-0.283-1.863l-9.4-6.928h12.609c4.412 0 8 3.588 8 8 0 0.737 0.597 1.333 1.333 1.333s1.333-0.596 1.333-1.333c0-5.881-4.785-10.667-10.667-10.667z"></path>
|
|
49
|
+
</svg>
|
|
50
|
+
`;
|
|
51
|
+
|
|
52
|
+
var ThumbsUp = `<!-- Generated by IcoMoon.io -->
|
|
53
|
+
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
|
54
|
+
<title>thumbs-up</title>
|
|
55
|
+
<path d="M26.667 10.667h-8.261l1.279-3.38c0.723-1.911 0.087-4.051-1.549-5.203-0.909-0.639-2.004-0.881-3.085-0.684-1.101 0.203-2.061 0.837-2.703 1.787l-5.452 8.067c-0.148 0.22-0.228 0.48-0.228 0.747v12c0 3.676 2.991 6.667 6.667 6.667h8.688c2.535 0 4.817-1.407 5.955-3.671l2.548-5.063c0.093-0.187 0.143-0.392 0.143-0.6v-6.667c0-2.205-1.795-4-4-4zM28 21.017l-2.405 4.78c-0.683 1.359-2.052 2.203-3.573 2.203h-8.688c-2.205 0-4-1.795-4-4v-11.592l5.223-7.728c0.237-0.352 0.584-0.585 0.975-0.657 0.367-0.067 0.749 0.017 1.068 0.241 0.631 0.444 0.879 1.317 0.591 2.079l-1.963 5.185c-0.156 0.409-0.099 0.869 0.149 1.229s0.66 0.576 1.099 0.576h10.192c0.735 0 1.333 0.599 1.333 1.333zM2.667 10.667c-0.736 0-1.333 0.597-1.333 1.333v16c0 0.736 0.597 1.333 1.333 1.333s1.333-0.597 1.333-1.333v-16c0-0.736-0.597-1.333-1.333-1.333z"></path>
|
|
56
|
+
</svg>
|
|
57
|
+
`;
|
|
58
|
+
|
|
59
|
+
const sallaCommentsCss$1 = ":host{display:block}";
|
|
60
|
+
|
|
61
|
+
const SallaCommentItem = class {
|
|
62
|
+
constructor(hostRef) {
|
|
63
|
+
registerInstance(this, hostRef);
|
|
64
|
+
// Translations
|
|
65
|
+
this.has_bought_trans = salla.lang.get('blocks.comments.has_bought');
|
|
66
|
+
this.rated_trans = salla.lang.get('pages.rating.rated');
|
|
67
|
+
this.waiting_approval_trans = salla.lang.get('blocks.comments.waiting_approval');
|
|
68
|
+
this.has_order_trans = salla.lang.get('blocks.comments.has_order');
|
|
69
|
+
this.allowLikes = salla.config.get('store.settings.rating.allow_likes');
|
|
70
|
+
this.allowAttachImages = salla.config.get('store.settings.rating.allow_attach_images');
|
|
71
|
+
this.helpfulLabel = salla.lang.getWithDefault('blocks.comments.helpful', 'مفيد');
|
|
72
|
+
this.likesCount = 0;
|
|
73
|
+
this.likedComments = [];
|
|
74
|
+
salla.lang.onLoaded(() => {
|
|
75
|
+
const setNestedAsync = (lang, key, value) => {
|
|
76
|
+
return new Promise((resolve) => {
|
|
77
|
+
salla.helpers.setNested(salla.lang.messages[lang], key, value);
|
|
78
|
+
resolve(true);
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
const setTranslations = async () => {
|
|
82
|
+
await setNestedAsync('ar.trans', 'blocks.comments.helpful', 'مفيد');
|
|
83
|
+
await setNestedAsync('en.trans', 'blocks.comments.helpful', 'Helpful');
|
|
84
|
+
this.helpfulLabel = salla.lang.getWithDefault('blocks.comments.helpful', 'مفيد');
|
|
85
|
+
};
|
|
86
|
+
this.has_bought_trans = salla.lang.get('blocks.comments.has_bought');
|
|
87
|
+
this.rated_trans = salla.lang.get('pages.rating.rated');
|
|
88
|
+
this.waiting_approval_trans = salla.lang.get('blocks.comments.waiting_approval');
|
|
89
|
+
this.has_order_trans = salla.lang.get('blocks.comments.has_order');
|
|
90
|
+
setTranslations();
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
componentDidLoad() {
|
|
94
|
+
this.likesCount = this.comment.likes_count;
|
|
95
|
+
try {
|
|
96
|
+
this.likedComments = JSON.parse(localStorage.getItem('liked_comments') || '[]');
|
|
97
|
+
if (this.likedComments.includes(this.comment.id)) {
|
|
98
|
+
this.likeBtn.classList.add('liked');
|
|
99
|
+
this.likeBtn.fill = "solid";
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
salla.log('Bad json for liked_comments');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
getReplies() {
|
|
107
|
+
return Array.isArray(this.comment.replies) ? this.comment.replies : [this.comment.replies];
|
|
108
|
+
}
|
|
109
|
+
getDate(dateString) {
|
|
110
|
+
const [datePart] = dateString.split(' ');
|
|
111
|
+
const [year, month, day] = datePart.split('-');
|
|
112
|
+
const formattedDate = `${parseInt(day, 10)}/${parseInt(month, 10)}/${parseInt(year, 10)}`;
|
|
113
|
+
return formattedDate;
|
|
114
|
+
}
|
|
115
|
+
getTime(dateString) {
|
|
116
|
+
const [, timePart] = dateString.split(' ');
|
|
117
|
+
const [hours, minutes] = timePart.split(':');
|
|
118
|
+
const formattedTime = `${parseInt(hours, 10)}:${parseInt(minutes, 10)}`;
|
|
119
|
+
return formattedTime;
|
|
120
|
+
}
|
|
121
|
+
async toggleLike() {
|
|
122
|
+
if (salla.config.isGuest()) {
|
|
123
|
+
return salla.notify.error(salla.lang.get('common.messages.must_login'));
|
|
124
|
+
}
|
|
125
|
+
this.likedComments = JSON.parse(localStorage.getItem('liked_comments') || '[]');
|
|
126
|
+
const isLiked = this.likedComments.includes(this.comment.id);
|
|
127
|
+
try {
|
|
128
|
+
const endpoint = isLiked ? `rating/${this.comment.id}/unlike` : `rating/${this.comment.id}/like`;
|
|
129
|
+
const res = await salla.api.request(endpoint, '', 'put');
|
|
130
|
+
salla.log(res.message);
|
|
131
|
+
if (isLiked) {
|
|
132
|
+
this.likeBtn.classList.remove('liked');
|
|
133
|
+
this.likeBtn.fill = 'outline';
|
|
134
|
+
this.updateLikedComments(this.comment.id, false);
|
|
135
|
+
this.likesCount--;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
this.likeBtn.classList.add('liked');
|
|
139
|
+
this.likeBtn.fill = 'solid';
|
|
140
|
+
this.updateLikedComments(this.comment.id, true);
|
|
141
|
+
this.likesCount++;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
if (e.response.status == 409) {
|
|
146
|
+
if (this.likeBtn.classList.contains('liked')) {
|
|
147
|
+
this.likeBtn.fill = 'outline';
|
|
148
|
+
this.likeBtn.classList.remove('liked');
|
|
149
|
+
this.updateLikedComments(this.comment.id, false);
|
|
150
|
+
this.likesCount--;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
this.likeBtn.fill = 'solid';
|
|
154
|
+
this.likeBtn.classList.add('liked');
|
|
155
|
+
salla.logger.warn('Like already exists');
|
|
156
|
+
this.updateLikedComments(this.comment.id, true);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
updateLikedComments(commentId, add) {
|
|
162
|
+
this.likedComments = JSON.parse(localStorage.getItem('liked_comments') || '[]');
|
|
163
|
+
if (add) {
|
|
164
|
+
if (!this.likedComments.includes(commentId)) {
|
|
165
|
+
this.likedComments.push(commentId);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
this.likedComments = this.likedComments.filter(id => id !== commentId);
|
|
170
|
+
}
|
|
171
|
+
localStorage.setItem('liked_comments', JSON.stringify(this.likedComments));
|
|
172
|
+
}
|
|
173
|
+
PinnedIcon() {
|
|
174
|
+
return (h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: "16", height: "16", color: "#555555", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("path", { d: "M12 16V21" }), h("path", { d: "M8 5.2918C8 5.02079 8 4.88529 8.01312 4.77132C8.1194 3.84789 8.84789 3.1194 9.77133 3.01312C9.88529 3 10.0208 3 10.2918 3H13.7082C13.9792 3 14.1147 3 14.2287 3.01312C15.1521 3.1194 15.8806 3.84789 15.9869 4.77132C16 4.88529 16 5.02079 16 5.2918C16 5.37885 16 5.42237 15.9967 5.46264C15.9708 5.78281 15.7927 6.07104 15.5179 6.2374C15.4834 6.25832 15.4444 6.27779 15.3666 6.31672L15.1055 6.44726C14.7021 6.64897 14.5003 6.74983 14.3681 6.90564C14.26 7.03286 14.1856 7.18509 14.1515 7.34846C14.1097 7.54854 14.1539 7.76968 14.2424 8.21197L15 12H15.3333C15.9533 12 16.2633 12 16.5176 12.0681C17.2078 12.2531 17.7469 12.7922 17.9319 13.4824C18 13.7367 18 14.0467 18 14.6667C18 14.9767 18 15.1317 17.9659 15.2588C17.8735 15.6039 17.6039 15.8735 17.2588 15.9659C17.1317 16 16.9767 16 16.6667 16H7.33333C7.02334 16 6.86835 16 6.74118 15.9659C6.39609 15.8735 6.12654 15.6039 6.03407 15.2588C6 15.1317 6 14.9767 6 14.6667C6 14.0467 6 13.7367 6.06815 13.4824C6.25308 12.7922 6.79218 12.2531 7.48236 12.0681C7.73669 12 8.04669 12 8.66667 12H9L9.75761 8.21197C9.84606 7.76968 9.89029 7.54854 9.84852 7.34846C9.81441 7.18509 9.73995 7.03286 9.63194 6.90564C9.49965 6.74983 9.29794 6.64897 8.89452 6.44726L8.63344 6.31672C8.55558 6.27779 8.51665 6.25832 8.48208 6.2374C8.20731 6.07104 8.02917 5.78281 8.00326 5.46264C8 5.42237 8 5.37885 8 5.2918Z" })));
|
|
175
|
+
}
|
|
176
|
+
render() {
|
|
177
|
+
let isAdmin = this.comment.type == 'admin';
|
|
178
|
+
return (h(Host, { key: '05979122884df06d634ab4f75f61d12cee93b228', class: isAdmin ? 's-comments-item-admin' : 's-comments-item' }, h("div", { key: 'd3be984afb159d8d6a1d4c0daf0bb72c97136a3a', class: { "s-comments-item-wrapper": !isAdmin, "s-comments-item-admin-wrapper": isAdmin }, id: `s-comments-item-${this.comment.id}` }, h("div", { key: '29a48174434b634e4afa5a1f2339b04705ea9f90', class: "s-comments-item-inner s-comments-flex-1" }, isAdmin && h("span", { key: 'b2536843c0549b2eb24759a09f51a97b68e36654', class: "s-comments-item-reply-icon", innerHTML: Reply }), h("div", { key: '553ad8fd8a3ada5cbca3c744f8b80a259ae7d2c2', class: "s-comments-item-avatar" }, h("img", { key: '57d429fa1dc545d3fe16c1f4713b960d1d7ef9f8', "data-src": this.comment?.avatar, alt: this.comment?.name, src: this.comment?.avatar, class: "s-comments-item-avatar-img lazy" })), h("div", { key: '8b2a3206dfa97c41a731baf18794e44ce096876f', class: "s-comments-flex-1" }, h("div", { key: '95ebefb4d82bb66d7cbc567554d0b9da2e4b416a', class: "s-comments-item-user-wrapper" }, h("div", { key: '1e6091d08973e5fc2ae8a982e6b09e5d349fede3', class: "s-comments-item-user-info" }, h("h3", { key: 'ee5ea0ea457fc43ee49cae033097297ab8358f76', class: this.comment.is_pinned ? "s-comments-item-user-info-name" : "s-comments-item-user-info-name-with-margin" }, this.comment?.name), this.comment.is_pinned ?
|
|
179
|
+
h("div", { class: "s-comments-item-pinned-icon-with-margin" }, this.PinnedIcon())
|
|
180
|
+
: null, (this.comment.has_order || !!this.comment.rating) && !this.comment.is_pending && !this.hideBought ?
|
|
181
|
+
h("div", { class: "s-comments-flex" }, this.comment.has_order ?
|
|
182
|
+
[h("span", { class: "s-comments-item-has-order-check-icon", innerHTML: iconCheck }), h("span", { class: "s-comments-item-has-order-check-text" }, this.has_bought_trans, " ", this.comment.rating ? ', ' : '')] : null, !!this.comment.rating ?
|
|
183
|
+
h("span", { class: "s-comments-item-rated-widget" }, this.rated_trans) : null)
|
|
184
|
+
: null), h("p", { key: '80c430d77b6ae3e959db9bc089fd7fe834e56bd2', class: "s-comments-item-timestamp s-ltr" }, this.getDate(this.comment.created_at?.date), h("span", { key: '49a1b26309490d6252f0fbd53b50374cbf10071d', class: "s-comments-item-time" }, " - ", this.getTime(this.comment.created_at?.date))), !!this.comment.rating || !!this.comment.stars ?
|
|
185
|
+
h("salla-rating-stars", { size: "mini", class: "s-comments-item-stars", value: this.comment.rating || this.comment.stars })
|
|
186
|
+
: null), h("div", { key: '780bee1166000b296e6956921c71cfd4f48e8153', class: "s-comments-item-content" }, h("p", { key: '9ff2a32cbd551ff911300ce6cfa1065770117a18', innerHTML: this.comment.content }), this.allowAttachImages && h("div", { key: 'f47022f4916c3d4e0641273612b4a5f7c69a4595', class: "s-comments-item-images" }, this.comment.images.map((image, index) => (h("img", { key: index, src: image, alt: "", onClick: () => this.modal.open() }))), h("salla-modal", { key: '8e70ec00301d369bbed5c1f11a1887a0498e2b0c', ref: modal => this.modal = modal, width: "sm" }, h("salla-slider", { key: '65cb35fd60869f64780fbb5bfc61fbc3cddc49c9', id: `s-comments-item-${this.comment.id}-images`, class: "s-comments-item-images-slider", type: "thumbs", "auto-height": true, showControls: this.comment.images.length > 1 ? true : false, "show-thumbs-controls": "false" }, h("div", { key: 'bb0cf465f99ecfe9ee10dfb96949cd7b5793da90', slot: 'items' }, this.comment.images.map((image, index) => (h("img", { key: index, src: image, alt: "" })))), h("div", { key: 'e195759f1df5a87b761478ac4a379411f284785c', slot: "thumbs" }, this.comment.images.map((image, index) => (h("div", { class: "s-comments-item-images-slider-thumb" }, h("img", { key: index, src: image, alt: "" })))))))), this.allowLikes && !isAdmin && salla.url.is_page('product.single') ? h("salla-button", { ref: el => this.likeBtn = el, class: `s-comments-item-like-btn ${this.likedComments.includes(this.comment.id) ? 'liked' : ''}`, loaderPosition: 'center', fill: 'outline', size: 'small', onClick: () => this.toggleLike() }, h("span", null, this.helpfulLabel, " ", this.likesCount > 0 ? `(${this.likesCount})` : ''), h("span", { innerHTML: ThumbsUp })) : '', this.comment.is_pending ?
|
|
187
|
+
h("span", { class: "s-comments-item-pending-text" }, this.waiting_approval_trans) : null))), !!this.getReplies().length && !isAdmin ?
|
|
188
|
+
this.getReplies().map((reply) => {
|
|
189
|
+
return h("div", null, h("salla-comment-item", { comment: reply }));
|
|
190
|
+
}) : null)));
|
|
191
|
+
}
|
|
192
|
+
get host() { return getElement(this); }
|
|
193
|
+
};
|
|
194
|
+
SallaCommentItem.style = sallaCommentsCss$1;
|
|
195
|
+
|
|
196
|
+
var CommentType;
|
|
197
|
+
(function (CommentType) {
|
|
198
|
+
CommentType["PAGE"] = "page";
|
|
199
|
+
CommentType["PRODUCT"] = "product";
|
|
200
|
+
CommentType["BLOG"] = "blog";
|
|
201
|
+
})(CommentType || (CommentType = {}));
|
|
202
|
+
|
|
203
|
+
var ChatBubbles = `<!-- Generated by IcoMoon.io -->
|
|
204
|
+
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
|
205
|
+
<title>chat-bubbles</title>
|
|
206
|
+
<path d="M15.333 17.333c4.779 0 8.667-3.888 8.667-8.667s-3.888-8.667-8.667-8.667h-6.667c-4.779 0-8.667 3.888-8.667 8.667 0 2.985 1.513 5.712 4 7.297v4.703c0 0.497 0.277 0.953 0.717 1.183 0.195 0.1 0.405 0.151 0.616 0.151 0.269 0 0.536-0.081 0.764-0.241l6.323-4.425zM11.236 14.908l-4.569 3.199v-2.913c0-0.5-0.28-0.959-0.725-1.187-2.020-1.035-3.275-3.080-3.275-5.34 0-3.308 2.692-6 6-6h6.667c3.308 0 6 2.692 6 6s-2.692 6-6 6h-3.333c-0.273 0-0.54 0.084-0.764 0.241zM29.196 12.964c-0.543-0.5-1.388-0.464-1.884 0.077-0.5 0.541-0.465 1.385 0.077 1.884 1.253 1.156 1.944 2.72 1.944 4.408 0 2.26-1.255 4.305-3.275 5.339-0.445 0.228-0.725 0.687-0.725 1.188v2.572l-5.441-2.939c-0.195-0.104-0.412-0.16-0.633-0.16h-2.592c-1.688 0-3.309-0.724-4.451-1.988-0.492-0.545-1.335-0.591-1.883-0.096-0.547 0.493-0.589 1.336-0.096 1.883 1.644 1.823 3.988 2.868 6.429 2.868h2.255l7.111 3.84c0.199 0.107 0.417 0.16 0.635 0.16 0.236 0 0.472-0.063 0.683-0.188 0.404-0.241 0.651-0.676 0.651-1.145v-4.036c2.487-1.585 4-4.311 4-7.297 0-2.407-1.023-4.727-2.804-6.369z"></path>
|
|
207
|
+
</svg>
|
|
208
|
+
`;
|
|
209
|
+
|
|
210
|
+
const sallaCommentsCss = ":host{display:block}";
|
|
211
|
+
|
|
212
|
+
const SallaComments = class {
|
|
213
|
+
constructor(hostRef) {
|
|
214
|
+
registerInstance(this, hostRef);
|
|
215
|
+
/**
|
|
216
|
+
* Comment Type
|
|
217
|
+
*/
|
|
218
|
+
this.type = CommentType.PAGE;
|
|
219
|
+
/**
|
|
220
|
+
* Show or hide avatar
|
|
221
|
+
*/
|
|
222
|
+
this.showFormAvatar = false;
|
|
223
|
+
/**
|
|
224
|
+
* Hide Bought
|
|
225
|
+
*/
|
|
226
|
+
this.hideBought = false;
|
|
227
|
+
/**
|
|
228
|
+
* Determines if the comments are testimonials
|
|
229
|
+
*/
|
|
230
|
+
this.testimonials = false;
|
|
231
|
+
// Translations
|
|
232
|
+
this.noComments = salla.lang.get('blocks.comments.no_comments');
|
|
233
|
+
this.comment_title = salla.lang.get('blocks.comments.title');
|
|
234
|
+
this.comment_name = salla.lang.get('blocks.comments.comment');
|
|
235
|
+
this.showRatingSummary = salla.config.get('store.settings.rating.show_rating_summary');
|
|
236
|
+
this.allowLikes = salla.config.get('store.settings.rating.allow_likes');
|
|
237
|
+
salla.onReady(() => {
|
|
238
|
+
this.allowLikes = salla.config.get('store.settings.rating.allow_likes');
|
|
239
|
+
this.showRatingSummary = salla.config.get('store.settings.rating.show_rating_summary');
|
|
240
|
+
});
|
|
241
|
+
salla.lang.onLoaded(() => {
|
|
242
|
+
this.comment_title = salla.lang.get('blocks.comments.title');
|
|
243
|
+
this.comment_name = salla.lang.get('blocks.comments.comment');
|
|
244
|
+
this.noComments = salla.lang.get('pages.rating.no_ratings');
|
|
245
|
+
const setNestedAsync = (lang, key, value) => {
|
|
246
|
+
return new Promise((resolve) => {
|
|
247
|
+
salla.helpers.setNested(salla.lang.messages[lang], key, value);
|
|
248
|
+
resolve(true);
|
|
249
|
+
});
|
|
250
|
+
};
|
|
251
|
+
const setTranslations = async () => {
|
|
252
|
+
await setNestedAsync('ar.trans', 'blocks.comments.most_helpful', 'الأكثر إفادة');
|
|
253
|
+
await setNestedAsync('en.trans', 'blocks.comments.most_helpful', 'Most helpful');
|
|
254
|
+
this.mostHelpfulLabel = salla.lang.get('blocks.comments.most_helpful');
|
|
255
|
+
this.comment_title = salla.lang.get('blocks.comments.title');
|
|
256
|
+
this.comment_name = salla.lang.get('blocks.comments.comment');
|
|
257
|
+
this.noComments = salla.lang.get('pages.rating.no_ratings');
|
|
258
|
+
};
|
|
259
|
+
setTranslations();
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
// TOOD: it's a good idea to move this into lang.js
|
|
263
|
+
// Pluralize a string based on the count
|
|
264
|
+
pluralize(phrases, count) {
|
|
265
|
+
const options = phrases.split('|');
|
|
266
|
+
const conditions = [
|
|
267
|
+
{ condition: count === 0, index: 0 },
|
|
268
|
+
{ condition: count === 1, index: 1 },
|
|
269
|
+
{ condition: count === 2, index: 2 },
|
|
270
|
+
{ condition: count > 2 && count <= 10, index: 3 },
|
|
271
|
+
{ condition: count >= 11, index: 4 }
|
|
272
|
+
];
|
|
273
|
+
const { index } = conditions.find(({ condition }) => condition) || { index: options.length - 1 };
|
|
274
|
+
const selectedOption = options[index];
|
|
275
|
+
return selectedOption.replace(':count', salla.helpers.number(count.toString()))
|
|
276
|
+
.replace(/\{[0-9]+\}/g, '')
|
|
277
|
+
.replace(/\[\d+,\d+\]|\[11,\*\]/g, '');
|
|
278
|
+
}
|
|
279
|
+
wrapConsoleError() {
|
|
280
|
+
if (Salla.infiniteScroll.errorWrapped) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
(() => {
|
|
284
|
+
const orig = console.error.bind(console);
|
|
285
|
+
console.error = (...args) => {
|
|
286
|
+
const msg = args[0];
|
|
287
|
+
// only rewrite the noisy one
|
|
288
|
+
if (typeof msg === 'string' && msg.toLowerCase().replace(/\s/g, '').includes('infinitescroll')) {
|
|
289
|
+
return console.log(...args); // downgrade to log
|
|
290
|
+
}
|
|
291
|
+
return orig(...args); // keep real errors
|
|
292
|
+
};
|
|
293
|
+
})();
|
|
294
|
+
Salla.infiniteScroll.errorWrapped = true;
|
|
295
|
+
}
|
|
296
|
+
// Initiate infinite scroll
|
|
297
|
+
initiateInfiniteScroll() {
|
|
298
|
+
if (!this.wrapper) {
|
|
299
|
+
console.error('Wrapper is undefined. Cannot initiate infinite scroll.');
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
this.wrapConsoleError();
|
|
303
|
+
this.infiniteScroll = salla.infiniteScroll.initiate(this.wrapper, this.wrapper, {
|
|
304
|
+
path: () => this.nextPage,
|
|
305
|
+
history: false,
|
|
306
|
+
nextPage: this.nextPage,
|
|
307
|
+
scrollThreshold: false,
|
|
308
|
+
}, true);
|
|
309
|
+
this.infiniteScroll?.on('request', _response => {
|
|
310
|
+
this.loading();
|
|
311
|
+
});
|
|
312
|
+
this.infiniteScroll?.on('load', response => {
|
|
313
|
+
this.pagination = response.pagination;
|
|
314
|
+
this.nextPage = typeof response.pagination.links === 'object' && !!response.pagination.links.next ? response.pagination.links.next : null;
|
|
315
|
+
for (const card of this.handleResponse(response)) {
|
|
316
|
+
this.wrapper.append(card);
|
|
317
|
+
}
|
|
318
|
+
const items = this.host.querySelectorAll('salla-comment-item:not(.animated):not(.s-comments-item-admin)');
|
|
319
|
+
this.animateItems(items);
|
|
320
|
+
this.loading(false);
|
|
321
|
+
});
|
|
322
|
+
this.infiniteScroll?.on('error', (e) => {
|
|
323
|
+
salla.console.error('Error loading more comments:', e);
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
// Show/hide loading
|
|
327
|
+
loading(isLoading = true) {
|
|
328
|
+
const btnText = this.status?.querySelector('.s-button-text');
|
|
329
|
+
if (btnText) {
|
|
330
|
+
Helper.toggleElementClassIf(btnText, 's-button-hide', 's-button-show', () => isLoading);
|
|
331
|
+
this.btnLoader.style.display = isLoading ? 'inherit' : 'none';
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
// Animate newly added items
|
|
335
|
+
animateItems(items) {
|
|
336
|
+
anime({
|
|
337
|
+
targets: items,
|
|
338
|
+
opacity: [0, 1],
|
|
339
|
+
duration: 1200,
|
|
340
|
+
translateY: [20, 0],
|
|
341
|
+
delay: (_el, i) => i * 100,
|
|
342
|
+
easing: 'easeOutExpo',
|
|
343
|
+
complete: (_anim) => {
|
|
344
|
+
for (const item of items) {
|
|
345
|
+
item.classList.add('animated');
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Reloads the comments data from the server
|
|
352
|
+
*/
|
|
353
|
+
async reload() {
|
|
354
|
+
this.showPlaceholder = false;
|
|
355
|
+
if (this.wrapper) {
|
|
356
|
+
this.wrapper.innerHTML = "";
|
|
357
|
+
const loading = document.createElement('salla-loading');
|
|
358
|
+
this.wrapper.append(loading);
|
|
359
|
+
}
|
|
360
|
+
this.nextPage = null;
|
|
361
|
+
this.loadInitialData();
|
|
362
|
+
}
|
|
363
|
+
// Get comment item HTML
|
|
364
|
+
getCommentHTML(comment) {
|
|
365
|
+
const commentItem = document.createElement('salla-comment-item');
|
|
366
|
+
commentItem.comment = comment;
|
|
367
|
+
commentItem.hideBought = this.hideBought;
|
|
368
|
+
return commentItem;
|
|
369
|
+
}
|
|
370
|
+
// Parse response and return an array of comment items to be appended to the wrapper
|
|
371
|
+
handleResponse(response) {
|
|
372
|
+
return response.data?.map(comment => this.getCommentHTML(comment)) || [];
|
|
373
|
+
}
|
|
374
|
+
componentWillLoad() {
|
|
375
|
+
return salla.onReady()
|
|
376
|
+
.then(() => {
|
|
377
|
+
this.showRatingSummary = salla.config.get('store.settings.rating.show_rating_summary');
|
|
378
|
+
})
|
|
379
|
+
.then(() => this.loading())
|
|
380
|
+
.then(() => {
|
|
381
|
+
this.hideTitle = this.hideTitle || this.testimonials;
|
|
382
|
+
this.hideForm = this.hideForm || this.testimonials;
|
|
383
|
+
return this.loadInitialData();
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
// Load initial data
|
|
387
|
+
async loadInitialData() {
|
|
388
|
+
try {
|
|
389
|
+
let resp = { data: [], pagination: {} };
|
|
390
|
+
const searchParams = new URLSearchParams(window.location.search);
|
|
391
|
+
if (searchParams.has('sort')) {
|
|
392
|
+
this.sort = searchParams.get('sort');
|
|
393
|
+
}
|
|
394
|
+
if (this.testimonials) {
|
|
395
|
+
const params = {
|
|
396
|
+
sort: this.sort,
|
|
397
|
+
type: "store"
|
|
398
|
+
};
|
|
399
|
+
resp = await salla.api.request('reviews', { params }, 'get');
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
// Ensure sort is passed for regular comments as well
|
|
403
|
+
resp = await salla.api.comment.getComments(this.type, this.itemId, 1, 5, this.sort);
|
|
404
|
+
}
|
|
405
|
+
if (!resp.data || !resp.data.length) {
|
|
406
|
+
this.showPlaceholder = false;
|
|
407
|
+
this.loading(false);
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
if (this.wrapper) {
|
|
411
|
+
this.wrapper.innerHTML = "";
|
|
412
|
+
}
|
|
413
|
+
this.comments = resp.data;
|
|
414
|
+
this.pagination = resp.pagination;
|
|
415
|
+
this.total = resp.pagination.total;
|
|
416
|
+
this.nextPage = typeof resp.pagination.links === 'object' && !!resp.pagination.links.next ? resp.pagination.links.next : null;
|
|
417
|
+
// Preserve sort param in next page URL for infinite scroll
|
|
418
|
+
if (this.nextPage && this.sort) {
|
|
419
|
+
try {
|
|
420
|
+
const url = new URL(this.nextPage, window.location.origin);
|
|
421
|
+
if (!url.searchParams.get('sort')) {
|
|
422
|
+
url.searchParams.set('sort', this.sort);
|
|
423
|
+
this.nextPage = url.toString();
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
catch (_e) {
|
|
427
|
+
// fallback for relative next links
|
|
428
|
+
const hasQuery = this.nextPage.includes('?');
|
|
429
|
+
const hasSort = /[?&]sort=/.test(this.nextPage);
|
|
430
|
+
if (!hasSort) {
|
|
431
|
+
this.nextPage = this.nextPage + (hasQuery ? '&' : '?') + `sort=${this.sort}`;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
setTimeout(() => {
|
|
436
|
+
for (const card of this.handleResponse(resp)) {
|
|
437
|
+
this.wrapper.append(card);
|
|
438
|
+
}
|
|
439
|
+
this.initiateInfiniteScroll(); // Initiate infinite scroll after the initial data is loaded
|
|
440
|
+
const items = this.wrapper.querySelectorAll('salla-comment-item:not(.animated)');
|
|
441
|
+
this.animateItems(items);
|
|
442
|
+
}, 100);
|
|
443
|
+
}
|
|
444
|
+
catch (error) {
|
|
445
|
+
console.error('Error loading initial data:', error);
|
|
446
|
+
this.showPlaceholder = true;
|
|
447
|
+
this.loading(false);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
// Get next page
|
|
451
|
+
async loadMore() {
|
|
452
|
+
this.infiniteScroll?.loadNextPage();
|
|
453
|
+
}
|
|
454
|
+
render() {
|
|
455
|
+
// We should show a different placeholder for pages and products (WIP)
|
|
456
|
+
if (this.showPlaceholder) {
|
|
457
|
+
return (h("div", null, !!this.total && !this.hideTitle ? h("h2", { class: "s-comments-title" }, this.blockTitle ? this.blockTitle : this.comment_title) : '', !this.hideForm && !this.testimonials ? h("salla-comment-form", { showAvatar: this.showFormAvatar, type: this.type, "item-id": this.itemId }) : '', h("div", { class: "s-comments-placeholder" }, h("span", { innerHTML: ChatBubbles }), h("p", null, this.noComments))));
|
|
458
|
+
}
|
|
459
|
+
return (h("div", { class: `s-comments s-comments-${this.testimonials ? 'testimonials' : this.type}` }, h("div", { class: `${this.type === CommentType.PAGE ? "s-comments-page-container" : "s-comments-container"}` }, !!this.total && !this.hideTitle ? h("h2", { class: "s-comments-title" }, this.blockTitle ? this.blockTitle : this.comment_title) : '', !this.hideForm && h("salla-comment-form", { showAvatar: this.showFormAvatar, type: this.type, "item-id": this.itemId }), salla.url.is_page('product.single') ? h("salla-reviews-summary", { itemId: this.itemId }) : '', h("div", { class: `s-comments-header ${this.total ? "has-total" : ""}` }, !!this.total && h("span", { class: "s-comments-count-label", innerHTML: this.pluralize(this.comment_name, this.total) }), !!this.total && !this.testimonials && this.type !== CommentType.BLOG ?
|
|
460
|
+
h("div", { class: "s-comments-filter-wrapper" }, h("label", { class: "s-comments-filter-label", htmlFor: "comments-filter" }, salla.lang.get('pages.categories.sorting')), h("select", { id: "comments-filter", "aria-label": salla.lang.get('pages.categories.sorting'), class: "s-form-control s-comments-sort-input", onChange: (e) => {
|
|
461
|
+
this.sort = e.target.value;
|
|
462
|
+
this.reload();
|
|
463
|
+
} }, h("option", { value: "latest", selected: true }, salla.lang.get("pages.testimonials.sort_by_date_desc")), h("option", { value: "oldest" }, salla.lang.get("pages.testimonials.sort_by_date_asc")), this.allowLikes && h("option", { value: "most_helpful" }, this.mostHelpfulLabel)))
|
|
464
|
+
: ''), h("div", { ref: wrapper => {
|
|
465
|
+
this.wrapper = wrapper;
|
|
466
|
+
} }), this.nextPage && (h("div", { class: "s-infinite-scroll-wrapper", ref: status => {
|
|
467
|
+
this.status = status;
|
|
468
|
+
} }, h("button", { onClick: () => this.loadMore(), class: "s-infinite-scroll-btn s-button-btn s-button-primary", type: "button" }, h("span", { class: "s-button-text s-infinite-scroll-btn-text" }, this.loadMoreText ? this.loadMoreText : salla.lang.get('common.elements.load_more')), h("span", { class: "s-button-loader s-button-loader-center s-infinite-scroll-btn-loader", ref: btnLoader => {
|
|
469
|
+
this.btnLoader = btnLoader;
|
|
470
|
+
}, style: { "display": "none" } })))))));
|
|
471
|
+
}
|
|
472
|
+
get host() { return getElement(this); }
|
|
473
|
+
};
|
|
474
|
+
SallaComments.style = sallaCommentsCss;
|
|
475
|
+
|
|
476
|
+
const sallaRatingStarsCss = "";
|
|
477
|
+
|
|
478
|
+
const SallaRatingStars = class {
|
|
479
|
+
constructor(hostRef) {
|
|
480
|
+
registerInstance(this, hostRef);
|
|
481
|
+
this.translationsLoaded = false;
|
|
482
|
+
this.labels = [];
|
|
483
|
+
this.reviewLabel = '';
|
|
484
|
+
this.selectedStar = 0;
|
|
485
|
+
/**
|
|
486
|
+
* Sets input name.
|
|
487
|
+
*/
|
|
488
|
+
this.name = 'rating';
|
|
489
|
+
/**
|
|
490
|
+
* Sets the height and width of the component. Defaults to medium.
|
|
491
|
+
*/
|
|
492
|
+
this.size = 'medium';
|
|
493
|
+
/**
|
|
494
|
+
* Number of reviews to display.
|
|
495
|
+
*/
|
|
496
|
+
this.reviews = 0;
|
|
497
|
+
/**
|
|
498
|
+
* Allows the rating to be editable.
|
|
499
|
+
*/
|
|
500
|
+
this.editable = false;
|
|
501
|
+
}
|
|
502
|
+
async componentWillLoad() {
|
|
503
|
+
await new Promise(resolve => {
|
|
504
|
+
salla.lang.onLoaded(() => {
|
|
505
|
+
this.labels = [
|
|
506
|
+
salla.lang.get('pages.rating.poor'),
|
|
507
|
+
salla.lang.get('pages.rating.average'),
|
|
508
|
+
salla.lang.get('pages.rating.good'),
|
|
509
|
+
salla.lang.get('pages.rating.very_good'),
|
|
510
|
+
salla.lang.get('pages.rating.excellent')
|
|
511
|
+
];
|
|
512
|
+
if (this.value && this.withLabel) {
|
|
513
|
+
this.reviewLabel = this.labels[this.value - 1];
|
|
514
|
+
}
|
|
515
|
+
if (this.reviewsElement) {
|
|
516
|
+
this.reviewsElement.innerText = `(${salla.helpers.number(salla.lang.choice('pages.rating.reviews', this.reviews))})`;
|
|
517
|
+
}
|
|
518
|
+
this.translationsLoaded = true;
|
|
519
|
+
resolve();
|
|
520
|
+
});
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
initiateRating() {
|
|
524
|
+
this.host.addEventListener('click', this.handleRating.bind(this));
|
|
525
|
+
}
|
|
526
|
+
handleRating() {
|
|
527
|
+
if (!this.starsElem)
|
|
528
|
+
return;
|
|
529
|
+
let activeStars = this.starsElem.querySelectorAll('.s-rating-stars-hovered');
|
|
530
|
+
let selected = activeStars[activeStars.length - 1];
|
|
531
|
+
if (!selected)
|
|
532
|
+
return;
|
|
533
|
+
let selectedIndex = parseInt(selected.getAttribute('data-star'));
|
|
534
|
+
this.starsElem.querySelector('.rating_hidden_input').value = selectedIndex.toString();
|
|
535
|
+
this.starsElem.querySelectorAll('.s-rating-stars-btn-star')
|
|
536
|
+
.forEach((star, index) => Helper.toggleElementClassIf(star, 's-rating-stars-selected', 's-rating-stars-unselected', () => index < selectedIndex));
|
|
537
|
+
this.starsElem.querySelectorAll('[aria-pressed]').forEach(star => star.removeAttribute('aria-pressed'));
|
|
538
|
+
selected.setAttribute('aria-pressed', 'true');
|
|
539
|
+
this.selectedStar = selectedIndex;
|
|
540
|
+
this.withLabel && (this.reviewLabel = this.labels[selectedIndex - 1]);
|
|
541
|
+
}
|
|
542
|
+
triggerRatingProgrammatically(index) {
|
|
543
|
+
if (!this.starsElem)
|
|
544
|
+
return;
|
|
545
|
+
const stars = this.starsElem.querySelectorAll('.s-rating-stars-btn-star');
|
|
546
|
+
if (stars && index >= 0 && index <= stars.length) {
|
|
547
|
+
// Simulate the hovering effect
|
|
548
|
+
stars.forEach((s, i) => {
|
|
549
|
+
s.classList.toggle('s-rating-stars-hovered', i <= index);
|
|
550
|
+
});
|
|
551
|
+
// Trigger the same logic as clicking
|
|
552
|
+
this.handleRating();
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
highlightSelectedStars() {
|
|
556
|
+
let hoveredClass = 's-rating-stars-hovered', stars = this.starsElem?.querySelectorAll('.s-rating-stars-btn-star');
|
|
557
|
+
stars?.forEach((star, index) => {
|
|
558
|
+
star.addEventListener('mouseover', () => {
|
|
559
|
+
for (let i = 0; i <= index; i++) {
|
|
560
|
+
stars[i].classList.add(hoveredClass);
|
|
561
|
+
}
|
|
562
|
+
this.withLabel && (this.reviewLabel = this.labels[index]);
|
|
563
|
+
});
|
|
564
|
+
star.addEventListener('mouseout', () => {
|
|
565
|
+
star.classList.remove(hoveredClass);
|
|
566
|
+
this.withLabel && (this.reviewLabel = this.selectedStar ? this.labels[this.selectedStar - 1] : '');
|
|
567
|
+
});
|
|
568
|
+
});
|
|
569
|
+
this.starsElem?.addEventListener('mouseout', () => stars.forEach(star => star.classList.remove(hoveredClass)));
|
|
570
|
+
}
|
|
571
|
+
createStars(n) {
|
|
572
|
+
let stars = [];
|
|
573
|
+
for (let i = 0; i < 5; i++) {
|
|
574
|
+
stars.push(h("span", { class: {
|
|
575
|
+
's-rating-stars-btn-star': true,
|
|
576
|
+
['s-rating-stars-' + this.size]: true,
|
|
577
|
+
's-rating-stars-selected': i < n
|
|
578
|
+
}, innerHTML: Star }));
|
|
579
|
+
}
|
|
580
|
+
if (this.reviews > 0) {
|
|
581
|
+
stars.push(h("span", { class: "s-rating-stars-reviews", ref: el => this.reviewsElement = el }, "(", salla.helpers.number(salla.lang.choice('pages.rating.reviews', this.reviews)), ")"));
|
|
582
|
+
}
|
|
583
|
+
return stars;
|
|
584
|
+
}
|
|
585
|
+
render() {
|
|
586
|
+
return this.translationsLoaded ? (this.host.closest('.swiper-slide')?.classList.contains('swiper-slide-duplicate')
|
|
587
|
+
? ''
|
|
588
|
+
: (h(Host, null, (this.value || this.value == 0) && !this.editable ?
|
|
589
|
+
h("div", { class: "s-rating-stars-wrapper" }, this.createStars(this.value), this.withLabel && this.reviewLabel ? h("span", { class: "s-rating-stars-label" }, this.reviewLabel) : '')
|
|
590
|
+
:
|
|
591
|
+
h("div", { class: "s-rating-stars-wrapper" }, h("div", { class: "s-rating-stars-element", ref: (el) => this.starsElem = el }, h("input", { type: "hidden", class: "rating_hidden_input", name: this.name, value: "" }), [1, 2, 3, 4, 5].map(star => h("button", { class: `s-rating-stars-btn-star s-rating-stars-` + this.size, "data-star": star }, h("span", { innerHTML: Star })))), this.withLabel && this.reviewLabel ? h("span", { class: "s-rating-stars-label" }, this.reviewLabel) : '')))) : (h(Host, null));
|
|
592
|
+
}
|
|
593
|
+
componentDidLoad() {
|
|
594
|
+
this.initiateRating();
|
|
595
|
+
this.highlightSelectedStars();
|
|
596
|
+
if (this.value && this.editable) {
|
|
597
|
+
const stars = this.starsElem?.querySelectorAll('.s-rating-stars-btn-star');
|
|
598
|
+
if (stars && this.value >= 0 && this.value <= stars.length) {
|
|
599
|
+
this.triggerRatingProgrammatically(this.value - 1);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
get host() { return getElement(this); }
|
|
604
|
+
};
|
|
605
|
+
SallaRatingStars.style = sallaRatingStarsCss;
|
|
606
|
+
|
|
607
|
+
var IconStar2 = ` <svg width="18" height="17" view-box="0 0 18 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
608
|
+
<path d="M9.00045 13.6951L3.71036 16.6563L4.89186 10.71L0.440918 6.59397L6.4612 5.88017L9.00045 0.375122L11.5396 5.88017L17.5599 6.59397L13.109 10.71L14.2905 16.6563L9.00045 13.6951Z" fill="currentcolor" />
|
|
609
|
+
</svg>`;
|
|
610
|
+
|
|
611
|
+
var IconStar2Muted = ` <svg width="18" height="17" view-box="0 0 18 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
612
|
+
<path d="M9.00045 13.6951L3.71036 16.6563L4.89186 10.71L0.440918 6.59397L6.4612 5.88017L9.00045 0.375122L11.5396 5.88017L17.5599 6.59397L13.109 10.71L14.2905 16.6563L9.00045 13.6951Z" fill="#DDDDDD" />
|
|
613
|
+
</svg>`;
|
|
614
|
+
|
|
615
|
+
var IconFire2 = ` <svg width="12" height="17" view-box="0 0 12 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
616
|
+
<path d="M6 16.2501C9.10658 16.2501 11.625 13.7317 11.625 10.6251C11.625 9.976 11.4523 9.35252 11.25 8.77232C9.99998 10.0075 9.05002 10.6251 8.4 10.6251C11.3966 5.37512 9.75 3.12512 5.25 0.125122C5.625 3.87475 3.15302 5.58043 2.14634 6.52757C1.0559 7.5535 0.375 9.00977 0.375 10.6251C0.375 13.7317 2.89339 16.2501 6 16.2501ZM6.53205 2.92636C8.96333 4.98908 8.97495 6.59185 7.09725 9.88157C6.5265 10.8815 7.2486 12.1251 8.4 12.1251C8.9163 12.1251 9.43807 11.9745 9.98917 11.6789C9.52342 13.4466 7.91393 14.7501 6 14.7501C3.72182 14.7501 1.875 12.9033 1.875 10.6251C1.875 9.47072 2.34959 8.39582 3.17419 7.62002C3.2687 7.53115 3.74812 7.1062 3.76858 7.08782C4.08646 6.8017 4.34835 6.54985 4.60718 6.2727C5.52998 5.28461 6.19283 4.18735 6.53205 2.92636Z" fill="currentcolor" />
|
|
617
|
+
</svg>`;
|
|
618
|
+
|
|
619
|
+
const sallaReviewCardCss = ":host{display:block}";
|
|
620
|
+
|
|
621
|
+
const SallaReviewCard = class {
|
|
622
|
+
constructor(hostRef) {
|
|
623
|
+
registerInstance(this, hostRef);
|
|
624
|
+
this.currentSlide = 0;
|
|
625
|
+
this.showPurchaseCount = false;
|
|
626
|
+
this.startPoint = { x: 0, y: 0 };
|
|
627
|
+
this.isSwiping = false;
|
|
628
|
+
this.isRTL = "rtl";
|
|
629
|
+
this.handlePointerDown = (e) => {
|
|
630
|
+
// Only handle primary pointer (first touch/mouse)
|
|
631
|
+
if (!e.isPrimary)
|
|
632
|
+
return;
|
|
633
|
+
this.sliderElement?.setPointerCapture(e.pointerId);
|
|
634
|
+
this.startSwipe(e.clientX, e.clientY);
|
|
635
|
+
e.preventDefault();
|
|
636
|
+
};
|
|
637
|
+
this.handlePointerMove = (e) => {
|
|
638
|
+
if (!this.isSwiping || !e.isPrimary)
|
|
639
|
+
return;
|
|
640
|
+
e.preventDefault();
|
|
641
|
+
};
|
|
642
|
+
this.handlePointerUp = (e) => {
|
|
643
|
+
if (!this.isSwiping || !e.isPrimary)
|
|
644
|
+
return;
|
|
645
|
+
this.sliderElement?.releasePointerCapture(e.pointerId);
|
|
646
|
+
this.endSwipe(e.clientX, e.clientY);
|
|
647
|
+
};
|
|
648
|
+
this.handlePointerCancel = (e) => {
|
|
649
|
+
if (!this.isSwiping || !e.isPrimary)
|
|
650
|
+
return;
|
|
651
|
+
this.sliderElement?.releasePointerCapture(e.pointerId);
|
|
652
|
+
this.isSwiping = false;
|
|
653
|
+
};
|
|
654
|
+
this.goToSlide = (index) => {
|
|
655
|
+
this.currentSlide = Math.max(0, Math.min(index, this.images.length - 1));
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
async componentDidLoad() {
|
|
659
|
+
await salla.onReady();
|
|
660
|
+
this.showPurchaseCount = !!salla.config.get('store.settings.product.total_sold_enabled', false);
|
|
661
|
+
this.isRTL = salla.config.get('theme.is_rtl', true);
|
|
662
|
+
this.purchasedCount = salla.lang.getWithDefault('blocks.home.reviews.purchased_count', this.isRTL ? ` تم شراءه ${this.review.product?.sold_quantity} مرة`
|
|
663
|
+
: `Purchased ${this.review.product.sold_quantity} times`, { count: this.review.product?.sold_quantity });
|
|
664
|
+
this.initializeSlider();
|
|
665
|
+
}
|
|
666
|
+
disconnectedCallback() {
|
|
667
|
+
this.removeEventListeners();
|
|
668
|
+
}
|
|
669
|
+
get images() {
|
|
670
|
+
const { review } = this;
|
|
671
|
+
return review?.images?.length > 1
|
|
672
|
+
? review.images.map((image, idx) => ({ url: image, alt: '', id: idx }))
|
|
673
|
+
: review?.product?.images || [];
|
|
674
|
+
}
|
|
675
|
+
get hasMultipleImages() {
|
|
676
|
+
return this.images.length > 1;
|
|
677
|
+
}
|
|
678
|
+
get slideTransform() {
|
|
679
|
+
const direction = this.isRTL ? 1 : -1;
|
|
680
|
+
return `translateX(${this.currentSlide * 100 * direction}%)`;
|
|
681
|
+
}
|
|
682
|
+
initializeSlider() {
|
|
683
|
+
if (!this.hasMultipleImages)
|
|
684
|
+
return;
|
|
685
|
+
this.sliderElement = this.el.querySelector(".s-review-card-slider-container");
|
|
686
|
+
if (!this.sliderElement)
|
|
687
|
+
return;
|
|
688
|
+
// Enable pointer events and set touch-action
|
|
689
|
+
this.sliderElement.style.touchAction = 'pan-y pinch-zoom';
|
|
690
|
+
this.addEventListeners();
|
|
691
|
+
}
|
|
692
|
+
addEventListeners() {
|
|
693
|
+
if (!this.sliderElement)
|
|
694
|
+
return;
|
|
695
|
+
this.sliderElement.addEventListener("pointerdown", this.handlePointerDown, { passive: false });
|
|
696
|
+
this.sliderElement.addEventListener("pointermove", this.handlePointerMove, { passive: false });
|
|
697
|
+
this.sliderElement.addEventListener("pointerup", this.handlePointerUp, { passive: true });
|
|
698
|
+
this.sliderElement.addEventListener("pointercancel", this.handlePointerCancel, { passive: true });
|
|
699
|
+
}
|
|
700
|
+
removeEventListeners() {
|
|
701
|
+
if (!this.sliderElement)
|
|
702
|
+
return;
|
|
703
|
+
this.sliderElement.removeEventListener("pointerdown", this.handlePointerDown);
|
|
704
|
+
this.sliderElement.removeEventListener("pointermove", this.handlePointerMove);
|
|
705
|
+
this.sliderElement.removeEventListener("pointerup", this.handlePointerUp);
|
|
706
|
+
this.sliderElement.removeEventListener("pointercancel", this.handlePointerCancel);
|
|
707
|
+
}
|
|
708
|
+
startSwipe(x, y) {
|
|
709
|
+
this.startPoint = { x, y };
|
|
710
|
+
this.isSwiping = true;
|
|
711
|
+
}
|
|
712
|
+
componentDidRender() {
|
|
713
|
+
this.removeEventListeners();
|
|
714
|
+
this.addEventListeners();
|
|
715
|
+
}
|
|
716
|
+
endSwipe(x, y) {
|
|
717
|
+
this.isSwiping = false;
|
|
718
|
+
const dx = x - this.startPoint.x;
|
|
719
|
+
const dy = y - this.startPoint.y;
|
|
720
|
+
this.processSwipe(dx, dy);
|
|
721
|
+
}
|
|
722
|
+
processSwipe(dx, dy) {
|
|
723
|
+
const MIN_SWIPE_DISTANCE = 10;
|
|
724
|
+
if (Math.abs(dx) < MIN_SWIPE_DISTANCE || Math.abs(dy) > Math.abs(dx))
|
|
725
|
+
return;
|
|
726
|
+
const isLeftSwipe = dx < 0;
|
|
727
|
+
const shouldGoNext = this.isRTL ? !isLeftSwipe : isLeftSwipe;
|
|
728
|
+
if (shouldGoNext) {
|
|
729
|
+
this.goToNextSlide();
|
|
730
|
+
}
|
|
731
|
+
else {
|
|
732
|
+
this.goToPrevSlide();
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
goToNextSlide() {
|
|
736
|
+
if (this.currentSlide < this.images.length - 1) {
|
|
737
|
+
this.currentSlide++;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
goToPrevSlide() {
|
|
741
|
+
if (this.currentSlide > 0) {
|
|
742
|
+
this.currentSlide--;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
renderStars() {
|
|
746
|
+
return Array(5)
|
|
747
|
+
.fill(null)
|
|
748
|
+
.map((_, index) => h("span", { key: index, innerHTML: this.review.stars >= index + 1 ? IconStar2 : IconStar2Muted }));
|
|
749
|
+
}
|
|
750
|
+
renderDots() {
|
|
751
|
+
return this.images.map(({ url }, index) => (h("button", { key: url || index, type: "button", class: `s-review-card-slider-dot ${this.currentSlide === index ? "active" : ""}`, onClick: () => this.goToSlide(index), "aria-label": `Go to slide ${index + 1}`, onPointerDown: () => this.goToSlide(index) })));
|
|
752
|
+
}
|
|
753
|
+
renderSlider() {
|
|
754
|
+
if (!this.hasMultipleImages)
|
|
755
|
+
return null;
|
|
756
|
+
return (h("div", { class: "s-review-card-slider-container" }, h("div", { class: "s-review-card-slides", style: { transform: this.slideTransform } }, this.images.map((image) => (h("div", { key: image?.id, class: "s-review-card-slider-slide" }, h("img", { src: image.url, alt: image.alt || "Product image", width: 275, height: 275, loading: "lazy", draggable: false }))))), h("div", { class: "s-review-card-slider-dots" }, this.renderDots())));
|
|
757
|
+
}
|
|
758
|
+
renderSingleImage() {
|
|
759
|
+
const image = this.review?.product?.image;
|
|
760
|
+
if (!image || this.hasMultipleImages)
|
|
761
|
+
return null;
|
|
762
|
+
return (h("img", { src: image.url, alt: image.alt || "Product image", class: "s-review-card-image", width: 275, height: 275, loading: "lazy", decoding: "async", draggable: false }));
|
|
763
|
+
}
|
|
764
|
+
renderHeader() {
|
|
765
|
+
return (h("div", { class: "s-review-card-header" }, h("div", { class: "s-review-card-reviewer-name" }, h("p", null, this.review?.name), this.review?.has_order && h("span", { class: "s-review-card-verified-icon", innerHTML: iconCheck })), h("div", { class: "s-review-card-stars" }, this.renderStars())));
|
|
766
|
+
}
|
|
767
|
+
renderProductInfo() {
|
|
768
|
+
const product = this.review?.product;
|
|
769
|
+
if (!product)
|
|
770
|
+
return null;
|
|
771
|
+
return (h("a", { href: this.review?.product?.url, class: "s-review-card-product-container" }, h("img", { alt: product.image?.alt || "Product", src: product.image?.url, class: "s-review-card-product-image", width: 60, height: 60, loading: "lazy", decoding: "async", draggable: false }), h("div", { class: "s-review-card-product-details" }, h("p", { class: "s-review-card-product-details-name" }, product.name), this.showPurchaseCount ? h("p", { class: "s-review-card-product-details-purchase-count" }, h("span", { innerHTML: IconFire2 }), this.purchasedCount) : null)));
|
|
772
|
+
}
|
|
773
|
+
render() {
|
|
774
|
+
return h("div", { key: '251b76f2f2935ab7be248f589badaebe0f297cb2', class: "s-review-card-container" }, this.renderSlider(), this.renderSingleImage(), renderDivider(), h("div", { key: '2621097a4115e278b1b99d46b6be22341a7ea064', class: "s-review-card-content" }, this.renderHeader(), h("p", { key: 'cd641970280867954f431fc3a2812080ebe32bd9', class: "s-review-card-review-content", innerHTML: this.review?.content }), renderDivider(), this.renderProductInfo()));
|
|
775
|
+
}
|
|
776
|
+
get el() { return getElement(this); }
|
|
777
|
+
};
|
|
778
|
+
const renderDivider = (className) => (h("div", { class: `s-review-card-divider ${""}` }));
|
|
779
|
+
SallaReviewCard.style = sallaReviewCardCss;
|
|
780
|
+
|
|
781
|
+
var IconQuoteOpen = `<!-- Generated by IcoMoon.io -->
|
|
782
|
+
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
|
783
|
+
<title>quote-open</title>
|
|
784
|
+
<path d="M8 12v-5.333c0-0.737-0.596-1.333-1.333-1.333-3.676 0-6.667 2.991-6.667 6.667v8c0 3.676 2.991 6.667 6.667 6.667h1.333c3.676 0 6.667-2.991 6.667-6.667v-1.333c0-3.676-2.991-6.667-6.667-6.667zM12 20c0 2.205-1.795 4-4 4h-1.333c-2.205 0-4-1.795-4-4v-8c0-1.739 1.115-3.221 2.667-3.772v5.105c0 0.737 0.596 1.333 1.333 1.333h1.333c2.205 0 4 1.795 4 4zM25.333 12v-5.333c0-0.737-0.596-1.333-1.333-1.333-3.676 0-6.667 2.991-6.667 6.667v8c0 3.676 2.991 6.667 6.667 6.667h1.333c3.676 0 6.667-2.991 6.667-6.667v-1.333c0-3.676-2.991-6.667-6.667-6.667zM29.333 20c0 2.205-1.795 4-4 4h-1.333c-2.205 0-4-1.795-4-4v-8c0-1.739 1.115-3.221 2.667-3.772v5.105c0 0.737 0.596 1.333 1.333 1.333h1.333c2.205 0 4 1.795 4 4z"></path>
|
|
785
|
+
</svg>
|
|
786
|
+
`;
|
|
787
|
+
|
|
788
|
+
const sallaReviewsCss = "";
|
|
789
|
+
|
|
790
|
+
const SallaReviews = class {
|
|
791
|
+
constructor(hostRef) {
|
|
792
|
+
registerInstance(this, hostRef);
|
|
793
|
+
/**
|
|
794
|
+
* Defines the maximum number of reviews to retrieve from the API.
|
|
795
|
+
*
|
|
796
|
+
* @type {number}
|
|
797
|
+
* @default 5
|
|
798
|
+
*/
|
|
799
|
+
this.limit = 5;
|
|
800
|
+
/**
|
|
801
|
+
* Specifies the type of reviews to fetch.
|
|
802
|
+
* Available options:
|
|
803
|
+
* - "all": Fetches reviews from all sources.
|
|
804
|
+
* - "store": Fetches reviews specific to the store.
|
|
805
|
+
* - "products": Fetches reviews specific to products.
|
|
806
|
+
*
|
|
807
|
+
* @type {ReviewType}
|
|
808
|
+
* @default store
|
|
809
|
+
*/
|
|
810
|
+
this.type = "store";
|
|
811
|
+
/**
|
|
812
|
+
* Specifies the sorting criteria for the fetched reviews.
|
|
813
|
+
* Available options:
|
|
814
|
+
* - "top_rating": Sorts reviews based on top ratings.
|
|
815
|
+
* - "random": Sorts reviews randomly.
|
|
816
|
+
* - "latest": Sorts reviews based on the latest ones (default).
|
|
817
|
+
*
|
|
818
|
+
* @type {SortingOption}
|
|
819
|
+
* @default latest
|
|
820
|
+
*/
|
|
821
|
+
this.sort = "latest";
|
|
822
|
+
/**
|
|
823
|
+
* Specifies whether to hide customer information in the component.
|
|
824
|
+
* When set to true, customer information will be hidden.
|
|
825
|
+
* Defaults to false, meaning customer information will be displayed.
|
|
826
|
+
*/
|
|
827
|
+
this.hideCustomerInfo = false;
|
|
828
|
+
this.reviews = [];
|
|
829
|
+
this.showReviews = false;
|
|
830
|
+
this.testimonialText = salla.lang.get('blocks.home.testimonials');
|
|
831
|
+
this.displayAllLinkText = salla.lang.get('blocks.home.display_all');
|
|
832
|
+
this.displayAllURL = null;
|
|
833
|
+
this.source = this.source;
|
|
834
|
+
salla.onReady(() => {
|
|
835
|
+
this.displayAllURL = salla.url.get('testimonials');
|
|
836
|
+
this.isRTL = salla.config.get('theme.is_rtl', true);
|
|
837
|
+
});
|
|
838
|
+
salla.lang.onLoaded(() => {
|
|
839
|
+
this.testimonialText = salla.lang.get('blocks.home.testimonials');
|
|
840
|
+
this.displayAllLinkText = salla.lang.get('blocks.home.display_all');
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
fetchReviews() {
|
|
844
|
+
if (this.source === 'json') {
|
|
845
|
+
return Promise.resolve(JSON.parse(this.sourceValue));
|
|
846
|
+
}
|
|
847
|
+
const isJsonEncoded = ['products', 'categories'].includes(this.source);
|
|
848
|
+
const params = {
|
|
849
|
+
limit: this.limit,
|
|
850
|
+
source: this.source,
|
|
851
|
+
items: isJsonEncoded ? JSON.parse(this.sourceValue) : this.sourceValue,
|
|
852
|
+
sort: this.sort,
|
|
853
|
+
type: this.type,
|
|
854
|
+
hide_customer_info: this.hideCustomerInfo ? 1 : 0
|
|
855
|
+
};
|
|
856
|
+
return salla.api.request('reviews', { params }, 'get');
|
|
857
|
+
}
|
|
858
|
+
componentWillLoad() {
|
|
859
|
+
return (new Promise(resolve => salla.onReady(resolve)))
|
|
860
|
+
.then(() => this.fetchReviews())
|
|
861
|
+
.then((resp) => resp.data || [])
|
|
862
|
+
.then(reviews => {
|
|
863
|
+
if (reviews.length) {
|
|
864
|
+
this.reviews = reviews;
|
|
865
|
+
this.showReviews = true;
|
|
866
|
+
Helper.generateReviewSchema(this.reviews);
|
|
867
|
+
}
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
render() {
|
|
871
|
+
return (h("div", { key: 'aa4937182950d1b0fbcb67aa577d6fb3c413af79', class: "s-reviews-container" }, h("div", { key: 'dbfb22a037c29a0bf88b73481aa8ea4988ef819a', class: "s-reviews-header-wrapper" }, h("h1", { key: '7b874af56f8933777942d829d1311cd0854e5a12', class: "s-reviews-header" }, this.testimonialText), !!this.displayAllLink ? (h("a", { href: this.displayAllURL, class: "s-reviews-display-all" }, this.displayAllLinkText, h("span", { class: "s-reviews-display-all-icon", innerHTML: arrowLeft }))) : null), h("salla-slider", { key: '0050aac87a3aadc858aa352ba7ac82158bb586de', centered: true, "slides-per-view": 1, type: "testimonials", class: "s-reviews-testimonials-slider", "controls-outer": true, "auto-play": true, id: `testimonials-${this.source}-slider` }, h("div", { key: '7d1801d35aeba19fa913609202128b6866ca7118', slot: "items" }, this.reviews.map((item, index) => (h("div", { key: index, class: "s-reviews-swiper-slide" }, h("div", { class: "s-reviews-testimonial" }, h("div", { class: "s-reviews-testimonial__inner" }, h("div", { class: "s-reviews-testimonial__avatar" }, h("img", { src: 'images/s-empty.png', "data-src": item.avatar, alt: item.name ? item.name : 'testimonial-' + index, class: "lazy" })), h("div", { class: "s-reviews-testimonial__text" }, h("p", { innerHTML: item.content }), h("div", { class: "s-reviews-testimonial__name_wrapper" }, h("div", { class: "s-reviews-testimonial__info" }, item.name && h("h2", null, `${item.name}`)), h("div", { class: "s-reviews-testimonial__rating" }, h("salla-rating-stars", { size: "small", value: item.stars })))), h("span", { class: "s-reviews-testimonial__icon", innerHTML: IconQuoteOpen }))))))))));
|
|
872
|
+
}
|
|
873
|
+
};
|
|
874
|
+
SallaReviews.style = sallaReviewsCss;
|
|
875
|
+
|
|
876
|
+
var now_1;
|
|
877
|
+
var hasRequiredNow;
|
|
878
|
+
|
|
879
|
+
function requireNow () {
|
|
880
|
+
if (hasRequiredNow) return now_1;
|
|
881
|
+
hasRequiredNow = 1;
|
|
882
|
+
var root = require_root();
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
* Gets the timestamp of the number of milliseconds that have elapsed since
|
|
886
|
+
* the Unix epoch (1 January 1970 00:00:00 UTC).
|
|
887
|
+
*
|
|
888
|
+
* @static
|
|
889
|
+
* @memberOf _
|
|
890
|
+
* @since 2.4.0
|
|
891
|
+
* @category Date
|
|
892
|
+
* @returns {number} Returns the timestamp.
|
|
893
|
+
* @example
|
|
894
|
+
*
|
|
895
|
+
* _.defer(function(stamp) {
|
|
896
|
+
* console.log(_.now() - stamp);
|
|
897
|
+
* }, _.now());
|
|
898
|
+
* // => Logs the number of milliseconds it took for the deferred invocation.
|
|
899
|
+
*/
|
|
900
|
+
var now = function() {
|
|
901
|
+
return root.Date.now();
|
|
902
|
+
};
|
|
903
|
+
|
|
904
|
+
now_1 = now;
|
|
905
|
+
return now_1;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
/** Used to match a single whitespace character. */
|
|
909
|
+
|
|
910
|
+
var _trimmedEndIndex;
|
|
911
|
+
var hasRequired_trimmedEndIndex;
|
|
912
|
+
|
|
913
|
+
function require_trimmedEndIndex () {
|
|
914
|
+
if (hasRequired_trimmedEndIndex) return _trimmedEndIndex;
|
|
915
|
+
hasRequired_trimmedEndIndex = 1;
|
|
916
|
+
var reWhitespace = /\s/;
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
|
|
920
|
+
* character of `string`.
|
|
921
|
+
*
|
|
922
|
+
* @private
|
|
923
|
+
* @param {string} string The string to inspect.
|
|
924
|
+
* @returns {number} Returns the index of the last non-whitespace character.
|
|
925
|
+
*/
|
|
926
|
+
function trimmedEndIndex(string) {
|
|
927
|
+
var index = string.length;
|
|
928
|
+
|
|
929
|
+
while (index-- && reWhitespace.test(string.charAt(index))) {}
|
|
930
|
+
return index;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
_trimmedEndIndex = trimmedEndIndex;
|
|
934
|
+
return _trimmedEndIndex;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
var _baseTrim;
|
|
938
|
+
var hasRequired_baseTrim;
|
|
939
|
+
|
|
940
|
+
function require_baseTrim () {
|
|
941
|
+
if (hasRequired_baseTrim) return _baseTrim;
|
|
942
|
+
hasRequired_baseTrim = 1;
|
|
943
|
+
var trimmedEndIndex = require_trimmedEndIndex();
|
|
944
|
+
|
|
945
|
+
/** Used to match leading whitespace. */
|
|
946
|
+
var reTrimStart = /^\s+/;
|
|
947
|
+
|
|
948
|
+
/**
|
|
949
|
+
* The base implementation of `_.trim`.
|
|
950
|
+
*
|
|
951
|
+
* @private
|
|
952
|
+
* @param {string} string The string to trim.
|
|
953
|
+
* @returns {string} Returns the trimmed string.
|
|
954
|
+
*/
|
|
955
|
+
function baseTrim(string) {
|
|
956
|
+
return string
|
|
957
|
+
? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')
|
|
958
|
+
: string;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
_baseTrim = baseTrim;
|
|
962
|
+
return _baseTrim;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
var toNumber_1;
|
|
966
|
+
var hasRequiredToNumber;
|
|
967
|
+
|
|
968
|
+
function requireToNumber () {
|
|
969
|
+
if (hasRequiredToNumber) return toNumber_1;
|
|
970
|
+
hasRequiredToNumber = 1;
|
|
971
|
+
var baseTrim = require_baseTrim(),
|
|
972
|
+
isObject = requireIsObject(),
|
|
973
|
+
isSymbol = requireIsSymbol();
|
|
974
|
+
|
|
975
|
+
/** Used as references for various `Number` constants. */
|
|
976
|
+
var NAN = 0 / 0;
|
|
977
|
+
|
|
978
|
+
/** Used to detect bad signed hexadecimal string values. */
|
|
979
|
+
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
|
|
980
|
+
|
|
981
|
+
/** Used to detect binary string values. */
|
|
982
|
+
var reIsBinary = /^0b[01]+$/i;
|
|
983
|
+
|
|
984
|
+
/** Used to detect octal string values. */
|
|
985
|
+
var reIsOctal = /^0o[0-7]+$/i;
|
|
986
|
+
|
|
987
|
+
/** Built-in method references without a dependency on `root`. */
|
|
988
|
+
var freeParseInt = parseInt;
|
|
989
|
+
|
|
990
|
+
/**
|
|
991
|
+
* Converts `value` to a number.
|
|
992
|
+
*
|
|
993
|
+
* @static
|
|
994
|
+
* @memberOf _
|
|
995
|
+
* @since 4.0.0
|
|
996
|
+
* @category Lang
|
|
997
|
+
* @param {*} value The value to process.
|
|
998
|
+
* @returns {number} Returns the number.
|
|
999
|
+
* @example
|
|
1000
|
+
*
|
|
1001
|
+
* _.toNumber(3.2);
|
|
1002
|
+
* // => 3.2
|
|
1003
|
+
*
|
|
1004
|
+
* _.toNumber(Number.MIN_VALUE);
|
|
1005
|
+
* // => 5e-324
|
|
1006
|
+
*
|
|
1007
|
+
* _.toNumber(Infinity);
|
|
1008
|
+
* // => Infinity
|
|
1009
|
+
*
|
|
1010
|
+
* _.toNumber('3.2');
|
|
1011
|
+
* // => 3.2
|
|
1012
|
+
*/
|
|
1013
|
+
function toNumber(value) {
|
|
1014
|
+
if (typeof value == 'number') {
|
|
1015
|
+
return value;
|
|
1016
|
+
}
|
|
1017
|
+
if (isSymbol(value)) {
|
|
1018
|
+
return NAN;
|
|
1019
|
+
}
|
|
1020
|
+
if (isObject(value)) {
|
|
1021
|
+
var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
|
|
1022
|
+
value = isObject(other) ? (other + '') : other;
|
|
1023
|
+
}
|
|
1024
|
+
if (typeof value != 'string') {
|
|
1025
|
+
return value === 0 ? value : +value;
|
|
1026
|
+
}
|
|
1027
|
+
value = baseTrim(value);
|
|
1028
|
+
var isBinary = reIsBinary.test(value);
|
|
1029
|
+
return (isBinary || reIsOctal.test(value))
|
|
1030
|
+
? freeParseInt(value.slice(2), isBinary ? 2 : 8)
|
|
1031
|
+
: (reIsBadHex.test(value) ? NAN : +value);
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
toNumber_1 = toNumber;
|
|
1035
|
+
return toNumber_1;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
var debounce_1;
|
|
1039
|
+
var hasRequiredDebounce;
|
|
1040
|
+
|
|
1041
|
+
function requireDebounce () {
|
|
1042
|
+
if (hasRequiredDebounce) return debounce_1;
|
|
1043
|
+
hasRequiredDebounce = 1;
|
|
1044
|
+
var isObject = requireIsObject(),
|
|
1045
|
+
now = requireNow(),
|
|
1046
|
+
toNumber = requireToNumber();
|
|
1047
|
+
|
|
1048
|
+
/** Error message constants. */
|
|
1049
|
+
var FUNC_ERROR_TEXT = 'Expected a function';
|
|
1050
|
+
|
|
1051
|
+
/* Built-in method references for those with the same name as other `lodash` methods. */
|
|
1052
|
+
var nativeMax = Math.max,
|
|
1053
|
+
nativeMin = Math.min;
|
|
1054
|
+
|
|
1055
|
+
/**
|
|
1056
|
+
* Creates a debounced function that delays invoking `func` until after `wait`
|
|
1057
|
+
* milliseconds have elapsed since the last time the debounced function was
|
|
1058
|
+
* invoked. The debounced function comes with a `cancel` method to cancel
|
|
1059
|
+
* delayed `func` invocations and a `flush` method to immediately invoke them.
|
|
1060
|
+
* Provide `options` to indicate whether `func` should be invoked on the
|
|
1061
|
+
* leading and/or trailing edge of the `wait` timeout. The `func` is invoked
|
|
1062
|
+
* with the last arguments provided to the debounced function. Subsequent
|
|
1063
|
+
* calls to the debounced function return the result of the last `func`
|
|
1064
|
+
* invocation.
|
|
1065
|
+
*
|
|
1066
|
+
* **Note:** If `leading` and `trailing` options are `true`, `func` is
|
|
1067
|
+
* invoked on the trailing edge of the timeout only if the debounced function
|
|
1068
|
+
* is invoked more than once during the `wait` timeout.
|
|
1069
|
+
*
|
|
1070
|
+
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
|
|
1071
|
+
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
|
|
1072
|
+
*
|
|
1073
|
+
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
|
|
1074
|
+
* for details over the differences between `_.debounce` and `_.throttle`.
|
|
1075
|
+
*
|
|
1076
|
+
* @static
|
|
1077
|
+
* @memberOf _
|
|
1078
|
+
* @since 0.1.0
|
|
1079
|
+
* @category Function
|
|
1080
|
+
* @param {Function} func The function to debounce.
|
|
1081
|
+
* @param {number} [wait=0] The number of milliseconds to delay.
|
|
1082
|
+
* @param {Object} [options={}] The options object.
|
|
1083
|
+
* @param {boolean} [options.leading=false]
|
|
1084
|
+
* Specify invoking on the leading edge of the timeout.
|
|
1085
|
+
* @param {number} [options.maxWait]
|
|
1086
|
+
* The maximum time `func` is allowed to be delayed before it's invoked.
|
|
1087
|
+
* @param {boolean} [options.trailing=true]
|
|
1088
|
+
* Specify invoking on the trailing edge of the timeout.
|
|
1089
|
+
* @returns {Function} Returns the new debounced function.
|
|
1090
|
+
* @example
|
|
1091
|
+
*
|
|
1092
|
+
* // Avoid costly calculations while the window size is in flux.
|
|
1093
|
+
* jQuery(window).on('resize', _.debounce(calculateLayout, 150));
|
|
1094
|
+
*
|
|
1095
|
+
* // Invoke `sendMail` when clicked, debouncing subsequent calls.
|
|
1096
|
+
* jQuery(element).on('click', _.debounce(sendMail, 300, {
|
|
1097
|
+
* 'leading': true,
|
|
1098
|
+
* 'trailing': false
|
|
1099
|
+
* }));
|
|
1100
|
+
*
|
|
1101
|
+
* // Ensure `batchLog` is invoked once after 1 second of debounced calls.
|
|
1102
|
+
* var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
|
|
1103
|
+
* var source = new EventSource('/stream');
|
|
1104
|
+
* jQuery(source).on('message', debounced);
|
|
1105
|
+
*
|
|
1106
|
+
* // Cancel the trailing debounced invocation.
|
|
1107
|
+
* jQuery(window).on('popstate', debounced.cancel);
|
|
1108
|
+
*/
|
|
1109
|
+
function debounce(func, wait, options) {
|
|
1110
|
+
var lastArgs,
|
|
1111
|
+
lastThis,
|
|
1112
|
+
maxWait,
|
|
1113
|
+
result,
|
|
1114
|
+
timerId,
|
|
1115
|
+
lastCallTime,
|
|
1116
|
+
lastInvokeTime = 0,
|
|
1117
|
+
leading = false,
|
|
1118
|
+
maxing = false,
|
|
1119
|
+
trailing = true;
|
|
1120
|
+
|
|
1121
|
+
if (typeof func != 'function') {
|
|
1122
|
+
throw new TypeError(FUNC_ERROR_TEXT);
|
|
1123
|
+
}
|
|
1124
|
+
wait = toNumber(wait) || 0;
|
|
1125
|
+
if (isObject(options)) {
|
|
1126
|
+
leading = !!options.leading;
|
|
1127
|
+
maxing = 'maxWait' in options;
|
|
1128
|
+
maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
|
|
1129
|
+
trailing = 'trailing' in options ? !!options.trailing : trailing;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
function invokeFunc(time) {
|
|
1133
|
+
var args = lastArgs,
|
|
1134
|
+
thisArg = lastThis;
|
|
1135
|
+
|
|
1136
|
+
lastArgs = lastThis = undefined;
|
|
1137
|
+
lastInvokeTime = time;
|
|
1138
|
+
result = func.apply(thisArg, args);
|
|
1139
|
+
return result;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
function leadingEdge(time) {
|
|
1143
|
+
// Reset any `maxWait` timer.
|
|
1144
|
+
lastInvokeTime = time;
|
|
1145
|
+
// Start the timer for the trailing edge.
|
|
1146
|
+
timerId = setTimeout(timerExpired, wait);
|
|
1147
|
+
// Invoke the leading edge.
|
|
1148
|
+
return leading ? invokeFunc(time) : result;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
function remainingWait(time) {
|
|
1152
|
+
var timeSinceLastCall = time - lastCallTime,
|
|
1153
|
+
timeSinceLastInvoke = time - lastInvokeTime,
|
|
1154
|
+
timeWaiting = wait - timeSinceLastCall;
|
|
1155
|
+
|
|
1156
|
+
return maxing
|
|
1157
|
+
? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke)
|
|
1158
|
+
: timeWaiting;
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
function shouldInvoke(time) {
|
|
1162
|
+
var timeSinceLastCall = time - lastCallTime,
|
|
1163
|
+
timeSinceLastInvoke = time - lastInvokeTime;
|
|
1164
|
+
|
|
1165
|
+
// Either this is the first call, activity has stopped and we're at the
|
|
1166
|
+
// trailing edge, the system time has gone backwards and we're treating
|
|
1167
|
+
// it as the trailing edge, or we've hit the `maxWait` limit.
|
|
1168
|
+
return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
|
|
1169
|
+
(timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
function timerExpired() {
|
|
1173
|
+
var time = now();
|
|
1174
|
+
if (shouldInvoke(time)) {
|
|
1175
|
+
return trailingEdge(time);
|
|
1176
|
+
}
|
|
1177
|
+
// Restart the timer.
|
|
1178
|
+
timerId = setTimeout(timerExpired, remainingWait(time));
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
function trailingEdge(time) {
|
|
1182
|
+
timerId = undefined;
|
|
1183
|
+
|
|
1184
|
+
// Only invoke if we have `lastArgs` which means `func` has been
|
|
1185
|
+
// debounced at least once.
|
|
1186
|
+
if (trailing && lastArgs) {
|
|
1187
|
+
return invokeFunc(time);
|
|
1188
|
+
}
|
|
1189
|
+
lastArgs = lastThis = undefined;
|
|
1190
|
+
return result;
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
function cancel() {
|
|
1194
|
+
if (timerId !== undefined) {
|
|
1195
|
+
clearTimeout(timerId);
|
|
1196
|
+
}
|
|
1197
|
+
lastInvokeTime = 0;
|
|
1198
|
+
lastArgs = lastCallTime = lastThis = timerId = undefined;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
function flush() {
|
|
1202
|
+
return timerId === undefined ? result : trailingEdge(now());
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
function debounced() {
|
|
1206
|
+
var time = now(),
|
|
1207
|
+
isInvoking = shouldInvoke(time);
|
|
1208
|
+
|
|
1209
|
+
lastArgs = arguments;
|
|
1210
|
+
lastThis = this;
|
|
1211
|
+
lastCallTime = time;
|
|
1212
|
+
|
|
1213
|
+
if (isInvoking) {
|
|
1214
|
+
if (timerId === undefined) {
|
|
1215
|
+
return leadingEdge(lastCallTime);
|
|
1216
|
+
}
|
|
1217
|
+
if (maxing) {
|
|
1218
|
+
// Handle invocations in a tight loop.
|
|
1219
|
+
clearTimeout(timerId);
|
|
1220
|
+
timerId = setTimeout(timerExpired, wait);
|
|
1221
|
+
return invokeFunc(lastCallTime);
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
if (timerId === undefined) {
|
|
1225
|
+
timerId = setTimeout(timerExpired, wait);
|
|
1226
|
+
}
|
|
1227
|
+
return result;
|
|
1228
|
+
}
|
|
1229
|
+
debounced.cancel = cancel;
|
|
1230
|
+
debounced.flush = flush;
|
|
1231
|
+
return debounced;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
debounce_1 = debounce;
|
|
1235
|
+
return debounce_1;
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
var throttle_1;
|
|
1239
|
+
var hasRequiredThrottle;
|
|
1240
|
+
|
|
1241
|
+
function requireThrottle () {
|
|
1242
|
+
if (hasRequiredThrottle) return throttle_1;
|
|
1243
|
+
hasRequiredThrottle = 1;
|
|
1244
|
+
var debounce = requireDebounce(),
|
|
1245
|
+
isObject = requireIsObject();
|
|
1246
|
+
|
|
1247
|
+
/** Error message constants. */
|
|
1248
|
+
var FUNC_ERROR_TEXT = 'Expected a function';
|
|
1249
|
+
|
|
1250
|
+
/**
|
|
1251
|
+
* Creates a throttled function that only invokes `func` at most once per
|
|
1252
|
+
* every `wait` milliseconds. The throttled function comes with a `cancel`
|
|
1253
|
+
* method to cancel delayed `func` invocations and a `flush` method to
|
|
1254
|
+
* immediately invoke them. Provide `options` to indicate whether `func`
|
|
1255
|
+
* should be invoked on the leading and/or trailing edge of the `wait`
|
|
1256
|
+
* timeout. The `func` is invoked with the last arguments provided to the
|
|
1257
|
+
* throttled function. Subsequent calls to the throttled function return the
|
|
1258
|
+
* result of the last `func` invocation.
|
|
1259
|
+
*
|
|
1260
|
+
* **Note:** If `leading` and `trailing` options are `true`, `func` is
|
|
1261
|
+
* invoked on the trailing edge of the timeout only if the throttled function
|
|
1262
|
+
* is invoked more than once during the `wait` timeout.
|
|
1263
|
+
*
|
|
1264
|
+
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
|
|
1265
|
+
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
|
|
1266
|
+
*
|
|
1267
|
+
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
|
|
1268
|
+
* for details over the differences between `_.throttle` and `_.debounce`.
|
|
1269
|
+
*
|
|
1270
|
+
* @static
|
|
1271
|
+
* @memberOf _
|
|
1272
|
+
* @since 0.1.0
|
|
1273
|
+
* @category Function
|
|
1274
|
+
* @param {Function} func The function to throttle.
|
|
1275
|
+
* @param {number} [wait=0] The number of milliseconds to throttle invocations to.
|
|
1276
|
+
* @param {Object} [options={}] The options object.
|
|
1277
|
+
* @param {boolean} [options.leading=true]
|
|
1278
|
+
* Specify invoking on the leading edge of the timeout.
|
|
1279
|
+
* @param {boolean} [options.trailing=true]
|
|
1280
|
+
* Specify invoking on the trailing edge of the timeout.
|
|
1281
|
+
* @returns {Function} Returns the new throttled function.
|
|
1282
|
+
* @example
|
|
1283
|
+
*
|
|
1284
|
+
* // Avoid excessively updating the position while scrolling.
|
|
1285
|
+
* jQuery(window).on('scroll', _.throttle(updatePosition, 100));
|
|
1286
|
+
*
|
|
1287
|
+
* // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
|
|
1288
|
+
* var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
|
|
1289
|
+
* jQuery(element).on('click', throttled);
|
|
1290
|
+
*
|
|
1291
|
+
* // Cancel the trailing throttled invocation.
|
|
1292
|
+
* jQuery(window).on('popstate', throttled.cancel);
|
|
1293
|
+
*/
|
|
1294
|
+
function throttle(func, wait, options) {
|
|
1295
|
+
var leading = true,
|
|
1296
|
+
trailing = true;
|
|
1297
|
+
|
|
1298
|
+
if (typeof func != 'function') {
|
|
1299
|
+
throw new TypeError(FUNC_ERROR_TEXT);
|
|
1300
|
+
}
|
|
1301
|
+
if (isObject(options)) {
|
|
1302
|
+
leading = 'leading' in options ? !!options.leading : leading;
|
|
1303
|
+
trailing = 'trailing' in options ? !!options.trailing : trailing;
|
|
1304
|
+
}
|
|
1305
|
+
return debounce(func, wait, {
|
|
1306
|
+
'leading': leading,
|
|
1307
|
+
'maxWait': wait,
|
|
1308
|
+
'trailing': trailing
|
|
1309
|
+
});
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
throttle_1 = throttle;
|
|
1313
|
+
return throttle_1;
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
var throttleExports = requireThrottle();
|
|
1317
|
+
var throttle = /*@__PURE__*/getDefaultExportFromCjs(throttleExports);
|
|
1318
|
+
|
|
1319
|
+
class MasonryLayout {
|
|
1320
|
+
constructor(grid) {
|
|
1321
|
+
this.grid = grid;
|
|
1322
|
+
this.create = () => {
|
|
1323
|
+
this.mutationObserver.observe(this.grid, {
|
|
1324
|
+
childList: true,
|
|
1325
|
+
});
|
|
1326
|
+
for (const item of Array.from(this.grid.children)) {
|
|
1327
|
+
this.resizeObserver.observe(item);
|
|
1328
|
+
}
|
|
1329
|
+
};
|
|
1330
|
+
this.onContainerMutation = (mutations) => {
|
|
1331
|
+
const removedNodes = mutations.flatMap((mutation) => Array.from(mutation.removedNodes));
|
|
1332
|
+
const addedNodes = mutations.flatMap((mutation) => Array.from(mutation.addedNodes));
|
|
1333
|
+
for (const node of removedNodes) {
|
|
1334
|
+
if (node instanceof Element) {
|
|
1335
|
+
this.resizeObserver.unobserve(node);
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
for (const node of addedNodes) {
|
|
1339
|
+
if (node instanceof Element) {
|
|
1340
|
+
this.resizeObserver.observe(node);
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
if (removedNodes.length > 0 && addedNodes.length === 0) {
|
|
1344
|
+
this.update();
|
|
1345
|
+
}
|
|
1346
|
+
};
|
|
1347
|
+
this.onChildrenResize = (entries) => {
|
|
1348
|
+
const entriesToUpdate = entries.filter((entry) => entry.target.parentElement !== null);
|
|
1349
|
+
if (entriesToUpdate.length > 0) {
|
|
1350
|
+
this.update();
|
|
1351
|
+
}
|
|
1352
|
+
};
|
|
1353
|
+
this.update = throttle(() => {
|
|
1354
|
+
const computedStyle = window.getComputedStyle(this.grid);
|
|
1355
|
+
if (computedStyle.getPropertyValue("display").includes("grid") === false) {
|
|
1356
|
+
this.clean();
|
|
1357
|
+
return;
|
|
1358
|
+
}
|
|
1359
|
+
const columns = parseGridTemplateColumns(this.grid);
|
|
1360
|
+
if (columns.length <= 1) {
|
|
1361
|
+
this.clean();
|
|
1362
|
+
return;
|
|
1363
|
+
}
|
|
1364
|
+
const rowGap = Number.parseFloat(computedStyle.getPropertyValue("row-gap").trim()) || 0;
|
|
1365
|
+
const items = Array.from(this.grid.children);
|
|
1366
|
+
for (let columnIndex = 0; columnIndex < columns.length; columnIndex++) {
|
|
1367
|
+
const firstItemInColumn = items[columnIndex];
|
|
1368
|
+
firstItemInColumn?.style.removeProperty("margin-top");
|
|
1369
|
+
}
|
|
1370
|
+
for (let index = 0; index < items.length; index++) {
|
|
1371
|
+
const prevItem = items[index - columns.length];
|
|
1372
|
+
const nextItem = items[index];
|
|
1373
|
+
if (prevItem !== undefined && nextItem !== undefined) {
|
|
1374
|
+
const prevBottom = prevItem.getBoundingClientRect().bottom;
|
|
1375
|
+
nextItem.style.removeProperty("margin-top");
|
|
1376
|
+
const nextTop = nextItem.getBoundingClientRect().top;
|
|
1377
|
+
if (nextTop - rowGap !== prevBottom) {
|
|
1378
|
+
const margin = Math.round((prevBottom - (nextTop - rowGap) + Number.EPSILON) * 100) / 100;
|
|
1379
|
+
nextItem.style.setProperty("margin-top", `${margin}px`);
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
}, 32);
|
|
1384
|
+
this.destroy = () => {
|
|
1385
|
+
this.resizeObserver.disconnect();
|
|
1386
|
+
this.mutationObserver.disconnect();
|
|
1387
|
+
this.clean();
|
|
1388
|
+
};
|
|
1389
|
+
this.clean = () => {
|
|
1390
|
+
for (const item of Array.from(this.grid.children)) {
|
|
1391
|
+
item.style.removeProperty("margin-top");
|
|
1392
|
+
}
|
|
1393
|
+
};
|
|
1394
|
+
this.mutationObserver = new MutationObserver(this.onContainerMutation);
|
|
1395
|
+
this.resizeObserver = new ResizeObserver(this.onChildrenResize);
|
|
1396
|
+
if (CSS.supports("grid-template-rows", "masonry") === false) {
|
|
1397
|
+
this.create();
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
[Symbol.dispose]() {
|
|
1401
|
+
this.destroy();
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
function parseGridTemplateColumns(grid) {
|
|
1405
|
+
const computedStyle = window.getComputedStyle(grid);
|
|
1406
|
+
const gridTemplateColumns = computedStyle.getPropertyValue("grid-template-columns");
|
|
1407
|
+
return gridTemplateColumns
|
|
1408
|
+
.trim()
|
|
1409
|
+
.split(/\s+(?=(?:[^()]*\([^()]*\))*[^()]*$)/);
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
const sallaReviewsPageCss = ":host{display:block}";
|
|
1413
|
+
|
|
1414
|
+
const SallaReviewsPage = class {
|
|
1415
|
+
constructor(hostRef) {
|
|
1416
|
+
registerInstance(this, hostRef);
|
|
1417
|
+
this.reviews = [];
|
|
1418
|
+
this.isLoading = false;
|
|
1419
|
+
this.pagination = null;
|
|
1420
|
+
this.sort = "latest";
|
|
1421
|
+
}
|
|
1422
|
+
getUrlParams() {
|
|
1423
|
+
const params = new URLSearchParams(window.location.search);
|
|
1424
|
+
return {
|
|
1425
|
+
sort: params.get('sort') || null,
|
|
1426
|
+
page: Number.parseInt(params.get('page')) || 1
|
|
1427
|
+
};
|
|
1428
|
+
}
|
|
1429
|
+
updateUrlParams(params) {
|
|
1430
|
+
const url = new URL(window.location.href);
|
|
1431
|
+
for (const [key, value] of Object.entries(params)) {
|
|
1432
|
+
if (value) {
|
|
1433
|
+
url.searchParams.set(key, value.toString());
|
|
1434
|
+
}
|
|
1435
|
+
else {
|
|
1436
|
+
url.searchParams.delete(key);
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
window.history.replaceState({}, '', url.toString());
|
|
1440
|
+
}
|
|
1441
|
+
fetchReviews(sort, page) {
|
|
1442
|
+
const urlParams = this.getUrlParams();
|
|
1443
|
+
return salla.api.request('reviews', {
|
|
1444
|
+
params: {
|
|
1445
|
+
type: 'products',
|
|
1446
|
+
format: 'lite',
|
|
1447
|
+
per_page: 8,
|
|
1448
|
+
page: page || urlParams.page || 1,
|
|
1449
|
+
sort: sort || urlParams.sort || null
|
|
1450
|
+
}
|
|
1451
|
+
});
|
|
1452
|
+
}
|
|
1453
|
+
async initializeMasonry() {
|
|
1454
|
+
const grid = this.el.querySelector('.s-reviews-page-grid');
|
|
1455
|
+
if (!grid)
|
|
1456
|
+
return;
|
|
1457
|
+
try {
|
|
1458
|
+
new MasonryLayout(grid);
|
|
1459
|
+
salla.logger.info('Masonry initialized successfully');
|
|
1460
|
+
}
|
|
1461
|
+
catch (error) {
|
|
1462
|
+
salla.logger.error('Masonry initialization failed:', error);
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
animateReviewCards() {
|
|
1466
|
+
const items = this.wrapper.querySelectorAll('salla-review-card:not(.animated)');
|
|
1467
|
+
Helper.animateItems(items);
|
|
1468
|
+
}
|
|
1469
|
+
initiateInfiniteScroll() {
|
|
1470
|
+
if (!this.wrapper) {
|
|
1471
|
+
salla.logger.error('Wrapper is undefined. Cannot initiate infinite scroll.');
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1474
|
+
this.infiniteScroll = salla.infiniteScroll.initiate(this.wrapper, this.wrapper, {
|
|
1475
|
+
path: () => this.pagination?.links?.next || null,
|
|
1476
|
+
history: false,
|
|
1477
|
+
scrollThreshold: false,
|
|
1478
|
+
}, true);
|
|
1479
|
+
this.infiniteScroll?.on('request', () => {
|
|
1480
|
+
this.isLoading = true;
|
|
1481
|
+
});
|
|
1482
|
+
this.infiniteScroll?.on('load', response => {
|
|
1483
|
+
this.pagination = response.pagination;
|
|
1484
|
+
this.reviews = [...this.reviews, ...response.data];
|
|
1485
|
+
this.isLoading = false;
|
|
1486
|
+
// Update URL with the current page
|
|
1487
|
+
this.updateUrlParams({ page: response.pagination.current_page });
|
|
1488
|
+
});
|
|
1489
|
+
this.infiniteScroll?.on('error', (e) => {
|
|
1490
|
+
salla.logger.error('Error loading more reviews:', e);
|
|
1491
|
+
this.isLoading = false;
|
|
1492
|
+
});
|
|
1493
|
+
}
|
|
1494
|
+
componentDidRender() {
|
|
1495
|
+
setTimeout(() => {
|
|
1496
|
+
requestAnimationFrame(this.animateReviewCards.bind(this));
|
|
1497
|
+
}, 176);
|
|
1498
|
+
}
|
|
1499
|
+
async componentWillLoad() {
|
|
1500
|
+
try {
|
|
1501
|
+
await salla.onReady();
|
|
1502
|
+
// Initialize language variables
|
|
1503
|
+
this.langTitlesReviews = salla.lang.get("common.titles.reviews");
|
|
1504
|
+
this.langSorting = salla.lang.get('pages.categories.sorting');
|
|
1505
|
+
this.placeholderText = salla.lang.choice("pages.rating.reviews", 0);
|
|
1506
|
+
this.langLoadMore = salla.lang.get('common.elements.load_more');
|
|
1507
|
+
this.langSortByTopRating = salla.lang.get('pages.testimonials.sort_by_rating_desc');
|
|
1508
|
+
this.langSortByMostRecent = salla.lang.get('pages.testimonials.sort_by_date_desc');
|
|
1509
|
+
this.langSortByLeastRated = salla.lang.get('pages.testimonials.sort_by_rating_asc');
|
|
1510
|
+
this.langSortByLeastRecent = salla.lang.get('pages.testimonials.sort_by_date_asc');
|
|
1511
|
+
const urlParams = this.getUrlParams();
|
|
1512
|
+
const response = await this.fetchReviews(urlParams.sort);
|
|
1513
|
+
this.sort = urlParams.sort;
|
|
1514
|
+
this.reviews = response.data;
|
|
1515
|
+
this.pagination = response.pagination;
|
|
1516
|
+
this.langRatingReviews = salla.lang.choice("pages.rating.reviews", this.pagination?.total);
|
|
1517
|
+
}
|
|
1518
|
+
catch (error) {
|
|
1519
|
+
salla.logger.error('Error loading reviews:', error);
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
async handleSorting(e) {
|
|
1523
|
+
const value = e.target.value;
|
|
1524
|
+
this.sort = value;
|
|
1525
|
+
this.updateUrlParams({ sort: value, page: 1 }); // Reset to page 1 when changing sort
|
|
1526
|
+
const response = await this.fetchReviews(value, 1);
|
|
1527
|
+
this.reviews = response.data;
|
|
1528
|
+
this.pagination = response.pagination;
|
|
1529
|
+
}
|
|
1530
|
+
async componentDidLoad() {
|
|
1531
|
+
await this.initializeMasonry();
|
|
1532
|
+
this.initiateInfiniteScroll();
|
|
1533
|
+
this.sort = this.getUrlParams().sort || "latest";
|
|
1534
|
+
this.updateUrlParams({ sort: this.sort, page: 1 });
|
|
1535
|
+
}
|
|
1536
|
+
disconnectedCallback() {
|
|
1537
|
+
if (this.infiniteScroll) {
|
|
1538
|
+
this.infiniteScroll.destroy();
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
renderSortingOptions() {
|
|
1542
|
+
const options = [
|
|
1543
|
+
{ value: 'latest', label: this.langSortByMostRecent },
|
|
1544
|
+
{ value: 'oldest', label: this.langSortByLeastRecent },
|
|
1545
|
+
{ value: 'top_rating', label: this.langSortByTopRating },
|
|
1546
|
+
{ value: 'bottom_rating', label: this.langSortByLeastRated },
|
|
1547
|
+
];
|
|
1548
|
+
return options.map(option => (h("option", { key: option.value, value: option.value, selected: option.value === this.sort }, option.label)));
|
|
1549
|
+
}
|
|
1550
|
+
render() {
|
|
1551
|
+
return (h("host", { key: '5e3b4042e6412dd2fdef3d776d4204c731df6c80' }, h("div", { key: 'a9daf869bac109b7c627c9fd8fd7c84cd4dd2965', class: "s-reviews-page-header-wrapper" }, h("h2", { key: '01cd6892650d8288003d79b4c12e82c4693e1cb6', class: "s-reviews-page-title" }, this.langTitlesReviews, h("span", { key: '935329858a3cc699da6fb6fb8c8515348ded9eb4', class: "s-reviews-page-count" }, "(", this.langRatingReviews, ")")), h("div", { key: 'e74312403c6dc7625c0c2090e6627a8a6b5fca9b', class: "s-reviews-page-filter-wrapper" }, h("label", { key: 'bf51576936b030ee59836861b03fa3b06471ed1f', class: "s-reviews-page-filter-label", htmlFor: "testimonials-filter" }, this.langSorting), h("select", { key: '72f09a679c5f42b08f55b908f67f3d3627b3a50c', onChange: (e) => this.handleSorting(e), disabled: !this.reviews.length, class: "s-reviews-page-filter" }, this.renderSortingOptions()))), this.reviews.length ? h("main", { class: "s-reviews-page-grid", ref: el => {
|
|
1552
|
+
this.wrapper = el;
|
|
1553
|
+
} }, this.reviews.map(review => (h("salla-review-card", { key: review.id, review: review }))))
|
|
1554
|
+
: h("div", { class: "s-products-list-placeholder" }, h("span", { innerHTML: ShoppingBag }), h("p", null, this.placeholderText)), this.pagination?.links?.next && this.reviews.length ? (h("div", { class: "s-reviews-page-load-more-container" }, h("salla-button", { class: "s-reviews-page-load-more-btn", loading: this.isLoading, onClick: () => this.infiniteScroll?.loadNextPage(), onKeyUp: () => this.infiniteScroll?.loadNextPage() }, this.langLoadMore))) : null));
|
|
1555
|
+
}
|
|
1556
|
+
get el() { return getElement(this); }
|
|
1557
|
+
};
|
|
1558
|
+
SallaReviewsPage.style = sallaReviewsPageCss;
|
|
1559
|
+
|
|
1560
|
+
const sallaReviewsSummaryCss = ":host{display:block}";
|
|
1561
|
+
|
|
1562
|
+
const SallaReviewsSummary = class {
|
|
1563
|
+
constructor(hostRef) {
|
|
1564
|
+
registerInstance(this, hostRef);
|
|
1565
|
+
this.canRender = false;
|
|
1566
|
+
this.showRatingSummary = false;
|
|
1567
|
+
this.recommendationOnly = false;
|
|
1568
|
+
this.showRecommendation = false;
|
|
1569
|
+
}
|
|
1570
|
+
async componentWillLoad() {
|
|
1571
|
+
try {
|
|
1572
|
+
await salla.onReady();
|
|
1573
|
+
this.initializeLanguages();
|
|
1574
|
+
this.loadConfig();
|
|
1575
|
+
// Only load data if component should be displayed
|
|
1576
|
+
if (this.showRatingSummary || this.showRecommendation) {
|
|
1577
|
+
await this.loadSummary();
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
catch (error) {
|
|
1581
|
+
console.error('Failed to initialize reviews summary component:', error);
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
async loadConfig() {
|
|
1585
|
+
this.showRatingSummary = salla.config.get('store.settings.rating.show_rating_summary');
|
|
1586
|
+
this.showRecommendation = salla.config.get('store.settings.rating.show_recommendation');
|
|
1587
|
+
this.recommendationOnly = this.showRecommendation && !this.showRatingSummary;
|
|
1588
|
+
}
|
|
1589
|
+
initializeLanguages() {
|
|
1590
|
+
return Salla.lang.onLoaded(() => {
|
|
1591
|
+
Salla.lang.addBulk({
|
|
1592
|
+
"blocks.comments.based_on": { ar: "بناءً على", en: "Based on" },
|
|
1593
|
+
"blocks.comments.recommended": { ar: "أوصوا بالمنتج", en: "Recommended" }
|
|
1594
|
+
});
|
|
1595
|
+
this.basedOnLabel = salla.lang.get('blocks.comments.based_on');
|
|
1596
|
+
this.recommendedLabel = salla.lang.get('blocks.comments.recommended');
|
|
1597
|
+
});
|
|
1598
|
+
}
|
|
1599
|
+
async loadSummary() {
|
|
1600
|
+
if (!this.itemId) {
|
|
1601
|
+
console.error('Error loading reviews summary: itemId is not defined');
|
|
1602
|
+
return this.canRender = false;
|
|
1603
|
+
}
|
|
1604
|
+
try {
|
|
1605
|
+
const response = (await salla.api.request(`rating/summary/${this.itemId}`));
|
|
1606
|
+
if (!response?.data || (Array.isArray(response.data.reviews) && !response.data.reviews.length)) {
|
|
1607
|
+
this.canRender = false;
|
|
1608
|
+
this.data = null;
|
|
1609
|
+
return;
|
|
1610
|
+
}
|
|
1611
|
+
this.data = response.data;
|
|
1612
|
+
this.canRender = true;
|
|
1613
|
+
}
|
|
1614
|
+
catch (error) {
|
|
1615
|
+
this.canRender = false;
|
|
1616
|
+
this.data = null;
|
|
1617
|
+
console.error('Error loading reviews summary:', error);
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
renderRecommendation() {
|
|
1621
|
+
if (!this.showRecommendation || !this.data?.recommendation) {
|
|
1622
|
+
return null;
|
|
1623
|
+
}
|
|
1624
|
+
const classes = {
|
|
1625
|
+
base: 's-reviews-summary-header-section',
|
|
1626
|
+
standalone: this.recommendationOnly ? 's-reviews-summary-recommendation-only' : ''
|
|
1627
|
+
};
|
|
1628
|
+
return (h("div", { class: `${classes.base} ${classes.standalone}`.trim() }, h("h4", { class: "s-reviews-summary-recommendation-percentage" }, "%", this.data?.recommendation), h("p", { class: "s-reviews-summary-count" }, this.recommendedLabel)));
|
|
1629
|
+
}
|
|
1630
|
+
render() {
|
|
1631
|
+
if (!this.canRender)
|
|
1632
|
+
return null;
|
|
1633
|
+
if (this.recommendationOnly)
|
|
1634
|
+
return this.renderRecommendation();
|
|
1635
|
+
const ratings = {
|
|
1636
|
+
"1": 0,
|
|
1637
|
+
"2": 0,
|
|
1638
|
+
"3": 0,
|
|
1639
|
+
"4": 0,
|
|
1640
|
+
"5": 0,
|
|
1641
|
+
...this.data.reviews
|
|
1642
|
+
};
|
|
1643
|
+
const reviewElements = Object.keys(ratings).reverse().map((rating) => {
|
|
1644
|
+
const percentage = ratings[rating];
|
|
1645
|
+
return (h("div", { key: rating, class: "s-reviews-summary-row" }, h("div", { class: "s-reviews-summary-row-rate" }, rating, " ", h("span", { innerHTML: Star })), h("salla-progress-bar", { class: "s-reviews-summary-progress", value: percentage, target: 100, hideUnits: true, height: '16px' }), h("span", { class: "s-reviews-summary-percentage" }, percentage, "%")));
|
|
1646
|
+
});
|
|
1647
|
+
return (h(Host, { class: "s-reviews-summary-wrapper" }, h("div", { class: "s-reviews-summary-header" }, h("div", { class: "s-reviews-summary-header-section" }, h("h3", { class: "s-reviews-summary-average" }, this.data.rating), h("div", null, h("salla-rating-stars", { size: 'large', value: this.data.rating }), h("p", { class: "s-reviews-summary-count" }, this.basedOnLabel, " ", salla.helpers.number(salla.lang.choice('pages.rating.reviews', this.data.count))))), this.renderRecommendation()), h("div", { class: "s-reviews-summary-rows" }, reviewElements)));
|
|
1648
|
+
}
|
|
1649
|
+
};
|
|
1650
|
+
SallaReviewsSummary.style = sallaReviewsSummaryCss;
|
|
1651
|
+
|
|
1652
|
+
export { SallaCommentForm as salla_comment_form, SallaCommentItem as salla_comment_item, SallaComments as salla_comments, SallaRatingStars as salla_rating_stars, SallaReviewCard as salla_review_card, SallaReviews as salla_reviews, SallaReviewsPage as salla_reviews_page, SallaReviewsSummary as salla_reviews_summary };
|