@o2vend/theme-cli 1.0.32
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/README.md +425 -0
- package/assets/Logo_o2vend.png +0 -0
- package/assets/favicon.png +0 -0
- package/assets/logo-white.png +0 -0
- package/bin/o2vend +42 -0
- package/config/widget-map.json +50 -0
- package/lib/commands/check.js +201 -0
- package/lib/commands/generate.js +33 -0
- package/lib/commands/init.js +214 -0
- package/lib/commands/optimize.js +216 -0
- package/lib/commands/package.js +208 -0
- package/lib/commands/serve.js +105 -0
- package/lib/commands/validate.js +191 -0
- package/lib/lib/api-client.js +357 -0
- package/lib/lib/dev-server.js +2618 -0
- package/lib/lib/file-watcher.js +80 -0
- package/lib/lib/hot-reload.js +106 -0
- package/lib/lib/liquid-engine.js +822 -0
- package/lib/lib/liquid-filters.js +671 -0
- package/lib/lib/mock-api-server.js +989 -0
- package/lib/lib/mock-data.js +1468 -0
- package/lib/lib/widget-service.js +321 -0
- package/package.json +70 -0
- package/test-theme/README.md +27 -0
- package/test-theme/assets/async-sections.js +446 -0
- package/test-theme/assets/cart-drawer.js +463 -0
- package/test-theme/assets/cart-manager.js +223 -0
- package/test-theme/assets/checkout-price-handler.js +368 -0
- package/test-theme/assets/components.css +4629 -0
- package/test-theme/assets/delivery-zone.css +299 -0
- package/test-theme/assets/delivery-zone.js +396 -0
- package/test-theme/assets/logo.png +0 -0
- package/test-theme/assets/sections.css +48 -0
- package/test-theme/assets/theme.css +3500 -0
- package/test-theme/assets/theme.js +3745 -0
- package/test-theme/config/settings_data.json +292 -0
- package/test-theme/config/settings_schema.json +1050 -0
- package/test-theme/layout/theme.liquid +195 -0
- package/test-theme/locales/en.default.json +260 -0
- package/test-theme/sections/content-fallback.liquid +53 -0
- package/test-theme/sections/content.liquid +57 -0
- package/test-theme/sections/footer-fallback.liquid +328 -0
- package/test-theme/sections/footer.liquid +278 -0
- package/test-theme/sections/header-fallback.liquid +1805 -0
- package/test-theme/sections/header.liquid +1145 -0
- package/test-theme/sections/hero-fallback.liquid +212 -0
- package/test-theme/sections/hero.liquid +136 -0
- package/test-theme/snippets/account-sidebar.liquid +200 -0
- package/test-theme/snippets/add-to-cart-modal.liquid +484 -0
- package/test-theme/snippets/breadcrumbs.liquid +134 -0
- package/test-theme/snippets/cart-drawer.liquid +467 -0
- package/test-theme/snippets/delivery-zone-city-selector.liquid +79 -0
- package/test-theme/snippets/delivery-zone-modal.liquid +337 -0
- package/test-theme/snippets/delivery-zone-search.liquid +78 -0
- package/test-theme/snippets/icon.liquid +105 -0
- package/test-theme/snippets/login-modal.liquid +346 -0
- package/test-theme/snippets/mega-menu.liquid +812 -0
- package/test-theme/snippets/news-thumbnail.liquid +187 -0
- package/test-theme/snippets/pagination.liquid +120 -0
- package/test-theme/snippets/price.liquid +92 -0
- package/test-theme/snippets/product-card-related.liquid +78 -0
- package/test-theme/snippets/product-card-simple.liquid +41 -0
- package/test-theme/snippets/product-card.liquid +697 -0
- package/test-theme/snippets/rating.liquid +85 -0
- package/test-theme/snippets/skeleton-collection-grid.liquid +114 -0
- package/test-theme/snippets/skeleton-product-card.liquid +124 -0
- package/test-theme/snippets/skeleton-product-grid.liquid +34 -0
- package/test-theme/snippets/social-sharing.liquid +185 -0
- package/test-theme/templates/account/dashboard.liquid +401 -0
- package/test-theme/templates/account/loyalty-redemption.liquid +405 -0
- package/test-theme/templates/account/loyalty.liquid +588 -0
- package/test-theme/templates/account/order-detail.liquid +230 -0
- package/test-theme/templates/account/orders.liquid +349 -0
- package/test-theme/templates/account/profile.liquid +758 -0
- package/test-theme/templates/account/register.liquid +232 -0
- package/test-theme/templates/account/return-orders.liquid +348 -0
- package/test-theme/templates/account/store-credit.liquid +464 -0
- package/test-theme/templates/account/subscriptions.liquid +601 -0
- package/test-theme/templates/account/wishlist.liquid +419 -0
- package/test-theme/templates/address-book.liquid +1092 -0
- package/test-theme/templates/categories.liquid +452 -0
- package/test-theme/templates/checkout.liquid +4511 -0
- package/test-theme/templates/error.liquid +384 -0
- package/test-theme/templates/index.liquid +11 -0
- package/test-theme/templates/login.liquid +185 -0
- package/test-theme/templates/order-confirmation.liquid +720 -0
- package/test-theme/templates/page.liquid +297 -0
- package/test-theme/templates/product-detail.liquid +4363 -0
- package/test-theme/templates/products.liquid +518 -0
- package/test-theme/templates/search.liquid +922 -0
- package/test-theme/theme.json.example +19 -0
- package/test-theme/widgets/brand-carousel.liquid +676 -0
- package/test-theme/widgets/brand.liquid +245 -0
- package/test-theme/widgets/carousel.liquid +843 -0
- package/test-theme/widgets/category-list-carousel.liquid +656 -0
- package/test-theme/widgets/category-list.liquid +340 -0
- package/test-theme/widgets/category.liquid +475 -0
- package/test-theme/widgets/discount-time.liquid +176 -0
- package/test-theme/widgets/footer-menu.liquid +695 -0
- package/test-theme/widgets/footer.liquid +179 -0
- package/test-theme/widgets/gallery.liquid +271 -0
- package/test-theme/widgets/header-menu.liquid +932 -0
- package/test-theme/widgets/header.liquid +159 -0
- package/test-theme/widgets/html.liquid +214 -0
- package/test-theme/widgets/news.liquid +217 -0
- package/test-theme/widgets/product-canvas.liquid +235 -0
- package/test-theme/widgets/product-carousel.liquid +502 -0
- package/test-theme/widgets/product.liquid +45 -0
- package/test-theme/widgets/recently-viewed.liquid +26 -0
- package/test-theme/widgets/shared/product-grid.liquid +339 -0
- package/test-theme/widgets/simple-product.liquid +42 -0
- package/test-theme/widgets/single-product.liquid +610 -0
- package/test-theme/widgets/spacebar-carousel.liquid +663 -0
- package/test-theme/widgets/spacebar.liquid +279 -0
- package/test-theme/widgets/splash.liquid +378 -0
- package/test-theme/widgets/testimonial-carousel.liquid +709 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
{% liquid
|
|
2
|
+
assign widget_settings = widget.settings
|
|
3
|
+
assign widget_data = widget.data
|
|
4
|
+
|
|
5
|
+
comment
|
|
6
|
+
Dynamic Widget: Brands come from widget_data.brands (enriched by WidgetService)
|
|
7
|
+
Settings come from widget_settings
|
|
8
|
+
endcomment
|
|
9
|
+
assign brands = widget_data.Brands | default: widget_data.brands
|
|
10
|
+
assign show_container = widget_settings.showContainer
|
|
11
|
+
assign show_bottom_margin = widget_settings.showWidgetBottomMargin
|
|
12
|
+
assign show_widget_title_raw = widget_settings.showWidgetTitle | default: 'Yes'
|
|
13
|
+
if show_widget_title_raw == null or show_widget_title_raw == blank or show_widget_title_raw == 'null'
|
|
14
|
+
assign show_widget_title = true
|
|
15
|
+
else
|
|
16
|
+
if show_widget_title_raw == 'Yes'
|
|
17
|
+
assign show_widget_title = true
|
|
18
|
+
elsif show_widget_title_raw == true
|
|
19
|
+
assign show_widget_title = true
|
|
20
|
+
else
|
|
21
|
+
assign show_widget_title = false
|
|
22
|
+
endif
|
|
23
|
+
endif
|
|
24
|
+
assign widget_title_alignment_raw = widget_settings.widgetTitleAlignment | default: 'center'
|
|
25
|
+
assign widget_title_alignment = widget_title_alignment_raw | downcase
|
|
26
|
+
if widget_title_alignment != 'left' and widget_title_alignment != 'right' and widget_title_alignment != 'center'
|
|
27
|
+
assign widget_title_alignment = 'center'
|
|
28
|
+
endif
|
|
29
|
+
assign background_color = widget_settings.backgroundColor
|
|
30
|
+
assign text_color = widget_settings.textColor
|
|
31
|
+
assign heading = widget_settings.title
|
|
32
|
+
assign subtitle = widget_settings.subtitle
|
|
33
|
+
%}
|
|
34
|
+
|
|
35
|
+
<section class="widget widget-brand" data-widget-id="{{ widget.id }}"{% if background_color and background_color != 'null' %} style="background-color: {{ background_color }};"{% endif %}>
|
|
36
|
+
<div class="widget-brand__inner">
|
|
37
|
+
{% if show_widget_title %}
|
|
38
|
+
{% if heading or subtitle %}
|
|
39
|
+
<header class="widget-header"{% if widget_title_alignment %} style="text-align: {{ widget_title_alignment }};"{% endif %}{% if text_color and text_color != 'null' %} style="color: {{ text_color }};"{% endif %}>
|
|
40
|
+
{% if heading %}<h2 class="widget-title">{{ heading }}</h2>{% endif %}
|
|
41
|
+
{% if subtitle %}<p class="widget-subtitle">{{ subtitle }}</p>{% endif %}
|
|
42
|
+
</header>
|
|
43
|
+
{% endif %}
|
|
44
|
+
{% endif %}
|
|
45
|
+
|
|
46
|
+
{% if brands and brands.size > 0 %}
|
|
47
|
+
<div class="widget-brand__grid">
|
|
48
|
+
{% for brand in brands %}
|
|
49
|
+
{% assign brand_id = brand.Id | default: brand.id | default: brand.brandId %}
|
|
50
|
+
{% assign brand_name = brand.Name | default: brand.name %}
|
|
51
|
+
{% assign brand_slug = brand.Slug | default: brand.slug %}
|
|
52
|
+
{% assign brand_url = brand.Url | default: brand.url | default: brand.link %}
|
|
53
|
+
{% if brand_url == blank %}
|
|
54
|
+
{% if brand_slug and brand_slug != blank %}
|
|
55
|
+
{% assign brand_url = brand_slug %}
|
|
56
|
+
{% else %}
|
|
57
|
+
{% assign brand_url = '#' %}
|
|
58
|
+
{% endif %}
|
|
59
|
+
{% endif %}
|
|
60
|
+
|
|
61
|
+
{% comment %} Image fallback: thumbnailImage.url > Logo > logo > image {% endcomment %}
|
|
62
|
+
{% assign brand_image = nil %}
|
|
63
|
+
{% if brand.thumbnailImage and brand.thumbnailImage.url %}
|
|
64
|
+
{% assign brand_image = brand.thumbnailImage.url %}
|
|
65
|
+
{% elsif brand.ThumbnailImage and brand.ThumbnailImage.Url %}
|
|
66
|
+
{% assign brand_image = brand.ThumbnailImage.Url %}
|
|
67
|
+
{% elsif brand.Logo %}
|
|
68
|
+
{% assign brand_image = brand.Logo %}
|
|
69
|
+
{% elsif brand.logo %}
|
|
70
|
+
{% assign brand_image = brand.logo %}
|
|
71
|
+
{% elsif brand.image %}
|
|
72
|
+
{% assign brand_image = brand.image %}
|
|
73
|
+
{% elsif brand.Image %}
|
|
74
|
+
{% assign brand_image = brand.Image %}
|
|
75
|
+
{% endif %}
|
|
76
|
+
|
|
77
|
+
<a href="{{ brand_url }}" class="widget-brand__item" aria-label="{{ brand_name }}">
|
|
78
|
+
{% if brand_image != blank and brand_image != '' and brand_image != 'null' %}
|
|
79
|
+
{% if brand_image contains 'http://' or brand_image contains 'https://' %}
|
|
80
|
+
{% assign brand_image_src = brand_image %}
|
|
81
|
+
{% else %}
|
|
82
|
+
{% assign brand_image_src = brand_image | asset_url %}
|
|
83
|
+
{% endif %}
|
|
84
|
+
<img src="{{ brand_image_src }}" alt="{{ brand_name }}" width="200" height="60" loading="lazy" onerror="this.style.display='none'; this.nextElementSibling.style.display='block';">
|
|
85
|
+
<span class="widget-brand__name widget-brand__name--fallback" style="display: none;">{{ brand_name }}</span>
|
|
86
|
+
{% else %}
|
|
87
|
+
<span class="widget-brand__name">{{ brand_name }}</span>
|
|
88
|
+
{% endif %}
|
|
89
|
+
</a>
|
|
90
|
+
{% endfor %}
|
|
91
|
+
</div>
|
|
92
|
+
{% else %}
|
|
93
|
+
<div class="widget-empty">
|
|
94
|
+
<p>{{ widget_settings.empty_state | default: 'No brands to display yet.' }}</p>
|
|
95
|
+
</div>
|
|
96
|
+
{% endif %}
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
<style>
|
|
100
|
+
.widget-brand {
|
|
101
|
+
{% if show_bottom_margin == 'Yes' %}
|
|
102
|
+
padding: 2.5rem 0;
|
|
103
|
+
{% elsif show_bottom_margin == 'No' %}
|
|
104
|
+
padding: 2.5rem 0 0;
|
|
105
|
+
{% else %}
|
|
106
|
+
padding: 2.5rem 0;
|
|
107
|
+
{% endif %}
|
|
108
|
+
background: {{ background_color | default: widget_settings.background_color | default: 'transparent' }};
|
|
109
|
+
}
|
|
110
|
+
.widget-brand__inner {
|
|
111
|
+
{% if show_container == 'Yes' %}
|
|
112
|
+
max-width: 1400px;
|
|
113
|
+
margin-left: auto;
|
|
114
|
+
margin-right: auto;
|
|
115
|
+
{% endif %}
|
|
116
|
+
padding-left: 24px;
|
|
117
|
+
padding-right: 24px;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.widget-brand .widget-header {
|
|
121
|
+
margin-bottom: 32px;
|
|
122
|
+
position: static;
|
|
123
|
+
z-index: auto;
|
|
124
|
+
}
|
|
125
|
+
.widget-brand .widget-title {
|
|
126
|
+
font-size: 1.4rem;
|
|
127
|
+
font-weight: 500;
|
|
128
|
+
line-height: 1.3;
|
|
129
|
+
color: #111;
|
|
130
|
+
margin: 0 0 8px 0;
|
|
131
|
+
letter-spacing: -0.01em;
|
|
132
|
+
}
|
|
133
|
+
.widget-brand .widget-subtitle {
|
|
134
|
+
font-size: 14px;
|
|
135
|
+
color: #6b7280;
|
|
136
|
+
margin: 0;
|
|
137
|
+
}
|
|
138
|
+
.widget-brand__grid {
|
|
139
|
+
display: grid;
|
|
140
|
+
gap: 24px;
|
|
141
|
+
grid-template-columns: repeat(6, 1fr);
|
|
142
|
+
align-items: stretch;
|
|
143
|
+
}
|
|
144
|
+
.widget-brand__item {
|
|
145
|
+
position: relative;
|
|
146
|
+
display: flex;
|
|
147
|
+
align-items: center;
|
|
148
|
+
justify-content: center;
|
|
149
|
+
padding: 12px;
|
|
150
|
+
border-radius: 12px;
|
|
151
|
+
background: #fff;
|
|
152
|
+
box-shadow: 0 4px 12px rgba(15, 23, 42, 0.08);
|
|
153
|
+
min-height: 100px;
|
|
154
|
+
text-decoration: none;
|
|
155
|
+
color: inherit;
|
|
156
|
+
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
|
157
|
+
overflow: hidden;
|
|
158
|
+
}
|
|
159
|
+
.widget-brand__item:hover {
|
|
160
|
+
transform: translateY(-4px);
|
|
161
|
+
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);
|
|
162
|
+
}
|
|
163
|
+
.widget-brand__item img {
|
|
164
|
+
max-width: 100%;
|
|
165
|
+
max-height: 60px;
|
|
166
|
+
width: auto;
|
|
167
|
+
height: auto;
|
|
168
|
+
object-fit: contain;
|
|
169
|
+
}
|
|
170
|
+
.widget-brand__name {
|
|
171
|
+
font-size: 14px;
|
|
172
|
+
font-weight: 600;
|
|
173
|
+
color: #111;
|
|
174
|
+
text-align: center;
|
|
175
|
+
line-height: 1.3;
|
|
176
|
+
word-break: break-word;
|
|
177
|
+
letter-spacing: -0.01em;
|
|
178
|
+
}
|
|
179
|
+
.widget-brand__name--fallback {
|
|
180
|
+
position: absolute;
|
|
181
|
+
top: 50%;
|
|
182
|
+
left: 50%;
|
|
183
|
+
transform: translate(-50%, -50%);
|
|
184
|
+
width: 100%;
|
|
185
|
+
padding: 0 8px;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/* Tablet: 4 columns */
|
|
189
|
+
@media (max-width: 1024px) {
|
|
190
|
+
.widget-brand__grid {
|
|
191
|
+
grid-template-columns: repeat(4, 1fr);
|
|
192
|
+
gap: 20px;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/* Mobile: 3 columns */
|
|
197
|
+
@media (max-width: 768px) {
|
|
198
|
+
.widget-brand {
|
|
199
|
+
padding: 32px 0;
|
|
200
|
+
}
|
|
201
|
+
.widget-brand__inner {
|
|
202
|
+
padding: 0 16px;
|
|
203
|
+
}
|
|
204
|
+
.widget-brand .widget-header {
|
|
205
|
+
margin-bottom: 24px;
|
|
206
|
+
}
|
|
207
|
+
.widget-brand .widget-title {
|
|
208
|
+
font-size: 1.3rem;
|
|
209
|
+
}
|
|
210
|
+
.widget-brand__grid {
|
|
211
|
+
grid-template-columns: repeat(3, 1fr);
|
|
212
|
+
gap: 16px;
|
|
213
|
+
}
|
|
214
|
+
.widget-brand__item {
|
|
215
|
+
padding: 16px;
|
|
216
|
+
min-height: 80px;
|
|
217
|
+
}
|
|
218
|
+
.widget-brand__item img {
|
|
219
|
+
max-height: 40px;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/* Small Mobile: 2 columns */
|
|
224
|
+
@media (max-width: 480px) {
|
|
225
|
+
.widget-brand__inner {
|
|
226
|
+
padding: 0 12px;
|
|
227
|
+
}
|
|
228
|
+
.widget-brand__grid {
|
|
229
|
+
grid-template-columns: repeat(2, 1fr);
|
|
230
|
+
gap: 12px;
|
|
231
|
+
}
|
|
232
|
+
.widget-brand__item {
|
|
233
|
+
padding: 12px;
|
|
234
|
+
min-height: 70px;
|
|
235
|
+
border-radius: 8px;
|
|
236
|
+
}
|
|
237
|
+
.widget-brand__item img {
|
|
238
|
+
max-height: 36px;
|
|
239
|
+
}
|
|
240
|
+
.widget-brand .widget-title {
|
|
241
|
+
font-size: 1.2rem;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
</style>
|
|
245
|
+
</section>
|