@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.
Files changed (116) hide show
  1. package/README.md +425 -0
  2. package/assets/Logo_o2vend.png +0 -0
  3. package/assets/favicon.png +0 -0
  4. package/assets/logo-white.png +0 -0
  5. package/bin/o2vend +42 -0
  6. package/config/widget-map.json +50 -0
  7. package/lib/commands/check.js +201 -0
  8. package/lib/commands/generate.js +33 -0
  9. package/lib/commands/init.js +214 -0
  10. package/lib/commands/optimize.js +216 -0
  11. package/lib/commands/package.js +208 -0
  12. package/lib/commands/serve.js +105 -0
  13. package/lib/commands/validate.js +191 -0
  14. package/lib/lib/api-client.js +357 -0
  15. package/lib/lib/dev-server.js +2618 -0
  16. package/lib/lib/file-watcher.js +80 -0
  17. package/lib/lib/hot-reload.js +106 -0
  18. package/lib/lib/liquid-engine.js +822 -0
  19. package/lib/lib/liquid-filters.js +671 -0
  20. package/lib/lib/mock-api-server.js +989 -0
  21. package/lib/lib/mock-data.js +1468 -0
  22. package/lib/lib/widget-service.js +321 -0
  23. package/package.json +70 -0
  24. package/test-theme/README.md +27 -0
  25. package/test-theme/assets/async-sections.js +446 -0
  26. package/test-theme/assets/cart-drawer.js +463 -0
  27. package/test-theme/assets/cart-manager.js +223 -0
  28. package/test-theme/assets/checkout-price-handler.js +368 -0
  29. package/test-theme/assets/components.css +4629 -0
  30. package/test-theme/assets/delivery-zone.css +299 -0
  31. package/test-theme/assets/delivery-zone.js +396 -0
  32. package/test-theme/assets/logo.png +0 -0
  33. package/test-theme/assets/sections.css +48 -0
  34. package/test-theme/assets/theme.css +3500 -0
  35. package/test-theme/assets/theme.js +3745 -0
  36. package/test-theme/config/settings_data.json +292 -0
  37. package/test-theme/config/settings_schema.json +1050 -0
  38. package/test-theme/layout/theme.liquid +195 -0
  39. package/test-theme/locales/en.default.json +260 -0
  40. package/test-theme/sections/content-fallback.liquid +53 -0
  41. package/test-theme/sections/content.liquid +57 -0
  42. package/test-theme/sections/footer-fallback.liquid +328 -0
  43. package/test-theme/sections/footer.liquid +278 -0
  44. package/test-theme/sections/header-fallback.liquid +1805 -0
  45. package/test-theme/sections/header.liquid +1145 -0
  46. package/test-theme/sections/hero-fallback.liquid +212 -0
  47. package/test-theme/sections/hero.liquid +136 -0
  48. package/test-theme/snippets/account-sidebar.liquid +200 -0
  49. package/test-theme/snippets/add-to-cart-modal.liquid +484 -0
  50. package/test-theme/snippets/breadcrumbs.liquid +134 -0
  51. package/test-theme/snippets/cart-drawer.liquid +467 -0
  52. package/test-theme/snippets/delivery-zone-city-selector.liquid +79 -0
  53. package/test-theme/snippets/delivery-zone-modal.liquid +337 -0
  54. package/test-theme/snippets/delivery-zone-search.liquid +78 -0
  55. package/test-theme/snippets/icon.liquid +105 -0
  56. package/test-theme/snippets/login-modal.liquid +346 -0
  57. package/test-theme/snippets/mega-menu.liquid +812 -0
  58. package/test-theme/snippets/news-thumbnail.liquid +187 -0
  59. package/test-theme/snippets/pagination.liquid +120 -0
  60. package/test-theme/snippets/price.liquid +92 -0
  61. package/test-theme/snippets/product-card-related.liquid +78 -0
  62. package/test-theme/snippets/product-card-simple.liquid +41 -0
  63. package/test-theme/snippets/product-card.liquid +697 -0
  64. package/test-theme/snippets/rating.liquid +85 -0
  65. package/test-theme/snippets/skeleton-collection-grid.liquid +114 -0
  66. package/test-theme/snippets/skeleton-product-card.liquid +124 -0
  67. package/test-theme/snippets/skeleton-product-grid.liquid +34 -0
  68. package/test-theme/snippets/social-sharing.liquid +185 -0
  69. package/test-theme/templates/account/dashboard.liquid +401 -0
  70. package/test-theme/templates/account/loyalty-redemption.liquid +405 -0
  71. package/test-theme/templates/account/loyalty.liquid +588 -0
  72. package/test-theme/templates/account/order-detail.liquid +230 -0
  73. package/test-theme/templates/account/orders.liquid +349 -0
  74. package/test-theme/templates/account/profile.liquid +758 -0
  75. package/test-theme/templates/account/register.liquid +232 -0
  76. package/test-theme/templates/account/return-orders.liquid +348 -0
  77. package/test-theme/templates/account/store-credit.liquid +464 -0
  78. package/test-theme/templates/account/subscriptions.liquid +601 -0
  79. package/test-theme/templates/account/wishlist.liquid +419 -0
  80. package/test-theme/templates/address-book.liquid +1092 -0
  81. package/test-theme/templates/categories.liquid +452 -0
  82. package/test-theme/templates/checkout.liquid +4511 -0
  83. package/test-theme/templates/error.liquid +384 -0
  84. package/test-theme/templates/index.liquid +11 -0
  85. package/test-theme/templates/login.liquid +185 -0
  86. package/test-theme/templates/order-confirmation.liquid +720 -0
  87. package/test-theme/templates/page.liquid +297 -0
  88. package/test-theme/templates/product-detail.liquid +4363 -0
  89. package/test-theme/templates/products.liquid +518 -0
  90. package/test-theme/templates/search.liquid +922 -0
  91. package/test-theme/theme.json.example +19 -0
  92. package/test-theme/widgets/brand-carousel.liquid +676 -0
  93. package/test-theme/widgets/brand.liquid +245 -0
  94. package/test-theme/widgets/carousel.liquid +843 -0
  95. package/test-theme/widgets/category-list-carousel.liquid +656 -0
  96. package/test-theme/widgets/category-list.liquid +340 -0
  97. package/test-theme/widgets/category.liquid +475 -0
  98. package/test-theme/widgets/discount-time.liquid +176 -0
  99. package/test-theme/widgets/footer-menu.liquid +695 -0
  100. package/test-theme/widgets/footer.liquid +179 -0
  101. package/test-theme/widgets/gallery.liquid +271 -0
  102. package/test-theme/widgets/header-menu.liquid +932 -0
  103. package/test-theme/widgets/header.liquid +159 -0
  104. package/test-theme/widgets/html.liquid +214 -0
  105. package/test-theme/widgets/news.liquid +217 -0
  106. package/test-theme/widgets/product-canvas.liquid +235 -0
  107. package/test-theme/widgets/product-carousel.liquid +502 -0
  108. package/test-theme/widgets/product.liquid +45 -0
  109. package/test-theme/widgets/recently-viewed.liquid +26 -0
  110. package/test-theme/widgets/shared/product-grid.liquid +339 -0
  111. package/test-theme/widgets/simple-product.liquid +42 -0
  112. package/test-theme/widgets/single-product.liquid +610 -0
  113. package/test-theme/widgets/spacebar-carousel.liquid +663 -0
  114. package/test-theme/widgets/spacebar.liquid +279 -0
  115. package/test-theme/widgets/splash.liquid +378 -0
  116. package/test-theme/widgets/testimonial-carousel.liquid +709 -0
@@ -0,0 +1,346 @@
1
+ {% comment %}
2
+ Global Login Modal
3
+ Supports three methods: email/password, email OTP, mobile OTP
4
+ Opened via JS (no route change)
5
+ {% endcomment %}
6
+
7
+ <div id="login-modal" class="login-modal" aria-hidden="true" role="dialog" aria-modal="true">
8
+ <div class="login-modal__overlay" data-login-overlay></div>
9
+ <div class="login-modal__panel" role="document">
10
+ <header class="login-modal__header">
11
+ <div>
12
+ <h2 class="login-modal__title">Sign in</h2>
13
+ <p class="login-modal__subtitle">Choose how you’d like to continue</p>
14
+ </div>
15
+ <button class="login-modal__close" type="button" aria-label="Close" data-login-close>
16
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
17
+ <line x1="18" y1="6" x2="6" y2="18"></line>
18
+ <line x1="6" y1="6" x2="18" y2="18"></line>
19
+ </svg>
20
+ </button>
21
+ </header>
22
+
23
+ <div class="login-modal__body">
24
+ <!-- Method selection -->
25
+ <div class="login-modal__methods" data-login-view="methods">
26
+ <button type="button" class="login-modal__method-card" data-login-method="email-otp">
27
+ <div class="login-modal__method-title">Email OTP</div>
28
+ <div class="login-modal__method-desc">Receive a one-time code to your email.</div>
29
+ </button>
30
+
31
+ <button type="button" class="login-modal__method-card" data-login-method="phone-otp">
32
+ <div class="login-modal__method-title">Mobile OTP</div>
33
+ <div class="login-modal__method-desc">Receive a one-time code via SMS.</div>
34
+ </button>
35
+ </div>
36
+
37
+ <!-- Email OTP flow (hidden until method is chosen) -->
38
+ <div class="login-modal__flow" data-login-view="email-otp" hidden>
39
+ <form class="login-modal__form" data-login-step="email-input" novalidate>
40
+ <div class="form-group">
41
+ <label for="login-email-otp" class="form-label">Email</label>
42
+ <input id="login-email-otp" name="email" type="email" class="form-input" required autocomplete="email">
43
+ </div>
44
+ <div class="login-modal__error" data-login-error="email-otp-input"></div>
45
+ <button type="submit" class="btn btn-primary btn-block" data-login-send-email-otp>
46
+ Send OTP
47
+ </button>
48
+ </form>
49
+
50
+ <form class="login-modal__form" data-login-step="email-verify" novalidate style="display:none;">
51
+ <p class="login-modal__info">
52
+ Enter the code we sent to <span data-login-email-display></span>
53
+ </p>
54
+ <div class="form-group">
55
+ <label for="login-email-otp-code" class="form-label">OTP code</label>
56
+ <input id="login-email-otp-code" name="otp" type="text" class="form-input" required maxlength="6" inputmode="numeric">
57
+ </div>
58
+ <div class="login-modal__resend">
59
+ <button type="button" class="btn btn-ghost btn-sm" data-login-resend-email-otp>
60
+ Resend code
61
+ </button>
62
+ <span class="login-modal__resend-timer" data-login-resend-email-timer></span>
63
+ </div>
64
+ <div class="login-modal__error" data-login-error="email-otp-verify"></div>
65
+ <button type="submit" class="btn btn-primary btn-block" data-login-verify-email-otp>
66
+ Verify &amp; continue
67
+ </button>
68
+ </form>
69
+ </div>
70
+
71
+ <!-- Phone OTP flow (hidden until method is chosen) -->
72
+ <div class="login-modal__flow" data-login-view="phone-otp" hidden>
73
+ <form class="login-modal__form" data-login-step="phone-input" novalidate>
74
+ <div class="form-group">
75
+ <label for="login-phone-otp" class="form-label">Mobile number</label>
76
+ <input id="login-phone-otp" name="phone" type="tel" class="form-input login-phone-input" required inputmode="tel">
77
+ </div>
78
+ <div class="login-modal__error" data-login-error="phone-otp-input"></div>
79
+ <button type="submit" class="btn btn-primary btn-block" data-login-send-phone-otp>
80
+ Send OTP
81
+ </button>
82
+ </form>
83
+
84
+ <form class="login-modal__form" data-login-step="phone-verify" novalidate style="display:none;">
85
+ <p class="login-modal__info">
86
+ Enter the code we sent to <span data-login-phone-display></span>
87
+ </p>
88
+ <div class="form-group">
89
+ <label for="login-phone-otp-code" class="form-label">OTP code</label>
90
+ <input id="login-phone-otp-code" name="otp" type="text" class="form-input" required maxlength="6" inputmode="numeric">
91
+ </div>
92
+ <div class="login-modal__resend">
93
+ <button type="button" class="btn btn-ghost btn-sm" data-login-resend-phone-otp>
94
+ Resend code
95
+ </button>
96
+ <span class="login-modal__resend-timer" data-login-resend-phone-timer></span>
97
+ </div>
98
+ <div class="login-modal__error" data-login-error="phone-otp-verify"></div>
99
+ <button type="submit" class="btn btn-primary btn-block" data-login-verify-phone-otp>
100
+ Verify &amp; continue
101
+ </button>
102
+ </form>
103
+ </div>
104
+
105
+ <!-- Success state -->
106
+ <div class="login-modal__success" data-login-view="success" hidden>
107
+ <div class="login-modal__success-icon">
108
+ <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
109
+ <path d="M9 12l2 2 4-4"></path>
110
+ <circle cx="12" cy="12" r="9"></circle>
111
+ </svg>
112
+ </div>
113
+ <h3 class="login-modal__success-title">You’re signed in</h3>
114
+ <p class="login-modal__success-text">
115
+ You can now continue shopping with your account benefits.
116
+ </p>
117
+ <button type="button" class="btn btn-primary btn-block" data-login-close>
118
+ Continue
119
+ </button>
120
+ </div>
121
+ </div>
122
+ </div>
123
+ </div>
124
+
125
+ <style>
126
+ .login-modal {
127
+ position: fixed;
128
+ inset: 0;
129
+ z-index: 10000;
130
+ display: none;
131
+ }
132
+ .login-modal--active {
133
+ display: flex;
134
+ align-items: center;
135
+ justify-content: center;
136
+ }
137
+ .login-modal__overlay {
138
+ position: absolute;
139
+ inset: 0;
140
+ background: rgba(0, 0, 0, 0.45);
141
+ backdrop-filter: blur(4px);
142
+ }
143
+ .login-modal__panel {
144
+ position: relative;
145
+ background: #fff;
146
+ border-radius: 16px;
147
+ box-shadow: 0 24px 80px rgba(0, 0, 0, 0.25);
148
+ width: 100%;
149
+ max-width: 480px;
150
+ max-height: 90vh;
151
+ display: flex;
152
+ flex-direction: column;
153
+ overflow: hidden;
154
+ }
155
+ .login-modal__header {
156
+ display: flex;
157
+ align-items: center;
158
+ justify-content: space-between;
159
+ padding: 20px 24px;
160
+ border-bottom: 1px solid #e5e7eb;
161
+ }
162
+ .login-modal__title {
163
+ margin: 0;
164
+ font-size: 20px;
165
+ font-weight: 600;
166
+ color: #111827;
167
+ }
168
+ .login-modal__subtitle {
169
+ margin: 4px 0 0;
170
+ font-size: 14px;
171
+ color: #6b7280;
172
+ }
173
+ .login-modal__close {
174
+ border: none;
175
+ background: none;
176
+ padding: 4px;
177
+ border-radius: 999px;
178
+ cursor: pointer;
179
+ color: #6b7280;
180
+ }
181
+ .login-modal__close:hover {
182
+ background: #f3f4f6;
183
+ color: #111827;
184
+ }
185
+ .login-modal__body {
186
+ padding: 20px 24px 24px;
187
+ overflow-y: auto;
188
+ }
189
+ .login-modal__steps {
190
+ display: flex;
191
+ gap: 12px;
192
+ font-size: 12px;
193
+ text-transform: uppercase;
194
+ letter-spacing: 0.08em;
195
+ margin-bottom: 16px;
196
+ }
197
+ .login-modal__step {
198
+ padding-bottom: 4px;
199
+ border-bottom: 2px solid transparent;
200
+ color: #9ca3af;
201
+ }
202
+ .login-modal__step--active {
203
+ border-color: #111827;
204
+ color: #111827;
205
+ }
206
+ .login-modal__methods {
207
+ display: grid;
208
+ grid-template-columns: 1fr;
209
+ gap: 12px;
210
+ }
211
+ .login-modal__method-card {
212
+ width: 100%;
213
+ text-align: left;
214
+ border-radius: 12px;
215
+ border: 1px solid #e5e7eb;
216
+ padding: 12px 14px;
217
+ background: #f9fafb;
218
+ cursor: pointer;
219
+ transition: all 0.15s ease;
220
+ }
221
+ .login-modal__method-card:hover {
222
+ border-color: #111827;
223
+ background: #f3f4f6;
224
+ }
225
+ .login-modal__method-title {
226
+ font-size: 14px;
227
+ font-weight: 600;
228
+ color: #111827;
229
+ }
230
+ .login-modal__method-desc {
231
+ font-size: 12px;
232
+ color: #6b7280;
233
+ margin-top: 2px;
234
+ }
235
+ .login-modal__form {
236
+ display: flex;
237
+ flex-direction: column;
238
+ gap: 14px;
239
+ margin-top: 4px;
240
+ }
241
+ .login-modal__flow {
242
+ margin-top: 8px;
243
+ }
244
+ .login-modal__info {
245
+ font-size: 13px;
246
+ color: #4b5563;
247
+ margin: 0 0 8px;
248
+ }
249
+ .login-modal__resend {
250
+ display: flex;
251
+ align-items: center;
252
+ justify-content: space-between;
253
+ gap: 8px;
254
+ font-size: 12px;
255
+ }
256
+ .login-modal__resend-timer {
257
+ color: #6b7280;
258
+ }
259
+ .login-modal__error {
260
+ display: none;
261
+ font-size: 13px;
262
+ color: #b91c1c;
263
+ background: #fee2e2;
264
+ border-radius: 8px;
265
+ padding: 8px 10px;
266
+ }
267
+ .login-modal__error--visible {
268
+ display: block;
269
+ }
270
+ .login-modal__success {
271
+ text-align: center;
272
+ padding-top: 8px;
273
+ }
274
+ .login-modal__success-icon {
275
+ width: 44px;
276
+ height: 44px;
277
+ border-radius: 999px;
278
+ background: #ecfdf3;
279
+ display: inline-flex;
280
+ align-items: center;
281
+ justify-content: center;
282
+ color: #16a34a;
283
+ margin-bottom: 12px;
284
+ }
285
+ .login-modal__success-title {
286
+ margin: 0 0 4px;
287
+ font-size: 18px;
288
+ font-weight: 600;
289
+ }
290
+ .login-modal__success-text {
291
+ margin: 0 0 16px;
292
+ font-size: 14px;
293
+ color: #6b7280;
294
+ }
295
+
296
+ @media (max-width: 640px) {
297
+ .login-modal__panel {
298
+ max-width: 100%;
299
+ height: 100%;
300
+ max-height: 100%;
301
+ border-radius: 0;
302
+ }
303
+ }
304
+
305
+ /* intl-tel-input styling for login modal */
306
+ .login-phone-input {
307
+ padding-left: 3.5rem;
308
+ }
309
+
310
+ .iti {
311
+ width: 100%;
312
+ }
313
+
314
+ .iti__flag-container {
315
+ z-index: 1;
316
+ }
317
+
318
+ .iti__selected-flag {
319
+ padding: 0 0.75rem 0 0.5rem;
320
+ border-right: 1px solid #e5e7eb;
321
+ }
322
+
323
+ .iti__selected-flag:hover {
324
+ background-color: #f3f4f6;
325
+ }
326
+
327
+ .iti__country-list {
328
+ z-index: 10001;
329
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
330
+ border: 1px solid #e5e7eb;
331
+ border-radius: 8px;
332
+ max-height: 200px;
333
+ overflow-y: auto;
334
+ }
335
+
336
+ .iti__country {
337
+ padding: 0.5rem 0.75rem;
338
+ }
339
+
340
+ .iti__country:hover,
341
+ .iti__country.iti__highlight {
342
+ background-color: #dbeafe;
343
+ }
344
+ </style>
345
+
346
+