@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,159 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Header Widget - HTML Content/Announcement Bar Only
|
|
3
|
+
This widget displays only the HTML content announcement bar.
|
|
4
|
+
The actual header menu (logo, navigation, search, cart) should be handled by HeaderMenuWidget.
|
|
5
|
+
{% endcomment %}
|
|
6
|
+
|
|
7
|
+
{% liquid
|
|
8
|
+
assign widget_settings = widget.settings
|
|
9
|
+
assign widget_data = widget.data
|
|
10
|
+
|
|
11
|
+
comment
|
|
12
|
+
Static Widget: Content comes from widget_data.content (header configuration)
|
|
13
|
+
Settings come from widget_settings
|
|
14
|
+
endcomment
|
|
15
|
+
|
|
16
|
+
assign content_data = widget_data.content | default: widget.content
|
|
17
|
+
if content_data.size > 0
|
|
18
|
+
assign header_config = content_data.first
|
|
19
|
+
else
|
|
20
|
+
assign header_config = content_data
|
|
21
|
+
endif
|
|
22
|
+
|
|
23
|
+
assign html_content_raw = header_config.HtmlContent | default: header_config.htmlContent
|
|
24
|
+
assign html_content = blank
|
|
25
|
+
if html_content_raw and html_content_raw != blank and html_content_raw != 'null'
|
|
26
|
+
assign html_content = html_content_raw
|
|
27
|
+
endif
|
|
28
|
+
assign hide_close_button = widget_settings.hideCloseButton
|
|
29
|
+
if hide_close_button == nil and header_config and header_config.HideCloseButton != nil
|
|
30
|
+
assign hide_close_button = header_config.HideCloseButton
|
|
31
|
+
endif
|
|
32
|
+
assign background_color = widget_settings.backgroundColor
|
|
33
|
+
if background_color == nil and header_config and header_config.BackgroundColor != nil
|
|
34
|
+
assign background_color = header_config.BackgroundColor
|
|
35
|
+
endif
|
|
36
|
+
assign text_color = widget_settings.textColor
|
|
37
|
+
if text_color == nil and header_config and header_config.TextColor != nil
|
|
38
|
+
assign text_color = header_config.TextColor
|
|
39
|
+
endif
|
|
40
|
+
%}
|
|
41
|
+
|
|
42
|
+
{% if html_content and html_content != blank and html_content != 'null' %}
|
|
43
|
+
<div class="widget-header-announcement" data-widget-id="{{ widget.id }}">
|
|
44
|
+
<div class="widget-header-announcement__bar"{% if background_color and background_color != 'null' and background_color != blank %} style="background-color: {{ background_color }};"{% endif %}>
|
|
45
|
+
<div class="widget-header-announcement__content"{% if text_color and text_color != 'null' and text_color != blank %} style="color: {{ text_color }};"{% endif %}>
|
|
46
|
+
{{ html_content }}
|
|
47
|
+
</div>
|
|
48
|
+
{% unless hide_close_button %}
|
|
49
|
+
<button class="widget-header-announcement__close" aria-label="Close announcement" data-announcement-close>
|
|
50
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
51
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
52
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
53
|
+
</svg>
|
|
54
|
+
</button>
|
|
55
|
+
{% endunless %}
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
{% endif %}
|
|
59
|
+
|
|
60
|
+
<style>
|
|
61
|
+
/* Announcement Bar Styles */
|
|
62
|
+
.widget-header-announcement__bar {
|
|
63
|
+
display: flex;
|
|
64
|
+
align-items: center;
|
|
65
|
+
justify-content: center;
|
|
66
|
+
position: relative;
|
|
67
|
+
padding: 12px 24px;
|
|
68
|
+
background: #111;
|
|
69
|
+
color: #fff;
|
|
70
|
+
text-align: center;
|
|
71
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.widget-header-announcement__bar.hidden {
|
|
75
|
+
display: none;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.widget-header-announcement__content {
|
|
79
|
+
flex: 1;
|
|
80
|
+
font-size: 14px;
|
|
81
|
+
line-height: 1.5;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.widget-header-announcement__content p {
|
|
85
|
+
margin: 0;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.widget-header-announcement__content img {
|
|
89
|
+
max-width: 100%;
|
|
90
|
+
height: auto;
|
|
91
|
+
vertical-align: middle;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.widget-header-announcement__close {
|
|
95
|
+
position: absolute;
|
|
96
|
+
right: 12px;
|
|
97
|
+
top: 50%;
|
|
98
|
+
transform: translateY(-50%);
|
|
99
|
+
background: transparent;
|
|
100
|
+
border: none;
|
|
101
|
+
color: inherit;
|
|
102
|
+
cursor: pointer;
|
|
103
|
+
padding: 4px;
|
|
104
|
+
display: flex;
|
|
105
|
+
align-items: center;
|
|
106
|
+
justify-content: center;
|
|
107
|
+
opacity: 0.7;
|
|
108
|
+
transition: opacity 0.2s ease;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.widget-header-announcement__close:hover {
|
|
112
|
+
opacity: 1;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.widget-header-announcement__close svg {
|
|
116
|
+
width: 16px;
|
|
117
|
+
height: 16px;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
@media (max-width: 768px) {
|
|
121
|
+
.widget-header-announcement__bar {
|
|
122
|
+
padding: 10px 40px 10px 16px;
|
|
123
|
+
font-size: 13px;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.widget-header-announcement__close {
|
|
127
|
+
right: 8px;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
</style>
|
|
131
|
+
|
|
132
|
+
<script>
|
|
133
|
+
// Handle announcement bar close button
|
|
134
|
+
(function() {
|
|
135
|
+
const announcementCloseBtn = document.querySelector('[data-announcement-close]');
|
|
136
|
+
if (announcementCloseBtn) {
|
|
137
|
+
announcementCloseBtn.addEventListener('click', function() {
|
|
138
|
+
const announcement = this.closest('.widget-header-announcement__bar');
|
|
139
|
+
if (announcement) {
|
|
140
|
+
announcement.classList.add('hidden');
|
|
141
|
+
// Store in sessionStorage to remember it's closed for this session
|
|
142
|
+
const widgetId = announcement.closest('[data-widget-id]')?.getAttribute('data-widget-id');
|
|
143
|
+
if (widgetId) {
|
|
144
|
+
sessionStorage.setItem(`announcement-closed-${widgetId}`, 'true');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Check if announcement was previously closed in this session
|
|
150
|
+
const widgetId = announcementCloseBtn.closest('[data-widget-id]')?.getAttribute('data-widget-id');
|
|
151
|
+
if (widgetId && sessionStorage.getItem(`announcement-closed-${widgetId}`) === 'true') {
|
|
152
|
+
const announcement = announcementCloseBtn.closest('.widget-header-announcement__bar');
|
|
153
|
+
if (announcement) {
|
|
154
|
+
announcement.classList.add('hidden');
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
})();
|
|
159
|
+
</script>
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
{% liquid
|
|
2
|
+
assign widget_settings = widget.settings
|
|
3
|
+
assign widget_content = widget.content
|
|
4
|
+
assign widget_data = widget.data
|
|
5
|
+
|
|
6
|
+
assign title = widget_content.Title | default: widget_content.title | default: widget_settings.title
|
|
7
|
+
|
|
8
|
+
comment
|
|
9
|
+
HTML content priority order:
|
|
10
|
+
1. HtmlContent / htmlContent - direct field from widget (highest priority)
|
|
11
|
+
2. widget.data.htmlContent - normalized HtmlContent
|
|
12
|
+
3. widget_content.HtmlContent / htmlContent - from content JSON
|
|
13
|
+
4. widget_content.Html / html - from content JSON
|
|
14
|
+
5. Other fallbacks for backward compatibility
|
|
15
|
+
endcomment
|
|
16
|
+
|
|
17
|
+
if widget.htmlContent
|
|
18
|
+
assign html_content = widget.htmlContent
|
|
19
|
+
elsif widget.HtmlContent
|
|
20
|
+
assign html_content = widget.HtmlContent
|
|
21
|
+
elsif widget_data.htmlContent
|
|
22
|
+
assign html_content = widget_data.htmlContent
|
|
23
|
+
elsif widget_content.Html
|
|
24
|
+
assign html_content = widget_content.Html
|
|
25
|
+
elsif widget_content.html
|
|
26
|
+
assign html_content = widget_content.html
|
|
27
|
+
elsif widget_content.HtmlContent
|
|
28
|
+
assign html_content = widget_content.HtmlContent
|
|
29
|
+
elsif widget_content.htmlContent
|
|
30
|
+
assign html_content = widget_content.htmlContent
|
|
31
|
+
elsif widget_content.Body
|
|
32
|
+
assign html_content = widget_content.Body
|
|
33
|
+
elsif widget_content.body
|
|
34
|
+
assign html_content = widget_content.body
|
|
35
|
+
elsif widget_content.Content
|
|
36
|
+
assign html_content = widget_content.Content
|
|
37
|
+
elsif widget_content.content
|
|
38
|
+
assign html_content = widget_content.content
|
|
39
|
+
elsif widget_settings.html
|
|
40
|
+
assign html_content = widget_settings.html
|
|
41
|
+
elsif widget_data.html
|
|
42
|
+
assign html_content = widget_data.html
|
|
43
|
+
else
|
|
44
|
+
assign html_content = ''
|
|
45
|
+
endif
|
|
46
|
+
|
|
47
|
+
assign show_container = widget_content.ShowContainer | default: widget_settings.show_container | default: 'Yes'
|
|
48
|
+
assign show_widget_title_raw = widget_content.ShowWidgetTitle | default: widget_settings.show_widget_title | default: 'Yes'
|
|
49
|
+
|
|
50
|
+
if show_widget_title_raw == null
|
|
51
|
+
assign show_widget_title = true
|
|
52
|
+
elsif show_widget_title_raw == blank
|
|
53
|
+
assign show_widget_title = true
|
|
54
|
+
elsif show_widget_title_raw == 'null'
|
|
55
|
+
assign show_widget_title = true
|
|
56
|
+
elsif show_widget_title_raw == 'Yes'
|
|
57
|
+
assign show_widget_title = true
|
|
58
|
+
elsif show_widget_title_raw == true
|
|
59
|
+
assign show_widget_title = true
|
|
60
|
+
else
|
|
61
|
+
assign show_widget_title = false
|
|
62
|
+
endif
|
|
63
|
+
assign widget_title_alignment_raw = widget_content.WidgetTitleAlignment | default: widget_settings.widget_title_alignment | default: 'center'
|
|
64
|
+
assign widget_title_alignment = widget_title_alignment_raw | downcase
|
|
65
|
+
if widget_title_alignment != 'left' and widget_title_alignment != 'right' and widget_title_alignment != 'center'
|
|
66
|
+
assign widget_title_alignment = 'center'
|
|
67
|
+
endif
|
|
68
|
+
assign background_color = widget_content.BackgroundColor | default: widget_settings.background_color
|
|
69
|
+
assign text_color = widget_content.TextColor | default: widget_settings.text_color
|
|
70
|
+
assign padding_top = widget_content.PaddingTop | default: widget_settings.padding_top
|
|
71
|
+
assign padding_bottom = widget_content.PaddingBottom | default: widget_settings.padding_bottom
|
|
72
|
+
%}
|
|
73
|
+
|
|
74
|
+
<section class="widget widget-html" data-widget-id="{{ widget.id }}"{% if background_color and background_color != blank and background_color != 'null' %} style="background-color: {{ background_color }};"{% endif %}>
|
|
75
|
+
<div class="widget-html__inner{% if show_container == 'No' %} widget-html__inner--full{% endif %}">
|
|
76
|
+
{% if show_widget_title %}
|
|
77
|
+
{% if title and title != blank %}
|
|
78
|
+
<h2 class="widget-title" style="text-align: {{ widget_title_alignment }};{% if text_color and text_color != blank %} color: {{ text_color }};{% endif %}">{{ title }}</h2>
|
|
79
|
+
{% endif %}
|
|
80
|
+
{% endif %}
|
|
81
|
+
|
|
82
|
+
{% if html_content and html_content != blank %}
|
|
83
|
+
<div class="widget-html__content"{% if text_color and text_color != blank and text_color != 'null' %} style="color: {{ text_color }};"{% endif %}>
|
|
84
|
+
{{ html_content }}
|
|
85
|
+
</div>
|
|
86
|
+
{% endif %}
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<style>
|
|
90
|
+
.widget-html {
|
|
91
|
+
padding: {{ padding_top | default: '40' }}px 0 {{ padding_bottom | default: '40' }}px;
|
|
92
|
+
}
|
|
93
|
+
.widget-html__inner {
|
|
94
|
+
max-width: 1400px;
|
|
95
|
+
margin: 0 auto;
|
|
96
|
+
padding: 0 24px;
|
|
97
|
+
}
|
|
98
|
+
.widget-html__inner--full {
|
|
99
|
+
max-width: none;
|
|
100
|
+
padding: 0;
|
|
101
|
+
}
|
|
102
|
+
.widget-html .widget-header {
|
|
103
|
+
position: static;
|
|
104
|
+
z-index: auto;
|
|
105
|
+
}
|
|
106
|
+
.widget-html .widget-title {
|
|
107
|
+
font-size: 1.4rem;
|
|
108
|
+
font-weight: 500;
|
|
109
|
+
line-height: 1.3;
|
|
110
|
+
color: #111;
|
|
111
|
+
margin: 0 0 8px 0;
|
|
112
|
+
letter-spacing: -0.01em;
|
|
113
|
+
}
|
|
114
|
+
.widget-html__content {
|
|
115
|
+
font-size: 16px;
|
|
116
|
+
line-height: 1.7;
|
|
117
|
+
color: #374151;
|
|
118
|
+
}
|
|
119
|
+
.widget-html__content :where(h1, h2, h3, h4, h5, h6) {
|
|
120
|
+
margin-top: 1.5em;
|
|
121
|
+
margin-bottom: 0.5em;
|
|
122
|
+
font-weight: 600;
|
|
123
|
+
line-height: 1.3;
|
|
124
|
+
color: #111;
|
|
125
|
+
}
|
|
126
|
+
.widget-html__content h1 { font-size: 2em; }
|
|
127
|
+
.widget-html__content h2 { font-size: 1.5em; }
|
|
128
|
+
.widget-html__content h3 { font-size: 1.25em; }
|
|
129
|
+
.widget-html__content h4 { font-size: 1.1em; }
|
|
130
|
+
.widget-html__content p {
|
|
131
|
+
margin-bottom: 1em;
|
|
132
|
+
}
|
|
133
|
+
.widget-html__content ul,
|
|
134
|
+
.widget-html__content ol {
|
|
135
|
+
margin: 1em 0;
|
|
136
|
+
padding-left: 1.5em;
|
|
137
|
+
}
|
|
138
|
+
.widget-html__content li {
|
|
139
|
+
margin-bottom: 0.5em;
|
|
140
|
+
}
|
|
141
|
+
.widget-html__content a {
|
|
142
|
+
color: #2563eb;
|
|
143
|
+
text-decoration: underline;
|
|
144
|
+
}
|
|
145
|
+
.widget-html__content a:hover {
|
|
146
|
+
color: #1d4ed8;
|
|
147
|
+
}
|
|
148
|
+
.widget-html__content img {
|
|
149
|
+
max-width: 100%;
|
|
150
|
+
height: auto;
|
|
151
|
+
border-radius: 8px;
|
|
152
|
+
}
|
|
153
|
+
.widget-html__content table {
|
|
154
|
+
width: 100%;
|
|
155
|
+
border-collapse: collapse;
|
|
156
|
+
margin: 1em 0;
|
|
157
|
+
}
|
|
158
|
+
.widget-html__content th,
|
|
159
|
+
.widget-html__content td {
|
|
160
|
+
padding: 12px;
|
|
161
|
+
border: 1px solid #e5e7eb;
|
|
162
|
+
text-align: left;
|
|
163
|
+
}
|
|
164
|
+
.widget-html__content th {
|
|
165
|
+
background: #f9fafb;
|
|
166
|
+
font-weight: 600;
|
|
167
|
+
}
|
|
168
|
+
.widget-html__content blockquote {
|
|
169
|
+
margin: 1.5em 0;
|
|
170
|
+
padding: 1em 1.5em;
|
|
171
|
+
border-left: 4px solid #e5e7eb;
|
|
172
|
+
background: #f9fafb;
|
|
173
|
+
font-style: italic;
|
|
174
|
+
}
|
|
175
|
+
.widget-html__content pre,
|
|
176
|
+
.widget-html__content code {
|
|
177
|
+
font-family: 'Monaco', 'Consolas', monospace;
|
|
178
|
+
font-size: 0.9em;
|
|
179
|
+
}
|
|
180
|
+
.widget-html__content pre {
|
|
181
|
+
background: #1f2937;
|
|
182
|
+
color: #f9fafb;
|
|
183
|
+
padding: 1em;
|
|
184
|
+
border-radius: 8px;
|
|
185
|
+
overflow-x: auto;
|
|
186
|
+
}
|
|
187
|
+
.widget-html__content code {
|
|
188
|
+
background: #f3f4f6;
|
|
189
|
+
padding: 0.2em 0.4em;
|
|
190
|
+
border-radius: 4px;
|
|
191
|
+
}
|
|
192
|
+
.widget-html__content pre code {
|
|
193
|
+
background: none;
|
|
194
|
+
padding: 0;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/* Mobile */
|
|
198
|
+
@media (max-width: 768px) {
|
|
199
|
+
.widget-html {
|
|
200
|
+
padding: 32px 0;
|
|
201
|
+
}
|
|
202
|
+
.widget-html__inner {
|
|
203
|
+
padding: 0 16px;
|
|
204
|
+
}
|
|
205
|
+
.widget-html .widget-title {
|
|
206
|
+
font-size: 1.3rem;
|
|
207
|
+
}
|
|
208
|
+
.widget-html__content {
|
|
209
|
+
font-size: 15px;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
</style>
|
|
213
|
+
</section>
|
|
214
|
+
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
{% liquid
|
|
2
|
+
assign widget_settings = widget.settings
|
|
3
|
+
assign widget_content = widget.content
|
|
4
|
+
assign widget_data = widget.data
|
|
5
|
+
|
|
6
|
+
comment
|
|
7
|
+
Dynamic Widget: News items come from widget_data.products (enriched by WidgetService)
|
|
8
|
+
Settings come from widget_settings
|
|
9
|
+
endcomment
|
|
10
|
+
assign news_items = widget_data.products | default: widget_data.items | default: widget_data.newsItems
|
|
11
|
+
assign heading = widget_settings.title | default: widget.Title | default: widget_content.ProductName
|
|
12
|
+
|
|
13
|
+
assign show_container = widget_content.ShowContainer | default: widget_settings.showContainer | default: 'Default'
|
|
14
|
+
assign show_widget_title_raw = widget_content.ShowWidgetTitle | default: widget_settings.showWidgetTitle | default: 'Default'
|
|
15
|
+
if show_widget_title_raw == null or show_widget_title_raw == blank or show_widget_title_raw == 'null'
|
|
16
|
+
assign show_widget_title = true
|
|
17
|
+
elsif show_widget_title_raw == 'Yes' or show_widget_title_raw == 'Default'
|
|
18
|
+
assign show_widget_title = true
|
|
19
|
+
else
|
|
20
|
+
assign show_widget_title = false
|
|
21
|
+
endif
|
|
22
|
+
|
|
23
|
+
assign widget_title_alignment_raw = widget_content.WidgetTitleAlignment | default: widget_settings.widgetTitleAlignment | default: 'Default'
|
|
24
|
+
assign alignment = 'center'
|
|
25
|
+
if widget_title_alignment_raw == 'Left' or widget_title_alignment_raw == 'left'
|
|
26
|
+
assign alignment = 'left'
|
|
27
|
+
elsif widget_title_alignment_raw == 'Right' or widget_title_alignment_raw == 'right'
|
|
28
|
+
assign alignment = 'right'
|
|
29
|
+
elsif widget_title_alignment_raw == 'Center' or widget_title_alignment_raw == 'Center' or widget_title_alignment_raw == 'Default' or widget_title_alignment_raw == 'default'
|
|
30
|
+
assign alignment = 'center'
|
|
31
|
+
endif
|
|
32
|
+
|
|
33
|
+
assign background_color = widget_content.BackgroundColor | default: widget_settings.backgroundColor
|
|
34
|
+
assign text_color = widget_content.TextColor | default: widget_settings.textColor
|
|
35
|
+
assign show_grid_view = widget_content.ShowGridView | default: widget_settings.showGridView | default: true
|
|
36
|
+
|
|
37
|
+
comment
|
|
38
|
+
Container logic based on section and ShowContainer:
|
|
39
|
+
- section == "hero" + ShowContainer == "No" or ("Default"/null in hero) → no container
|
|
40
|
+
- section != "hero" + ShowContainer == ("Default"/null) or ShowContainer == "Yes" → with container
|
|
41
|
+
- ShowContainer == "No" → no container
|
|
42
|
+
- ShowContainer == "Yes" → with container
|
|
43
|
+
endcomment
|
|
44
|
+
assign widget_section = widget.section | default: 'content'
|
|
45
|
+
assign use_container = true
|
|
46
|
+
|
|
47
|
+
if show_container == 'No'
|
|
48
|
+
assign use_container = false
|
|
49
|
+
elsif show_container == 'Yes'
|
|
50
|
+
assign use_container = true
|
|
51
|
+
else
|
|
52
|
+
if widget_section == 'hero'
|
|
53
|
+
if show_container == 'Default' or show_container == null or show_container == 'null' or show_container == blank
|
|
54
|
+
assign use_container = false
|
|
55
|
+
else
|
|
56
|
+
assign use_container = true
|
|
57
|
+
endif
|
|
58
|
+
else
|
|
59
|
+
assign use_container = true
|
|
60
|
+
endif
|
|
61
|
+
endif
|
|
62
|
+
%}
|
|
63
|
+
|
|
64
|
+
{% if news_items and news_items.size > 0 %}
|
|
65
|
+
{% if use_container %}
|
|
66
|
+
<section class="widget widget-news" data-widget-id="{{ widget.id }}"{% if background_color and background_color != 'null' and background_color != blank %} style="background-color: {{ background_color }}; color: {{ text_color }};"{% endif %}>
|
|
67
|
+
<div class="container">
|
|
68
|
+
{% if show_widget_title and heading and heading != blank %}
|
|
69
|
+
<h2 class="widget-news__title" style="text-align: {{ alignment }}; color: {{ text_color }}; padding-top: 2%;">{{ heading }}</h2>
|
|
70
|
+
{% endif %}
|
|
71
|
+
|
|
72
|
+
<div class="row product-list widget-news__list">
|
|
73
|
+
{% for item in news_items %}
|
|
74
|
+
{% if show_grid_view %}
|
|
75
|
+
<div class="col-6 col-md-3 p-b-35 p-l-5 p-r-5">
|
|
76
|
+
{% render 'snippets/news-thumbnail', news_item: item %}
|
|
77
|
+
</div>
|
|
78
|
+
{% else %}
|
|
79
|
+
<div class="col-md-3 p-b-35 p-l-5 p-r-5">
|
|
80
|
+
{% render 'snippets/news-thumbnail', news_item: item %}
|
|
81
|
+
</div>
|
|
82
|
+
{% endif %}
|
|
83
|
+
{% endfor %}
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
</section>
|
|
87
|
+
{% else %}
|
|
88
|
+
<div class="widget widget-news" data-widget-id="{{ widget.id }}"{% if background_color and background_color != 'null' and background_color != blank %} style="background-color: {{ background_color }}; color: {{ text_color }};"{% endif %}>
|
|
89
|
+
{% if show_widget_title and heading and heading != blank %}
|
|
90
|
+
<h2 class="widget-news__title" style="text-align: {{ alignment }}; color: {{ text_color }}; padding-top: 2%;">{{ heading }}</h2>
|
|
91
|
+
{% endif %}
|
|
92
|
+
|
|
93
|
+
<div class="row product-list widget-news__list">
|
|
94
|
+
{% for item in news_items %}
|
|
95
|
+
{% if show_grid_view %}
|
|
96
|
+
<div class="col-6 col-md-3 p-b-35 p-l-5 p-r-5">
|
|
97
|
+
{% render 'snippets/news-thumbnail', news_item: item %}
|
|
98
|
+
</div>
|
|
99
|
+
{% else %}
|
|
100
|
+
<div class="col-md-3 p-b-35 p-l-5 p-r-5">
|
|
101
|
+
{% render 'snippets/news-thumbnail', news_item: item %}
|
|
102
|
+
</div>
|
|
103
|
+
{% endif %}
|
|
104
|
+
{% endfor %}
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
{% endif %}
|
|
108
|
+
{% else %}
|
|
109
|
+
<section class="widget widget-news widget-news--empty" data-widget-id="{{ widget.id }}">
|
|
110
|
+
<div class="widget-empty">
|
|
111
|
+
<p>No news items available.</p>
|
|
112
|
+
</div>
|
|
113
|
+
</section>
|
|
114
|
+
{% endif %}
|
|
115
|
+
|
|
116
|
+
<style>
|
|
117
|
+
.widget-news {
|
|
118
|
+
padding: 40px 0;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.widget-news__title {
|
|
122
|
+
font-size: 1.4rem;
|
|
123
|
+
font-weight: 500;
|
|
124
|
+
line-height: 1.3;
|
|
125
|
+
margin: 0 0 32px 0;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.widget-news__list {
|
|
129
|
+
display: flex;
|
|
130
|
+
flex-wrap: wrap;
|
|
131
|
+
margin: 0 -5px;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.widget-news .row {
|
|
135
|
+
display: flex;
|
|
136
|
+
flex-wrap: wrap;
|
|
137
|
+
margin: 0 -5px;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.widget-news .col-6 {
|
|
141
|
+
flex: 0 0 50%;
|
|
142
|
+
max-width: 50%;
|
|
143
|
+
padding: 0 5px;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.widget-news .col-md-3 {
|
|
147
|
+
flex: 0 0 100%;
|
|
148
|
+
max-width: 100%;
|
|
149
|
+
padding: 0 5px;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@media (min-width: 768px) {
|
|
153
|
+
.widget-news .col-md-3 {
|
|
154
|
+
flex: 0 0 25%;
|
|
155
|
+
max-width: 25%;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.widget-news .p-b-35 {
|
|
160
|
+
padding-bottom: 35px;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.widget-news .p-l-5 {
|
|
164
|
+
padding-left: 5px;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.widget-news .p-r-5 {
|
|
168
|
+
padding-right: 5px;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.widget-news .container {
|
|
172
|
+
max-width: 1400px;
|
|
173
|
+
margin: 0 auto;
|
|
174
|
+
padding: 0 24px;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.widget-empty {
|
|
178
|
+
padding: 60px 24px;
|
|
179
|
+
text-align: center;
|
|
180
|
+
color: #6b7280;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.widget-empty p {
|
|
184
|
+
margin: 0;
|
|
185
|
+
font-size: 14px;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
@media (max-width: 768px) {
|
|
189
|
+
.widget-news {
|
|
190
|
+
padding: 32px 0;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.widget-news__title {
|
|
194
|
+
font-size: 1.3rem;
|
|
195
|
+
margin-bottom: 24px;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.widget-news .container {
|
|
199
|
+
padding: 0 16px;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@media (max-width: 480px) {
|
|
204
|
+
.widget-news {
|
|
205
|
+
padding: 24px 0;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.widget-news__title {
|
|
209
|
+
font-size: 1.2rem;
|
|
210
|
+
margin-bottom: 20px;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.widget-news .container {
|
|
214
|
+
padding: 0 12px;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
</style>
|