zz-shopify-components 0.24.1-beta.6 → 0.25.1-beta.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zz-shopify-components",
3
- "version": "0.24.1-beta.6",
3
+ "version": "0.25.1-beta.0",
4
4
  "description": "Reusable Shopify components for theme projects",
5
5
  "keywords": [
6
6
  "shopify",
@@ -1,4 +1,4 @@
1
- <div class=' tw-w-full product-accessories-swiper-container tw-h-full tw-relative'>
1
+ <zz-accessories-preview-swiper class=' tw-w-full product-accessories-swiper-container tw-h-full tw-relative'>
2
2
  <div class='swiper product-accessories-swiper-list tw-w-full tw-h-full tw-relative'>
3
3
  <div class='swiper-wrapper'>
4
4
  {% for image in product.metafields.custom.acc_images.value %}
@@ -98,9 +98,12 @@
98
98
  </div>
99
99
  </div>
100
100
  </div>
101
- </div>
101
+ </zz-accessories-preview-swiper>
102
102
 
103
103
  <style>
104
+ zz-accessories-preview-swiper {
105
+ display: block;
106
+ }
104
107
  .product-accessories-swiper-container .swiper-pagination {
105
108
  --swiper-pagination-color: black;
106
109
  --swiper-pagination-bottom: 10px;
@@ -162,113 +165,163 @@
162
165
  }
163
166
  </style>
164
167
  <script>
165
- document.addEventListener('DOMContentLoaded', function() {
166
- const thumbs = new Swiper('.product-accessories-swiper-list-thumbs', {
167
- slidesPerView: 5,
168
- spaceBetween: 8,
169
- watchSlidesProgress: true,
170
- slideToClickedSlide: true,
171
- breakpoints: {
172
- 0: { slidesPerView: 4, spaceBetween: 6 },
173
- 768: { slidesPerView: 5, spaceBetween: 8 },
174
- 1024:{ slidesPerView: 6, spaceBetween: 10 }
175
- }
176
- });
168
+ ;(() => {
169
+ class ZZAccessoriesPreviewSwiper extends HTMLElement {
170
+ constructor() {
171
+ super();
172
+ this._thumbs = null;
173
+ this._swiper = null;
174
+ this._listEl = null;
175
+ this._thumbsEl = null;
176
+ this._paginationEl = null;
177
+ this._btnPrev = null;
178
+ this._btnNext = null;
179
+ this._initialized = false;
180
+ }
181
+
182
+ connectedCallback() {
183
+ const init = () => {
184
+ if (this._initialized) return;
185
+ if (typeof Swiper === 'undefined') return;
186
+ this._ensureElements();
187
+ this._initSwipers();
188
+ this._initialized = true;
189
+ };
190
+
191
+ if (document.readyState === 'loading') {
192
+ document.addEventListener('DOMContentLoaded', init, { once: true });
193
+ } else {
194
+ init();
195
+ }
196
+ }
197
+
198
+ disconnectedCallback() {
199
+ this._destroySwipers();
200
+ this._initialized = false;
201
+ }
202
+
203
+ _ensureElements() {
204
+ this._listEl = this.querySelector('.product-accessories-swiper-list');
205
+ this._thumbsEl = this.querySelector('.product-accessories-swiper-list-thumbs');
206
+ if (!this._listEl || !this._thumbsEl) return;
207
+ this._paginationEl = this._listEl.querySelector('.swiper-pagination');
208
+ this._btnPrev = this._listEl.querySelector('.product-accessories-swiper-button-prev');
209
+ this._btnNext = this._listEl.querySelector('.product-accessories-swiper-button-next');
210
+ }
211
+
212
+ _initSwipers() {
213
+ if (!this._listEl || !this._thumbsEl) return;
214
+
215
+ this._thumbs = new Swiper(this._thumbsEl, {
216
+ slidesPerView: 5,
217
+ spaceBetween: 8,
218
+ watchSlidesProgress: true,
219
+ slideToClickedSlide: true,
220
+ breakpoints: {
221
+ 0: { slidesPerView: 4, spaceBetween: 6 },
222
+ 768: { slidesPerView: 5, spaceBetween: 8 },
223
+ 1024: { slidesPerView: 6, spaceBetween: 10 },
224
+ },
225
+ });
177
226
 
178
- const swiper = new Swiper('.product-accessories-swiper-list', {
179
- loop: true,
180
- navigation: {
181
- nextEl: '.product-accessories-swiper-button-next',
182
- prevEl: '.product-accessories-swiper-button-prev',
183
- },
184
- effect: 'fade',
185
- loopedSlides: {{ product.metafields.custom.acc_images.value.size | default: 0 }},
227
+ const loopedSlides = {{ product.metafields.custom.acc_images.value.size | default: 0 }};
228
+ this._swiper = new Swiper(this._listEl, {
229
+ loop: true,
230
+ navigation: {
231
+ nextEl: this._btnNext,
232
+ prevEl: this._btnPrev,
233
+ },
234
+ effect: 'fade',
235
+ loopedSlides: loopedSlides,
186
236
  slidesPerView: 1,
187
237
  spaceBetween: 10,
188
238
  pagination: {
189
- el: '.swiper-pagination',
190
- clickable: true,
239
+ el: this._paginationEl,
240
+ clickable: true,
191
241
  },
192
- thumbs: { swiper: thumbs },
193
- {% comment %} on: {
194
- slideChange: function() {
195
- const currentIndex = this.activeIndex;
196
- console.log('currentIndex:', currentIndex);
197
- const pointSwiperIndex = document.querySelectorAll('.product-accessories-point-item').forEach(item => {
198
- if (item.dataset.pointSwiperIndex == currentIndex + 1) {
199
- item.style.display = 'flex';
200
- } else {
201
- item.style.display = 'none';
202
- }
242
+ thumbs: { swiper: this._thumbs },
203
243
  });
204
244
  }
205
- } {% endcomment %}
206
- });
207
- });
208
245
 
209
- window.accessoriesPointClickHandler = async function(eventOrElement, variantId) {
210
- const element =
211
- eventOrElement?.currentTarget ||
212
- (eventOrElement instanceof Event ? eventOrElement.target : eventOrElement);
246
+ _destroySwipers() {
247
+ try {
248
+ this._swiper && this._swiper.destroy(true, true);
249
+ } catch (e) {}
250
+ try {
251
+ this._thumbs && this._thumbs.destroy(true, true);
252
+ } catch (e) {}
253
+ this._swiper = null;
254
+ this._thumbs = null;
255
+ }
256
+ }
213
257
 
214
- if (!(element instanceof Element)) {
215
- console.warn('accessoriesPointClickHandler: expected an Element but got', eventOrElement);
216
- return;
258
+ if (!customElements.get('zz-accessories-preview-swiper')) {
259
+ customElements.define('zz-accessories-preview-swiper', ZZAccessoriesPreviewSwiper);
217
260
  }
218
261
 
219
- const buyIcon = element.querySelector('.buy-icon');
220
- const buyDoneIcon = element.querySelector('.buy-done-icon');
221
- if (buyIcon) buyIcon.style.display = 'none';
222
- if (buyDoneIcon) buyDoneIcon.style.display = 'block';
223
- const data = {
224
- items: [
225
- {
226
- id: variantId,
227
- quantity: 1,
228
- },
229
- ],
230
- sections: 'cart-drawer,cart-icon-bubble',
231
- };
232
- const cart = document.querySelector('cart-drawer');
262
+ window.accessoriesPointClickHandler = async function(eventOrElement, variantId) {
263
+ const element =
264
+ eventOrElement?.currentTarget ||
265
+ (eventOrElement instanceof Event ? eventOrElement.target : eventOrElement);
233
266
 
234
- await fetch(`${routes.cart_add_url}`, {
235
- method: 'POST',
236
- headers: {
237
- 'Content-Type': 'application/json',
238
- Accept: 'application/javascript',
239
- },
240
- body: JSON.stringify(data),
241
- })
242
- .then((response) => response.json())
243
- .then((response) => {
244
- if (response.status) {
245
- publish(PUB_SUB_EVENTS.cartError, {
246
- source: 'product-form',
247
- productVariantId: variantId,
248
- errors: response.errors || response.description,
249
- message: response.message,
250
- });
251
- }
267
+ if (!(element instanceof Element)) {
268
+ console.warn('accessoriesPointClickHandler: expected an Element but got', eventOrElement);
269
+ return;
270
+ }
271
+
272
+ const buyIcon = element.querySelector('.buy-icon');
273
+ const buyDoneIcon = element.querySelector('.buy-done-icon');
274
+ if (buyIcon) buyIcon.style.display = 'none';
275
+ if (buyDoneIcon) buyDoneIcon.style.display = 'block';
276
+ const data = {
277
+ items: [
278
+ {
279
+ id: variantId,
280
+ quantity: 1,
281
+ },
282
+ ],
283
+ sections: 'cart-drawer,cart-icon-bubble',
284
+ };
285
+ const cart = document.querySelector('cart-drawer');
286
+
287
+ await fetch(`${routes.cart_add_url}`, {
288
+ method: 'POST',
289
+ headers: {
290
+ 'Content-Type': 'application/json',
291
+ Accept: 'application/javascript',
292
+ },
293
+ body: JSON.stringify(data),
294
+ })
295
+ .then((response) => response.json())
296
+ .then((response) => {
297
+ if (response.status) {
298
+ publish(PUB_SUB_EVENTS.cartError, {
299
+ source: 'product-form',
300
+ productVariantId: variantId,
301
+ errors: response.errors || response.description,
302
+ message: response.message,
303
+ });
304
+ }
252
305
 
253
306
  publish(PUB_SUB_EVENTS.cartUpdate, {
254
307
  source: 'product-form',
255
308
  productVariantId: variantId,
256
309
  cartData: response,
257
310
  });
258
- cart.renderContents(response, false);
259
- zzShowToast('1 item added to Cart', { type: 'success' });
260
-
261
- })
262
- .catch((e) => {
263
- console.error(e);
264
- })
265
- .finally(() => {
266
- setTimeout(() => {
267
- if (buyIcon) buyIcon.style.display = 'block';
268
- if (buyDoneIcon) buyDoneIcon.style.display = 'none';
269
- }, 3000);
270
- if (cart && cart.classList.contains('is-empty'))
271
- cart.classList.remove('is-empty');
272
- });
273
- };
311
+ cart.renderContents(response, false);
312
+ zzShowToast('1 item added to Cart', { type: 'success' });
313
+ })
314
+ .catch((e) => {
315
+ console.error(e);
316
+ })
317
+ .finally(() => {
318
+ setTimeout(() => {
319
+ if (buyIcon) buyIcon.style.display = 'block';
320
+ if (buyDoneIcon) buyDoneIcon.style.display = 'none';
321
+ }, 3000);
322
+ if (cart && cart.classList.contains('is-empty'))
323
+ cart.classList.remove('is-empty');
324
+ });
325
+ };
326
+ })();
274
327
  </script>