zz-shopify-components 0.34.1-beta.21 → 0.34.1-beta.23

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.
@@ -173,7 +173,6 @@ if (!customElements.get('zz-video-popup')) {
173
173
  this.popup = null;
174
174
  }
175
175
 
176
-
177
176
  connectedCallback() {
178
177
  this.querySelectorAll('.togglePopup').forEach((el) => {
179
178
  el.addEventListener('click', (event) => {
@@ -184,8 +183,6 @@ if (!customElements.get('zz-video-popup')) {
184
183
  });
185
184
  });
186
185
  this.popup = this.querySelector('.popup');
187
-
188
-
189
186
  }
190
187
 
191
188
  disconnectedCallback() {
@@ -226,7 +223,7 @@ if (!customElements.get('zz-video-popup')) {
226
223
  backdropFilter: 'blur(30px)',
227
224
  onComplete: () => {
228
225
  const videos = this.popup.querySelectorAll('video');
229
- videos.forEach(video => {
226
+ videos.forEach((video) => {
230
227
  if (window.getComputedStyle(video).display !== 'none') {
231
228
  video.play();
232
229
  }
@@ -246,7 +243,7 @@ if (!customElements.get('zz-video-popup')) {
246
243
  onComplete: () => {
247
244
  this.popup.classList.add('!tw-hidden');
248
245
  const videos = this.popup.querySelectorAll('video');
249
- videos.forEach(video => {
246
+ videos.forEach((video) => {
250
247
  if (video) {
251
248
  video.pause();
252
249
  }
@@ -261,7 +258,6 @@ if (!customElements.get('zz-video-popup')) {
261
258
  customElements.define('zz-video-popup', ZZVideoPopup);
262
259
  }
263
260
 
264
-
265
261
  if (!customElements.get('zz-video-handler')) {
266
262
  class ZZVideoHandler extends HTMLElement {
267
263
  constructor() {
@@ -310,7 +306,6 @@ if (!customElements.get('zz-video-handler')) {
310
306
  customElements.define('zz-video-handler', ZZVideoHandler);
311
307
  }
312
308
 
313
-
314
309
  /**
315
310
  * Toast 组件
316
311
  */
@@ -430,9 +425,11 @@ if (!customElements.get('zz-video-handler')) {
430
425
  function isSafari() {
431
426
  const ua = navigator.userAgent;
432
427
  // 包含 Safari / WebKit,且不包含 Chrome / CriOS / FxiOS / Android
433
- return /Safari/.test(ua)
434
- && /AppleWebKit/.test(ua)
435
- && !/CriOS|FxiOS|Chrome|Edg|OPR/.test(ua);
428
+ return (
429
+ /Safari/.test(ua) &&
430
+ /AppleWebKit/.test(ua) &&
431
+ !/CriOS|FxiOS|Chrome|Edg|OPR/.test(ua)
432
+ );
436
433
  }
437
434
 
438
435
  function isSafari26() {
@@ -442,8 +439,6 @@ if (!customElements.get('zz-video-handler')) {
442
439
  return /Version\/26\./.test(ua);
443
440
  }
444
441
 
445
-
446
-
447
442
  function lockBodyScroll() {
448
443
  if (isSafari26()) {
449
444
  scrollTop = window.scrollY;
@@ -506,11 +501,10 @@ document.addEventListener('DOMContentLoaded', (event) => {
506
501
  entries.forEach((entry) => {
507
502
  const el = entry.target;
508
503
  if (entry.isIntersecting) {
509
-
510
504
  } else {
511
505
  if (el.classList.contains('zz-card-animate-list')) {
512
506
  // 重置所有
513
- el.querySelectorAll('.zz-card-inner').forEach(card => {
507
+ el.querySelectorAll('.zz-card-inner').forEach((card) => {
514
508
  card.classList.remove('is-active');
515
509
  });
516
510
  }
@@ -518,47 +512,48 @@ document.addEventListener('DOMContentLoaded', (event) => {
518
512
  });
519
513
  });
520
514
 
521
-
522
515
  if (!isDesktop) {
523
516
  const switchCard = document.querySelectorAll('.product-switch-card');
524
517
  // 监听所有的switchCard 当它完全出现屏幕中时候,定时2秒切换成背景图。移出屏幕时候恢复
525
518
 
526
519
  if (switchCard.length > 0) {
527
520
  const switchTimers = new Map(); // 存储每个卡片的定时器
528
-
529
- const switchCardObserver = new IntersectionObserver((entries) => {
530
- entries.forEach((entry) => {
531
- const card = entry.target;
532
- console.log('switchCardObserver')
533
- if (entry.isIntersecting && entry.intersectionRatio >= 0.8) {
534
- // 完全出现在屏幕中,2秒后切换成背景图
535
- const timer = setInterval(() => {
536
- if (card.classList.contains('switchCard')) {
537
- card.classList.remove('switchCard');
538
- } else {
539
- card.classList.add('switchCard');
521
+
522
+ const switchCardObserver = new IntersectionObserver(
523
+ (entries) => {
524
+ entries.forEach((entry) => {
525
+ const card = entry.target;
526
+ console.log('switchCardObserver');
527
+ if (entry.isIntersecting && entry.intersectionRatio >= 0.8) {
528
+ // 完全出现在屏幕中,2秒后切换成背景图
529
+ const timer = setInterval(() => {
530
+ if (card.classList.contains('switchCard')) {
531
+ card.classList.remove('switchCard');
532
+ } else {
533
+ card.classList.add('switchCard');
534
+ }
535
+ }, 2000);
536
+ switchTimers.set(card, timer);
537
+ } else {
538
+ // 移出屏幕,恢复原状
539
+ const timer = switchTimers.get(card);
540
+ if (timer) {
541
+ clearInterval(timer);
542
+ switchTimers.delete(card);
540
543
  }
541
- }, 2000);
542
- switchTimers.set(card, timer);
543
- } else {
544
- // 移出屏幕,恢复原状
545
- const timer = switchTimers.get(card);
546
- if (timer) {
547
- clearInterval(timer);
548
- switchTimers.delete(card);
544
+ card.classList.remove('switchCard');
549
545
  }
550
- card.classList.remove('switchCard');
551
- }
552
- });
553
- }, {
554
- threshold: [0.2, 0.8] // 监听0%、99%和100%的可见度
555
- });
556
-
557
- switchCard.forEach(card => {
546
+ });
547
+ },
548
+ {
549
+ threshold: [0.2, 0.8], // 监听0%、99%和100%的可见度
550
+ }
551
+ );
552
+
553
+ switchCard.forEach((card) => {
558
554
  switchCardObserver.observe(card);
559
555
  });
560
556
  }
561
-
562
557
  }
563
558
 
564
559
  // 处理统一的定位脚本
@@ -568,17 +563,17 @@ document.addEventListener('DOMContentLoaded', (event) => {
568
563
  if (positionTrigger) {
569
564
  const selector = positionTrigger.getAttribute('data-zz-module-target');
570
565
  if (selector) {
571
- const target = document.querySelector(`[data-zz-module-name="${selector}"]`);
572
- const headerHeight = 50;
573
- const offsetTop = target.offsetTop - headerHeight;
574
- window.scrollTo(0, offsetTop);
575
-
566
+ const target = document.querySelector(
567
+ `[data-zz-module-name="${selector}"]`
568
+ );
569
+ const headerHeight = 50;
570
+ const offsetTop = target.offsetTop - headerHeight;
571
+ window.scrollTo(0, offsetTop);
576
572
  }
577
573
  return;
578
574
  }
579
575
  });
580
576
 
581
-
582
577
  // zz-card-animate-text.liquid
583
578
  const cardListGroup = document.querySelectorAll('.zz-card-animate-list');
584
579
  cardListGroup.forEach((list) => {
@@ -591,7 +586,7 @@ document.addEventListener('DOMContentLoaded', (event) => {
591
586
  console.log('click card item');
592
587
 
593
588
  // 重置所有
594
- list.querySelectorAll('.zz-card-inner').forEach(el => {
589
+ list.querySelectorAll('.zz-card-inner').forEach((el) => {
595
590
  el.classList.remove('is-active');
596
591
  });
597
592
 
@@ -599,8 +594,89 @@ document.addEventListener('DOMContentLoaded', (event) => {
599
594
  item.classList.add('is-active');
600
595
  });
601
596
  compIntersectionObserver.observe(list);
602
-
603
597
  });
598
+ });
599
+
600
+ if (!customElements.get('zz-normal-modal')) {
601
+ class ZZNormalModal extends HTMLElement {
602
+ constructor() {
603
+ super();
604
+ this.handleOverlayClick = this.handleOverlayClick.bind(this);
605
+ this.handleDocumentKeydown = this.handleDocumentKeydown.bind(this);
606
+ this.handleCloseClick = this.handleCloseClick.bind(this);
607
+ }
608
+
609
+ connectedCallback() {
610
+ this.dialogContent = this.querySelector('[data-modal-content]');
611
+ this.overlay = this.querySelector('[data-modal-overlay]');
612
+ this.closeButton = this.querySelector('[data-modal-close]');
604
613
 
614
+ if (this.overlay) {
615
+ this.overlay.addEventListener('click', this.handleOverlayClick);
616
+ }
617
+
618
+ if (this.closeButton) {
619
+ this.closeButton.addEventListener('click', this.handleCloseClick);
620
+ }
621
+ }
605
622
 
606
- });
623
+ disconnectedCallback() {
624
+ if (this.overlay) {
625
+ this.overlay.removeEventListener('click', this.handleOverlayClick);
626
+ }
627
+
628
+ if (this.closeButton) {
629
+ this.closeButton.removeEventListener('click', this.handleCloseClick);
630
+ }
631
+
632
+ document.removeEventListener('keydown', this.handleDocumentKeydown);
633
+ }
634
+
635
+ show() {
636
+ this.previousActiveElement = document.activeElement;
637
+ this.dialogContent.classList.add('is-open');
638
+ this.overlay.classList.add('is-open');
639
+ this.setAttribute('aria-hidden', 'false');
640
+ window.zzLockBodyScroll && window.zzLockBodyScroll();
641
+ document.addEventListener('keydown', this.handleDocumentKeydown);
642
+
643
+ requestAnimationFrame(() => {
644
+ if (this.dialogContent) {
645
+ this.dialogContent.focus();
646
+ }
647
+ });
648
+ }
649
+
650
+ hide() {
651
+ this.dialogContent.classList.remove('is-open');
652
+ this.overlay.classList.remove('is-open');
653
+ this.setAttribute('aria-hidden', 'true');
654
+ window.zzUnlockBodyScroll && window.zzUnlockBodyScroll();
655
+ document.removeEventListener('keydown', this.handleDocumentKeydown);
656
+
657
+ if (
658
+ this.previousActiveElement &&
659
+ typeof this.previousActiveElement.focus === 'function'
660
+ ) {
661
+ this.previousActiveElement.focus();
662
+ }
663
+ }
664
+
665
+ handleOverlayClick() {
666
+ this.hide();
667
+ }
668
+
669
+ handleCloseClick() {
670
+ console.log('click-close');
671
+ this.hide();
672
+ }
673
+
674
+ handleDocumentKeydown(event) {
675
+ if (event.key === 'Escape') {
676
+ this.hide();
677
+ }
678
+ }
679
+ }
680
+
681
+ customElements.define('zz-normal-modal', ZZNormalModal);
682
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zz-shopify-components",
3
- "version": "0.34.1-beta.21",
3
+ "version": "0.34.1-beta.23",
4
4
  "description": "Reusable Shopify components for theme projects",
5
5
  "keywords": [
6
6
  "shopify",
@@ -41,12 +41,23 @@
41
41
  "default": 24,
42
42
  "info": "单位:px"
43
43
  },
44
+ {
45
+ "type": "richtext",
46
+ "id": "title",
47
+ "label": "标题",
48
+ "info": "没有就不填写"
49
+ },
50
+ {
51
+ "type": "richtext",
52
+ "id": "title_mb",
53
+ "label": "标题移动端",
54
+ "info": "没有就不填写"
55
+ },
44
56
  ],
45
57
  "blocks": [
46
58
  {
47
59
  "type": "comment",
48
60
  "name": "comment",
49
- "limit": 3,
50
61
  "settings": [
51
62
  {
52
63
  "type": "select",
@@ -131,30 +142,54 @@
131
142
  }
132
143
  {% endschema %}
133
144
 
134
- <div class='user-spokes-section lg:tw-w-[85.3906vw] xl:tw-w-[1093px] lg:tw-mx-auto'>
135
- <div class='voc-item-list max-lg:tw-px-[20px] tw-flex lg:tw-justify-between max-lg:tw-overflow-x-auto tw-gap-[8px] lg:tw-gap-[20px] slow-reveal'>
136
- {% for block in section.blocks %}
137
- <div class='comment-box lg:tw-w-[351px] tw-flex tw-flex-col'>
138
- <div class='comment-item lg:tw-w-[351px] lg:tw-h-[468px]'>
139
- {% render 'zz-spoke',
140
- bg_color: 'rgba(0,0,0,0.04)',
141
- class_name: 'max-lg:tw-bg-[#F5F5F6]',
142
- pc_image: block.settings.pc_image,
143
- pc_video: block.settings.pc_video,
144
- mb_image: block.settings.mb_image,
145
- mb_video: block.settings.mb_video,
146
- pc_media_pos: block.settings.pc_media_pos,
147
- mb_media_pos: block.settings.mb_media_pos,
148
- user_name: block.settings.username,
149
- user_avatar: block.settings.avatar,
150
- user_account: block.settings.account,
151
- content: block.settings.content,
152
- name_class: 'tw-text-black max-lg:tw-text-[10px] lg:tw-text-[14px]',
153
- content_class: 'voc-text-content max-lg:tw-text-[10px] lg:tw-text-[14px] tw-text-black/70 lg:tw-text-black/60 max-lg:tw-leading-[1.2] tw-line-clamp-8 lg:tw-line-clamp-6'
154
- %}
145
+ {%- assign desktop_slider_enabled = false -%}
146
+ {%- if section.blocks.size > 3 -%}
147
+ {%- assign desktop_slider_enabled = true -%}
148
+ {%- endif -%}
149
+ <div class='user-spokes-section{% if desktop_slider_enabled %} voc-slider-active{% else %} lg:tw-w-[90vw] xl:tw-w-[1220px] lg:tw-mx-auto{% endif %}'>
150
+ {% if section.settings.title != blank %}
151
+ <div class='tw-flex tw-justify-center tw-mb-[30px] lg:tw-mb-[72px]'>
152
+ {% render 'zz-h3',
153
+ title: section.settings.title,
154
+ title_mb: section.settings.mb_title | default: section.settings.title,
155
+ class_name: 'tw-text-center'
156
+
157
+ %}
158
+ </div>
159
+ {% endif %}
160
+ <div class='tw-relative'>
161
+ <div class='voc-item-list max-lg:tw-px-[20px] tw-flex tw-gap-[8px] lg:tw-gap-[20px] slow-reveal{% if desktop_slider_enabled %} voc-item-list--desktop-slider{% else %} lg:tw-justify-center{% endif %}' data-voc-list>
162
+ {% for block in section.blocks %}
163
+ <div class='comment-box lg:tw-w-[351px] tw-flex tw-flex-col'>
164
+ <div class='comment-item lg:tw-w-[351px] lg:tw-h-[468px]'>
165
+ {% render 'zz-spoke',
166
+ bg_color: 'rgba(0,0,0,0.04)',
167
+ class_name: 'max-lg:tw-bg-[#F5F5F6]',
168
+ pc_image: block.settings.pc_image,
169
+ pc_video: block.settings.pc_video,
170
+ mb_image: block.settings.mb_image,
171
+ mb_video: block.settings.mb_video,
172
+ pc_media_pos: block.settings.pc_media_pos,
173
+ mb_media_pos: block.settings.mb_media_pos,
174
+ user_name: block.settings.username,
175
+ user_avatar: block.settings.avatar,
176
+ user_account: block.settings.account,
177
+ content: block.settings.content,
178
+ name_class: 'tw-text-black max-lg:tw-text-[10px] lg:tw-text-[14px]',
179
+ content_class: 'voc-text-content max-lg:tw-text-[10px] lg:tw-text-[14px] tw-text-black/70 lg:tw-text-black/60 max-lg:tw-leading-[1.2] tw-line-clamp-8 lg:tw-line-clamp-6'
180
+ %}
181
+ </div>
155
182
  </div>
156
- </div>
157
- {% endfor %}
183
+ {% endfor %}
184
+ </div>
185
+ {% if desktop_slider_enabled %}
186
+ <button type='button' class='voc-slider-button voc-slider-button--prev' data-voc-prev aria-label='Previous comments'>
187
+ {% render 'zz-prev-next-blur-icon', type: 'prev', color_type: 'light' %}
188
+ </button>
189
+ <button type='button' class='voc-slider-button voc-slider-button--next' data-voc-next aria-label='Next comments'>
190
+ {% render 'zz-prev-next-blur-icon', type: 'next', color_type: 'light' %}
191
+ </button>
192
+ {% endif %}
158
193
  </div>
159
194
  </div>
160
195
 
@@ -171,46 +206,57 @@
171
206
  #shopify-section-{{section.id}} .zz-spoke-block-media img{
172
207
  height: 100%;
173
208
  }
174
-
175
- .voc-item-list {
176
- -webkit-overflow-scrolling: touch; /* 移动端流畅滚动(可选) */
177
- scrollbar-width: none; /* Firefox */
178
- -ms-overflow-style: none; /* IE 和 Edge */
209
+ #shopify-section-{{section.id}} .voc-item-list {
210
+ -webkit-overflow-scrolling: touch;
211
+ scrollbar-width: none;
212
+ -ms-overflow-style: none;
213
+ }
214
+ #shopify-section-{{section.id}} .voc-item-list::-webkit-scrollbar {
215
+ width: 0px;
216
+ display: none;
179
217
  }
180
- .voc-item-list::-webkit-scrollbar {
181
- width: 0px; /* 隐藏滚动条 */
218
+ #shopify-section-{{section.id}} .voc-text-content {
219
+ display: -webkit-box;
220
+ -webkit-line-clamp: 5;
221
+ -webkit-box-orient: vertical;
222
+ overflow: hidden;
182
223
  }
183
- .voc-item-list::-webkit-scrollbar {
224
+ #shopify-section-{{section.id}} .voc-slider-button {
184
225
  display: none;
185
226
  }
186
227
  @media screen and (max-width: 1023px) {
228
+ #shopify-section-{{section.id}} .voc-item-list {
229
+ overflow-x: auto;
230
+ }
231
+ #shopify-section-{{section.id}} .voc-text-content {
232
+ -webkit-line-clamp: 8;
233
+ }
187
234
  #shopify-section-{{section.id}} .comment-box .comment-item {
188
235
  width: 168px;
189
-
190
236
  }
191
-
192
- #shopify-section-{{section.id}} .comment-box {
193
- width: 168px;
194
- height: 380px;
195
- }
196
- #shopify-section-{{section.id}} .comment-box .zz-spoke-block-media {
197
- height: 221px;
198
- }
199
- #shopify-section-{{section.id}} .comment-box .zz-spoke-block-content {
200
- box-sizing: border-box;
201
- height: 160px;
202
- }
203
-
204
-
205
-
237
+ #shopify-section-{{section.id}} .comment-box {
238
+ width: 168px;
239
+ height: 380px;
240
+ }
241
+ #shopify-section-{{section.id}} .comment-box .zz-spoke-block-media {
242
+ height: 221px;
243
+ }
244
+ #shopify-section-{{section.id}} .comment-box .zz-spoke-block-content {
245
+ box-sizing: border-box;
246
+ height: 160px;
247
+ }
206
248
  }
207
249
  @media (min-width: 1024px) {
208
250
  #shopify-section-{{section.id}} {
209
251
  padding-top: {{ section.settings.padding_top }}px;
210
252
  padding-bottom: {{ section.settings.padding_bottom }}px;
211
253
  }
254
+ #shopify-section-{{section.id}} .user-spokes-section {
255
+ width: 100%;
256
+ }
212
257
  #shopify-section-{{section.id}} .comment-box {
213
258
  height: 688px;
259
+ flex: 0 0 auto;
214
260
  }
215
261
  #shopify-section-{{section.id}} .comment-box .zz-spoke-block-media {
216
262
  height: 468px;
@@ -218,9 +264,53 @@
218
264
  #shopify-section-{{section.id}} .comment-box .zz-spoke-block-content {
219
265
  height: 210px;
220
266
  }
267
+ #shopify-section-{{section.id}} .voc-item-list--desktop-slider {
268
+ overflow-x: auto;
269
+ justify-content: flex-start;
270
+ scroll-behavior: smooth;
271
+ {% comment %} scroll-snap-type: x proximity; {% endcomment %}
272
+ width: 100vw;
273
+ max-width: 100vw;
274
+ {% comment %} padding-right: 5vw; {% endcomment %}
275
+ {% comment %} padding-left: 5vw; {% endcomment %}
276
+ box-sizing: border-box;
277
+ }
278
+ #shopify-section-{{section.id}} .voc-item-list--desktop-slider::before, #shopify-section-{{section.id}} .voc-item-list--desktop-slider::after {
279
+ content: '';
280
+ flex-shrink: 0;
281
+ width: 5vw;
282
+ }
283
+ #shopify-section-{{section.id}} .voc-item-list--desktop-slider .comment-box {
284
+ scroll-snap-align: start;
285
+ }
286
+ #shopify-section-{{section.id}} .voc-slider-button {
287
+ position: absolute;
288
+ top: 50%;
289
+ z-index: 2;
290
+ display: inline-flex;
291
+ align-items: center;
292
+ justify-content: center;
293
+ transform: translateY(-50%);
294
+ border: 0;
295
+ background: transparent;
296
+ padding: 0;
297
+ cursor: pointer;
298
+ }
299
+ #shopify-section-{{section.id}} .voc-slider-button[disabled] {
300
+ opacity: 0;
301
+ visibility: hidden;
302
+ pointer-events: none;
303
+ cursor: default;
304
+ }
305
+ #shopify-section-{{section.id}} .voc-slider-button--prev {
306
+ left: 16px;
307
+ }
308
+ #shopify-section-{{section.id}} .voc-slider-button--next {
309
+ right: 16px;
310
+ }
221
311
  }
222
- @media (min-width: 1024px) and (max-width: 1280px) {
223
- #shopify-section-{{section.id}} .user-spokes-section {
312
+ @media (min-width: 1024px) and (max-width: 1279px) {
313
+ #shopify-section-{{section.id}} .user-spokes-section:not(.voc-slider-active) {
224
314
  width: 85.3906vw;
225
315
  }
226
316
  #shopify-section-{{section.id}} .comment-box {
@@ -236,4 +326,63 @@
236
326
  height: 36.5625vw;
237
327
  }
238
328
  }
329
+ @media (min-width: 1280px) {
330
+ #shopify-section-{{section.id}} .voc-item-list--desktop-slider {
331
+ {% comment %} padding-left: calc((100vw - 1220px) / 2); {% endcomment %}
332
+ {% comment %} padding-right: calc((100vw - 1220px) / 2); {% endcomment %}
333
+ }
334
+ #shopify-section-{{section.id}} .voc-item-list--desktop-slider::after, #shopify-section-{{section.id}} .voc-item-list--desktop-slider::before {
335
+ content: '';
336
+ flex-shrink: 0;
337
+ width: calc((100vw - 1220px) / 2);
338
+ }
339
+ }
239
340
  </style>
341
+
342
+ <script>
343
+ document.addEventListener('DOMContentLoaded', () => {
344
+ const sectionRoot = document.getElementById('shopify-section-{{section.id}}');
345
+ if (!sectionRoot || window.innerWidth < 1024) return;
346
+
347
+ const list = sectionRoot.querySelector('[data-voc-list]');
348
+ const prevButton = sectionRoot.querySelector('[data-voc-prev]');
349
+ const nextButton = sectionRoot.querySelector('[data-voc-next]');
350
+ if (!list || !prevButton || !nextButton) return;
351
+
352
+ const getScrollAmount = () => {
353
+ const firstCard = list.querySelector('.comment-box');
354
+ if (!firstCard) return list.clientWidth;
355
+ const styles = window.getComputedStyle(list);
356
+ const gap = Number.parseFloat(styles.columnGap || styles.gap || '0') || 0;
357
+ return firstCard.getBoundingClientRect().width + gap;
358
+ };
359
+
360
+ const updateButtonState = () => {
361
+ const maxScrollLeft = Math.max(list.scrollWidth - list.clientWidth, 0);
362
+ const currentScrollLeft = Math.max(list.scrollLeft, 0);
363
+ prevButton.disabled = currentScrollLeft <= 2;
364
+ nextButton.disabled = currentScrollLeft >= maxScrollLeft - 2;
365
+ };
366
+
367
+ const scrollList = (direction) => {
368
+ list.scrollBy({
369
+ left: getScrollAmount() * direction,
370
+ behavior: 'smooth',
371
+ });
372
+ };
373
+
374
+ prevButton.addEventListener('click', () => {
375
+ if (prevButton.disabled) return;
376
+ scrollList(-1);
377
+ });
378
+
379
+ nextButton.addEventListener('click', () => {
380
+ if (nextButton.disabled) return;
381
+ scrollList(1);
382
+ });
383
+
384
+ list.addEventListener('scroll', updateButtonState, { passive: true });
385
+ window.addEventListener('resize', updateButtonState);
386
+ updateButtonState();
387
+ });
388
+ </script>
@@ -64,15 +64,29 @@ size:按钮尺寸
64
64
 
65
65
  {% else %}
66
66
 
67
- <button
68
- class="zz-btn zz-btn-{{ btn_type }} zz-btn-{{ btn_color }} zz-btn-shape-{{ shape }} zz-btn-{{ btn_size }} {% if width == 'full' %} tw-w-full {% endif %} {{ width }} {{ class_name }}"
69
- {% if modal_id != blank %} data-zz-modal-target="#{{ modal_id }}" {% endif %}
70
- {% if btn_id != blank %} id="{{ btn_id }}" data-track-zz-element="{{ btn_id }}" {% endif %}
71
- {% if backdrop_filter %}
72
- style="backdrop-filter: blur(12px);background: #FFFFFF0F;"
67
+ {% if btn_type == 'link' %}
68
+ <a href="{{ href | default: '#' }}"
69
+ {% if modal_id != blank %} data-zz-modal-target="#{{ modal_id }}" {% endif %}
70
+ {% if btn_id != blank %} id="{{ btn_id }}" data-track-zz-element="{{ btn_id }}" {% endif %}
71
+ class="zz-btn-link tw-text-[#378DDD] tw-inline-flex tw-items-center tw-text-[12px] lg:tw-text-[14px] tw-no-underline zz-btn-link-{{ btn_size }} {% if width == 'full' %} tw-w-full {% endif %} {{ class_name }}">
72
+ <span class="zz-btn-text">{{ text }}</span>
73
+ {% if postfix_icon %}<span class="zz-btn-icon" style="margin-left: {{ icon_left_margin }}px; margin-right: {{ icon_right_margin }}px;">
74
+ {% render 'zz-icon', icon_name: postfix_icon, icon_size: icon_size %}
75
+ </span>{% endif %}
76
+ </a>
77
+ {% else %}
78
+ <button
79
+ class="zz-btn zz-btn-{{ btn_type }} zz-btn-{{ btn_color }} zz-btn-shape-{{ shape }} zz-btn-{{ btn_size }} {% if width == 'full' %} tw-w-full {% endif %} {{ width }} {{ class_name }}"
80
+ {% if modal_id != blank %} data-zz-modal-target="#{{ modal_id }}" {% endif %}
81
+ {% if btn_id != blank %} id="{{ btn_id }}" data-track-zz-element="{{ btn_id }}" {% endif %}
82
+ {% if backdrop_filter %}
83
+ style="backdrop-filter: blur(12px);background: #FFFFFF0F;"
84
+ {% endif %}
85
+ >
86
+ {% if icon %}<span class="zz-btn-icon">{{ icon }}</span>{% endif %}
87
+ <span class="zz-btn-text">{{ text }}</span>
88
+ </button>
89
+
73
90
  {% endif %}
74
- >
75
- {% if icon %}<span class="zz-btn-icon">{{ icon }}</span>{% endif %}
76
- <span class="zz-btn-text">{{ text }}</span>
77
- </button>
91
+
78
92
  {% endif %}