zz-shopify-components 0.0.1-beta.1

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.
Files changed (61) hide show
  1. package/README.md +12 -0
  2. package/assets/fade-in-content.js +169 -0
  3. package/assets/gsap.min.js +11 -0
  4. package/assets/http-request.js +73 -0
  5. package/assets/jquery.js +2 -0
  6. package/assets/lozad.js +10 -0
  7. package/assets/site-jump.js +52 -0
  8. package/assets/site-jumpV2.js +35 -0
  9. package/assets/swiper-bundle.min.css +13 -0
  10. package/assets/swiper-bundle.min.js +14 -0
  11. package/assets/swiper.css +331 -0
  12. package/assets/zz-components.css +323 -0
  13. package/assets/zz-components.js +166 -0
  14. package/blocks/zz-accessories-item.liquid +183 -0
  15. package/blocks/zz-accessories-swiper.liquid +223 -0
  16. package/blocks/zz-button.liquid +189 -0
  17. package/blocks/zz-content-description-html.liquid +199 -0
  18. package/blocks/zz-content-description.liquid +200 -0
  19. package/blocks/zz-flex-layout-bg-block.liquid +520 -0
  20. package/blocks/zz-flex-layout-block.liquid +545 -0
  21. package/blocks/zz-flex-layout-widget.liquid +318 -0
  22. package/blocks/zz-full-screen-swiper.liquid +444 -0
  23. package/blocks/zz-icon.liquid +46 -0
  24. package/blocks/zz-mail.liquid +135 -0
  25. package/blocks/zz-mb-swiper-pc-flex.liquid +270 -0
  26. package/blocks/zz-ratio-image.liquid +177 -0
  27. package/blocks/zz-ratio-video.liquid +112 -0
  28. package/blocks/zz-responsive-width-image.liquid +219 -0
  29. package/blocks/zz-responsive-width-video.liquid +163 -0
  30. package/blocks/zz-scroll-animate-bg-text.liquid +265 -0
  31. package/blocks/zz-scroll-cover.liquid +64 -0
  32. package/blocks/zz-tag.liquid +48 -0
  33. package/blocks/zz-text.liquid +225 -0
  34. package/blocks/zz-title.liquid +284 -0
  35. package/blocks/zz-video-button.liquid +81 -0
  36. package/blocks/zz-video-swiper-perview-item.liquid +216 -0
  37. package/blocks/zz-video-swiper-perview.liquid +582 -0
  38. package/component.config.json +4 -0
  39. package/package.json +23 -0
  40. package/scripts/postinstall-v2.js +47 -0
  41. package/scripts/postinstall.js +39 -0
  42. package/sections/zz-flex-layout-section.liquid +266 -0
  43. package/sections/zz-navigation-tab-v3.liquid +403 -0
  44. package/sections/zz-navigation-tab.liquid +410 -0
  45. package/sections/zz-video-collapse-swiper.liquid +522 -0
  46. package/sections/zz-video-tab-swiper.liquid +745 -0
  47. package/snippets/zz-button.liquid +70 -0
  48. package/snippets/zz-content-text.liquid +56 -0
  49. package/snippets/zz-h2.liquid +31 -0
  50. package/snippets/zz-h3.liquid +31 -0
  51. package/snippets/zz-h4.liquid +30 -0
  52. package/snippets/zz-h5.liquid +39 -0
  53. package/snippets/zz-h6.liquid +39 -0
  54. package/snippets/zz-icon.liquid +74 -0
  55. package/snippets/zz-img.liquid +44 -0
  56. package/snippets/zz-prev-next-btn.liquid +62 -0
  57. package/snippets/zz-spoke.liquid +142 -0
  58. package/snippets/zz-tag.liquid +22 -0
  59. package/snippets/zz-video-button.liquid +55 -0
  60. package/snippets/zz-video-md.liquid +117 -0
  61. package/snippets/zz-video.liquid +117 -0
@@ -0,0 +1,582 @@
1
+ {% assign block_size = block.blocks.size %}
2
+ {% assign bullets_width_half = block_size
3
+ | minus: 1
4
+ | times: 14
5
+ | plus: 6
6
+ | divided_by: 2.0
7
+ | ceil
8
+ %}
9
+ {% assign btn_offset = bullets_width_half | plus: 14 | plus: 36 %}
10
+
11
+ <style>
12
+ #shopify-block-{{block.id}} {
13
+ background: {{ block.settings.bg_color }};
14
+ width: 100%;
15
+ box-sizing: border-box;
16
+ overflow: hidden;
17
+ position: relative;
18
+ }
19
+ #shopify-block-{{block.id}} .zz-video-swiper-preview {
20
+ width: 100%;
21
+ box-sizing: border-box;
22
+ overflow: hidden;
23
+ height: fit-content;
24
+ position: relative;
25
+ letter-spacing: 0;
26
+ }
27
+
28
+ #shopify-block-{{block.id}} .swiper-button-next,
29
+ #shopify-block-{{block.id}} .swiper-button-prev {
30
+ top: 0;
31
+ width: 48px;
32
+ height: 48px;
33
+ }
34
+ #shopify-block-{{block.id}} .swiper-button-prev {
35
+ left: unset;
36
+ right: 50%;
37
+ transform: translate(-46.4063vw, 23.4375vw);
38
+ }
39
+ #shopify-block-{{block.id}} .swiper-button-next {
40
+ right: unset;
41
+ left: 50%;
42
+ transform: translate(46.4063vw, 23.4375vw);
43
+ }
44
+ #shopify-block-{{block.id}} .swiper-button-next:after,
45
+ #shopify-block-{{block.id}} .swiper-button-prev:after {
46
+ display: none;
47
+ }
48
+ #shopify-section-{{section.id}} .swiper-button-next.swiper-button-disabled, #shopify-section-{{section.id}} .swiper-button-prev.swiper-button-disabled {
49
+ opacity: 0.5;
50
+ }
51
+
52
+ #shopify-block-{{block.id}} .zz-video-swiper-preview .swiper-pagination-bullets .swiper-pagination-bullet {
53
+ margin: 0 8px;
54
+ width: 48px;
55
+ height: 4px;
56
+ border-radius: 3px;
57
+ background: {{ block.settings.pagination_color | color_modify: 'alpha', 0.3 }};
58
+ opacity: 1;
59
+ transition: 0.3s;
60
+ }
61
+ #shopify-block-{{block.id}} .zz-video-swiper-preview .swiper-pagination-bullets .swiper-pagination-bullet-active {
62
+ position: relative;
63
+ width: 120px;
64
+ {% if block.settings.if_autoplay == false %}
65
+ background: #fff;
66
+ {% endif %}
67
+ }
68
+ #shopify-block-{{block.id}} .zz-video-swiper-preview .swiper-pagination-bullets .swiper-pagination-bullet-active .progress-line {
69
+ display: block;
70
+ position: absolute;
71
+ width:0;
72
+ height: 4px;
73
+ left: 0;
74
+ top: 0;
75
+ background-color: {{ block.settings.pagination_color }};
76
+ border-radius: 3px;
77
+ }
78
+ #shopify-block-{{block.id}} .swiper-slide-active .active-box-content {
79
+ display: block !important;
80
+ }
81
+
82
+ @media screen and (max-width: 1023px) {
83
+ #shopify-block-{{block.id}} .zz-video-swiper-preview {
84
+ padding-bottom: 40px;
85
+ }
86
+
87
+ #shopify-block-{{block.id}} .zz-video-swiper-preview .swiper-slide .banner-item::after {
88
+ display: none;
89
+ }
90
+ #shopify-block-{{block.id}} .swiper-button-next,
91
+ #shopify-block-{{block.id}} .swiper-button-prev {
92
+ z-index: 99;
93
+ top: unset;
94
+ bottom: 0;
95
+ width: 36px;
96
+ height: 36px;
97
+ }
98
+ #shopify-block-{{block.id}} .swiper-button-prev {
99
+ left: 50%;
100
+ transform: translate(-{{ btn_offset }}px, 0px);
101
+ }
102
+ #shopify-block-{{block.id}} .swiper-button-next {
103
+ left: unset;
104
+ right: 50%;
105
+ transform: translate({{ btn_offset }}px, 0px);
106
+ }
107
+ #shopify-block-{{block.id}} .zz-video-swiper-preview .swiper-pagination-bullets .swiper-pagination-bullet {
108
+ margin: 0 4px;
109
+ width: 6px;
110
+ height: 6px;
111
+ background-color: {{ block.settings.mb_pagination_color | color_modify: 'alpha', 0.3 }};
112
+ }
113
+ #shopify-block-{{block.id}} .zz-video-swiper-preview .swiper-pagination-bullets .swiper-pagination-bullet.swiper-pagination-bullet-active {
114
+ width: 6px;
115
+ background-color: {{ block.settings.mb_pagination_color }};
116
+ }
117
+ }
118
+ @media screen and (min-width: 1024px) {
119
+ #shopify-block-{{block.id}} .content-title-h2 {
120
+ font-size: 60px;
121
+ }
122
+ #shopify-block-{{block.id}} .zz-video-swiper-preview .swiper-pagination-bullets {
123
+ {% if block.settings.has_title_and_content %}
124
+ bottom: 220px;
125
+ {% else %}
126
+ bottom: 21px;
127
+ {% endif %}
128
+ }
129
+ #shopify-block-{{block.id}} .swiper-button-next.swiper-button-disabled, #shopify-block-{{block.id}} .swiper-button-prev.swiper-button-disabled {
130
+ opacity: 0;
131
+ }
132
+ #shopify-block-{{block.id}} .zz-video-swiper-preview::before {
133
+ content: '';
134
+ display: block;
135
+ position: absolute;
136
+ left: calc(50% - 30px);
137
+ top: 0;
138
+ width: 83.3594vw;
139
+ height: 46.875vw;
140
+ transform: translateX(-150%);
141
+ z-index: 2;
142
+ border-radius: 16px;
143
+ background: {{ block.settings.gradient_color_left }};
144
+ }
145
+
146
+ #shopify-block-{{block.id}} .zz-video-swiper-preview::after {
147
+ content: '';
148
+ display: block;
149
+ position: absolute;
150
+ right: calc(50% - 30px);
151
+ top: 0;
152
+ width: 83.3594vw;
153
+ height: 46.875vw;
154
+ transform: translateX(150%);
155
+ z-index: 2;
156
+ border-radius: 16px;
157
+ background: {{ block.settings.gradient_color_right }};
158
+ }
159
+
160
+
161
+ }
162
+ @media screen and (min-width: 1280px) {
163
+ #shopify-block-{{block.id}} .zz-video-swiper-preview::before,
164
+ #shopify-block-{{block.id}} .zz-video-swiper-preview::after {
165
+ width: 1067px;
166
+ height: 600px;
167
+ }
168
+ #shopify-block-{{block.id}} .swiper-button-prev {
169
+ transform: translate(-594px, 300px);
170
+ }
171
+ #shopify-block-{{block.id}} .swiper-button-next {
172
+ transform: translate(594px, 300px);
173
+ }
174
+
175
+ }
176
+ </style>
177
+
178
+ <div
179
+ class='zz-video-swiper-preview zz-video-swiper-preview-{{ block.id }}'
180
+ >
181
+ <div class='swiper-wrapper'>
182
+ {% content_for 'blocks' %}
183
+ </div>
184
+
185
+ <!-- If we need navigation buttons -->
186
+ <div class='swiper-button-prev {% if block_size <= 1 %} tw-hidden {% endif %}'>
187
+ <span class='lg:tw-hidden'>
188
+ {% if block.settings.prev_icon != blank %}
189
+ {{
190
+ block.settings.prev_icon
191
+ | image_url: width: 48
192
+ | image_tag:
193
+ alt: 'prev',
194
+ class: 'tw-w-full tw-h-full tw-object-contain'
195
+ }}
196
+ {% else %}
197
+ {% render 'zz-prev-next-btn',
198
+ type: 'prev',
199
+ color_type: block.settings.prev_next_type
200
+ %}
201
+ {% endif %}
202
+
203
+ </span>
204
+ <span class='max-lg:tw-hidden'>
205
+ {% render 'zz-prev-next-btn', type: 'prev', color_type: 'light' %}
206
+ </span>
207
+ </div>
208
+ <div class='swiper-button-next {% if block_size <= 1 %} tw-hidden {% endif %}'>
209
+ <span class='lg:tw-hidden'>
210
+ {% if block.settings.next_icon != blank %}
211
+ {{
212
+ block.settings.next_icon
213
+ | image_url: width: 48
214
+ | image_tag:
215
+ alt: 'prev',
216
+ class: 'tw-w-full tw-h-full tw-object-contain'
217
+ }}
218
+ {% else %}
219
+ {% render 'zz-prev-next-btn',
220
+ type: 'next',
221
+ color_type: block.settings.prev_next_type
222
+ %}
223
+ {% endif %}
224
+
225
+ </span>
226
+ <span class='max-lg:tw-hidden'>
227
+ {% render 'zz-prev-next-btn', type: 'next', color_type: 'light' %}
228
+ </span>
229
+ </div>
230
+
231
+ <!-- Pagination indicator -->
232
+ <div class='swiper-pagination'></div>
233
+ </div>
234
+
235
+ <script>
236
+ document.addEventListener('DOMContentLoaded', function () {
237
+ const swiperClassName = '.zz-video-swiper-preview-{{ block.id }}';
238
+ let isDesktop = window.innerWidth > 1023;
239
+ // 获取 class zz-accessories-swiper 的元素 且data-id 为 block.id 的元素
240
+ const zzAccessoriesSwiper = document.querySelector(swiperClassName);
241
+ const swiperWrapper = zzAccessoriesSwiper.querySelector('.swiper-wrapper');
242
+ // 获取当前 swiper-wrapper 下面 所有 第一层 div
243
+ const swiperSlides = swiperWrapper.querySelectorAll(':scope > div');
244
+ // 给每个 swiper-slide 添加 class swiper-slide
245
+ swiperSlides.forEach((slide) => {
246
+ slide.classList.add('swiper-slide');
247
+ });
248
+ let progressInterval = null;
249
+ let progressTimer = null;
250
+
251
+ const prevSwiper = new Swiper(swiperClassName, {
252
+ {% if block.settings.if_loop == true %}
253
+ loop: true,
254
+ {% endif %}
255
+ slidesPerView: 'auto',
256
+ centeredSlides: true,
257
+ spaceBetween: isDesktop ? 30 : 8,
258
+ navigation: {
259
+ nextEl: '.swiper-button-next',
260
+ prevEl: '.swiper-button-prev',
261
+ },
262
+ pagination: {
263
+ el: '.swiper-pagination',
264
+ clickable: true,
265
+ renderBullet: function (index, className) {
266
+ return `
267
+ <span class="${className}">
268
+ <span class="progress-line"></span>
269
+ </span>`;
270
+ },
271
+ },
272
+ effect: 'slide',
273
+ on: {
274
+ slideChangeTransitionEnd: function () {
275
+ handleVideoOnSlideChange();
276
+ },
277
+ slideChangeTransitionStart: function () {
278
+ if (progressInterval) {
279
+ clearInterval(progressInterval);
280
+ }
281
+ if (progressTimer) {
282
+ clearTimeout(progressTimer);
283
+ }
284
+ },
285
+ slideChange: function () {
286
+ if (isDesktop) {
287
+ const block = document.getElementById('shopify-block-{{block.id}}');
288
+ block
289
+ .querySelectorAll('.swiper-pagination-bullet')
290
+ .forEach((bullet) => {
291
+ const progressBar = bullet.querySelector('.progress-line');
292
+ progressBar.style.transition = 'none';
293
+ progressBar.style.width = '0';
294
+ });
295
+ }
296
+ },
297
+ },
298
+ });
299
+
300
+ // 使用 Intersection Observer 监听 swiper-wrapper 的可见性
301
+
302
+ const observer = new IntersectionObserver(
303
+ (entries) => {
304
+ entries.forEach((entry) => {
305
+ if (entry.isIntersecting) {
306
+ // 当 swiper-wrapper 第一次出现在视口中时执行
307
+ setTimeout(() => {
308
+ handleVideoOnSlideChange();
309
+ }, 200);
310
+ // 执行一次后取消观察
311
+ observer.unobserve(entry.target);
312
+ }
313
+ });
314
+ },
315
+ {
316
+ threshold: 0.2, // 当 20% 的元素可见时触发
317
+ }
318
+ );
319
+
320
+ if (swiperWrapper) {
321
+ observer.observe(swiperWrapper);
322
+ }
323
+
324
+ function getVisibleDisplayMedias(container) {
325
+ const videos = container.querySelectorAll('video');
326
+ const video = Array.from(videos).find((video) => {
327
+ const style = window.getComputedStyle(video);
328
+ return style.display !== 'none';
329
+ });
330
+ if (video) {
331
+ return {
332
+ video,
333
+ type: 'video',
334
+ };
335
+ } else {
336
+ const images = container.querySelectorAll('img');
337
+ const image = Array.from(images).find((image) => {
338
+ const style = window.getComputedStyle(image);
339
+ return style.display !== 'none';
340
+ });
341
+ if (image) {
342
+ return {
343
+ image,
344
+ type: 'image',
345
+ };
346
+ }
347
+ }
348
+ return null;
349
+ }
350
+ const endedHandler = function () {
351
+
352
+ if (prevSwiper.isEnd) {
353
+ prevSwiper.slideTo(0);
354
+ } else {
355
+ prevSwiper.slideNext();
356
+ }
357
+ if (progressInterval) {
358
+ clearInterval(progressInterval);
359
+ }
360
+ this.removeEventListener('ended', endedHandler);
361
+ };
362
+
363
+ function updataMediaProgress(type, videoDom) {
364
+ const block = document.getElementById('shopify-block-{{block.id}}');
365
+ const activeBullet = block.querySelector(
366
+ '.swiper-pagination-bullet-active'
367
+ );
368
+ const progressBar = activeBullet.querySelector('.progress-line');
369
+ if (progressBar) {
370
+ if (progressInterval) {
371
+ clearInterval(progressInterval);
372
+ }
373
+ if (progressTimer) {
374
+ clearTimeout(progressTimer);
375
+ }
376
+ if (type === 'video') {
377
+ // 添加新的事件监听器
378
+ if (isDesktop) {
379
+ progressInterval = setInterval(() => {
380
+ const progress = videoDom.currentTime / videoDom.duration;
381
+ progressBar.style.transition = '0.2s';
382
+ progressBar.style.width = `${progress * 100}%`;
383
+ }, 100);
384
+ }
385
+
386
+ videoDom.addEventListener('ended', endedHandler);
387
+ } else if (type === 'image') {
388
+ if (isDesktop) {
389
+ progressBar.style.transition = '10s linear';
390
+ progressBar.style.width = '100%';
391
+ }
392
+ progressTimer = setTimeout(() => {
393
+ if (prevSwiper.isEnd) {
394
+ prevSwiper.slideTo(0);
395
+ } else {
396
+ prevSwiper.slideNext();
397
+ }
398
+ }, 10000);
399
+ }
400
+ }
401
+ }
402
+
403
+ function handleVideoOnSlideChange() {
404
+ // 暂停所有视频
405
+ const block = document.getElementById('shopify-block-{{block.id}}');
406
+ const allvideo = block.querySelectorAll('video');
407
+ // 播放当前 active slide 中的视频
408
+ const activeSlide = block.querySelector('.swiper-slide-active');
409
+ const media = getVisibleDisplayMedias(activeSlide);
410
+ // 重置进度条
411
+ if (isDesktop) {
412
+ const activeBullet = block.querySelector(
413
+ '.swiper-pagination-bullet-active'
414
+ );
415
+ const progressBar = activeBullet.querySelector('.progress-line');
416
+ if (progressBar) {
417
+ progressBar.style.transition = 'none';
418
+ progressBar.style.width = '0';
419
+ }
420
+ }
421
+ if (media.type === 'video') {
422
+ allvideo.forEach((item) => {
423
+ if (item === media.video) {
424
+ media.video.currentTime = 0;
425
+ if (media.video.paused) {
426
+ media.video.play();
427
+ }
428
+
429
+ if('{{ block.settings.if_autoplay }}' == 'true') {
430
+ updataMediaProgress('video', media.video);
431
+ }
432
+ } else {
433
+ item.pause();
434
+ }
435
+ });
436
+ } else if (media.type === 'image') {
437
+ // 处理图片的情况
438
+ if('{{ block.settings.if_autoplay }}' == 'true') {
439
+ updataMediaProgress('image', media.image);
440
+ }
441
+ allvideo.forEach((item) => {
442
+ item.pause();
443
+ });
444
+ }
445
+ }
446
+ });
447
+ </script>
448
+
449
+ {% schema %}
450
+ {
451
+ "name": "Video Swiper Preview",
452
+ "class": "zz-video-swiper-preview-block",
453
+ "settings": [
454
+ {
455
+ "type": "color",
456
+ "id": "bg_color",
457
+ "default": "#ffffff",
458
+ "label": "背景色"
459
+ },
460
+
461
+ {
462
+ "type": "color",
463
+ "id": "pagination_color",
464
+ "default": "#ffffff",
465
+ "label": "轮播导航圆圈颜色"
466
+ },
467
+ {
468
+ "type": "color",
469
+ "id": "mb_pagination_color",
470
+ "default": "#000000",
471
+ "label": "移动端轮播导航圆圈颜色"
472
+ },
473
+ {
474
+ "type": "checkbox",
475
+ "id": "if_loop",
476
+ "label": "是否循环播放",
477
+ "default": false
478
+ },
479
+ {
480
+ "type": "checkbox",
481
+ "id": "if_autoplay",
482
+ "label": "是否自动轮播",
483
+ "default": false
484
+ },
485
+ {
486
+ "type": "checkbox",
487
+ "id": "has_gradient",
488
+ "label": "是否有左右渐变色",
489
+ "default": false
490
+ },
491
+ {
492
+ "type": "text",
493
+ "id": "gradient_color_left",
494
+ "label": "渐变色左边颜色",
495
+ "default": "linear-gradient(270deg, rgba(255,255,255, 0) 0%, rgba(255,255,255, 1) 40%)",
496
+ "visible_if": "{{ block.settings.has_gradient == true }}"
497
+ },
498
+ {
499
+ "type": "text",
500
+ "id": "gradient_color_right",
501
+ "label": "渐变色右边颜色",
502
+ "default": "linear-gradient(90deg, rgba(255,255,255, 0) 0%, rgba(255,255,255, 1) 40%)",
503
+ "visible_if": "{{ block.settings.has_gradient == true }}"
504
+ },
505
+ {
506
+ "type": "select",
507
+ "id": "prev_next_type",
508
+ "label": "prev next 颜色",
509
+ "options": [
510
+ { "value": "dark", "label": "黑色" },
511
+ { "value": "light", "label": "白色" },
512
+ ],
513
+ "default": "dark"
514
+ },
515
+ {
516
+ "type": "image_picker",
517
+ "id": "prev_icon",
518
+ "label": "轮播上一张图标 Mobile"
519
+ },
520
+ {
521
+ "type": "image_picker",
522
+ "id": "next_icon",
523
+ "label": "轮播下一张图标 Mobile"
524
+ },
525
+ {
526
+ "type": "checkbox",
527
+ "id": "has_title_and_content",
528
+ "label": "是否有标题与内容",
529
+ "default": true
530
+ }
531
+ ],
532
+ "blocks": [
533
+ {
534
+ "type": "zz-video-swiper-perview-item"
535
+ }
536
+ ],
537
+ "presets": [
538
+ {
539
+ "name": "可预览轮播图",
540
+ "settings": {
541
+ "bg_color": "#ffffff",
542
+ "pagination_color": "#ffffff",
543
+ "mb_pagination_color": "#000000",
544
+ "if_loop": false,
545
+ "if_autoplay": false,
546
+ "has_gradient": true,
547
+ "gradient_color_left": "linear-gradient(270deg, rgba(255,255,255, 0) 0%, rgba(255,255,255, 1) 40%)",
548
+ "gradient_color_right": "linear-gradient(90deg, rgba(255,255,255, 0) 0%, rgba(255,255,255, 1) 40%)",
549
+ "prev_next_type": "dark",
550
+ "has_title_and_content": true
551
+ },
552
+ "blocks": [
553
+ {
554
+ "type": "zz-video-swiper-perview-item",
555
+ "settings": {
556
+ "poster_pc": "shopify://shop_images/preset_pc_swiper_video_poster.png",
557
+ "poster_mb": "shopify://shop_images/preset_mobile_swiper_video_poster.png",
558
+ "has_title_and_content": true,
559
+ "heading": "Item Name",
560
+ "title_color": "#333232",
561
+ "row_content": "<p>Description set here, Description set here.</p>",
562
+ "content_color": "#5d544c",
563
+ },
564
+ },
565
+ {
566
+ "type": "zz-video-swiper-perview-item",
567
+ "settings": {
568
+ "poster_pc": "shopify://shop_images/preset_pc_swiper_video_poster_1.png",
569
+ "poster_mb": "shopify://shop_images/preset_mobile_swiper_video_poster_1.png",
570
+ "has_title_and_content": true,
571
+ "heading": "Item Name",
572
+ "title_color": "#333232",
573
+ "row_content": "<p>Description set here, Description set here.</p>",
574
+ "content_color": "#5d544c",
575
+ },
576
+
577
+ }
578
+ ]
579
+ }
580
+ ]
581
+ }
582
+ {% endschema %}
@@ -0,0 +1,4 @@
1
+ {
2
+
3
+ }
4
+
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "zz-shopify-components",
3
+ "version": "0.0.1-beta.1",
4
+ "description": "Reusable Shopify components for theme projects",
5
+ "keywords": ["shopify", "theme", "components"],
6
+ "license": "CC BY-NC-ND",
7
+ "bin": {
8
+ "sync-components-cli": "./scripts/postinstall.js"
9
+ },
10
+ "scripts": {
11
+ "dev": "concurrently -c \"auto\" \"npm:dev:*\"",
12
+ "dev:tailwind": "npx tailwindcss -i ./style.css -o ./assets/tailwind.css --watch",
13
+ "dev:shopify": "shopify theme dev --environment fake-us --error-overlay silent",
14
+ "postinstall": "node scripts/postinstall.js"
15
+ },
16
+ "devDependencies": {
17
+ "@shopify/prettier-plugin-liquid": "^1.5.0",
18
+ "concurrently": "^9.0.0",
19
+ "daisyui": "^4.12.23",
20
+ "prettier": "^3.3.3",
21
+ "tailwindcss": "^3.4.10"
22
+ }
23
+ }
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env node
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const fse = require('fs-extra');
5
+
6
+ const COMPONENT_DIRS = ['sections', 'blocks', 'snippets', 'assets', 'locales'];
7
+ const ROOT_DIR = path.resolve(__dirname); // 组件库自身
8
+ const TARGET_DIR = process.cwd(); // 使用组件库的项目目录
9
+
10
+ // 读取 ignore 配置
11
+ let ignoreList = [];
12
+ const configPath = path.join(ROOT_DIR, 'component.config.json');
13
+
14
+ if (fs.existsSync(configPath)) {
15
+ try {
16
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
17
+ ignoreList = config.ignore || [];
18
+ } catch (e) {
19
+ console.warn('[postinstall] Failed to parse component.config.json', e);
20
+ }
21
+ }
22
+
23
+ // 是否应忽略某个文件
24
+ const shouldIgnore = (relativePath) => {
25
+ return ignoreList.includes(relativePath.replace(/\\/g, '/'));
26
+ };
27
+
28
+ // 拷贝文件逻辑
29
+ COMPONENT_DIRS.forEach((dirName) => {
30
+ const sourceDir = path.join(ROOT_DIR, dirName);
31
+ const targetDir = path.join(TARGET_DIR, dirName);
32
+
33
+ if (!fs.existsSync(sourceDir)) return;
34
+
35
+ fse.readdirSync(sourceDir).forEach((file) => {
36
+ const relPath = `${dirName}/${file}`;
37
+ if (shouldIgnore(relPath)) {
38
+ console.log(`[postinstall] Ignored: ${relPath}`);
39
+ return;
40
+ }
41
+
42
+ const src = path.join(sourceDir, file);
43
+ const dest = path.join(targetDir, file);
44
+ fse.copySync(src, dest, { overwrite: true });
45
+ console.log(`[postinstall] Copied: ${relPath}`);
46
+ });
47
+ });
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ console.log('Running postinstall...');
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const PACKAGE_ROOT = path.resolve(__dirname, '..');
7
+ const PROJECT_ROOT = process.cwd();
8
+
9
+ const folders = ['sections', 'blocks', 'snippets', 'assets', 'locales'];
10
+
11
+ function copyDir(src, dest) {
12
+ if (!fs.existsSync(src)) return;
13
+
14
+ if (!fs.existsSync(dest)) {
15
+ fs.mkdirSync(dest, { recursive: true });
16
+ }
17
+
18
+ const items = fs.readdirSync(src);
19
+ for (const item of items) {
20
+ const srcPath = path.join(src, item);
21
+ const destPath = path.join(dest, item);
22
+ const stat = fs.statSync(srcPath);
23
+
24
+ if (stat.isDirectory()) {
25
+ copyDir(srcPath, destPath);
26
+ } else {
27
+ fs.copyFileSync(srcPath, destPath); // 覆盖
28
+ console.log(`✅ Copied: ${path.relative(PROJECT_ROOT, destPath)}`);
29
+ }
30
+ }
31
+ }
32
+
33
+ console.log('\n🧩 [component-lib] Start syncing components to project...');
34
+ for (const folder of folders) {
35
+ const from = path.join(PACKAGE_ROOT, folder);
36
+ const to = path.join(PROJECT_ROOT, folder);
37
+ copyDir(from, to);
38
+ }
39
+ console.log('🎉 [component-lib] Sync complete.\n');