@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,467 @@
1
+ <div class="cart-drawer" id="cart-drawer" aria-hidden="true">
2
+ <div class="cart-drawer-overlay" data-cart-overlay></div>
3
+ <aside class="cart-drawer-panel" role="dialog" aria-label="Shopping cart">
4
+ <header class="cart-drawer-header">
5
+ <h3 class="cart-drawer-title" data-cart-title>
6
+ <span class="cart-drawer-title-text">Cart</span>
7
+ <span class="cart-drawer-title-badge" data-cart-count>0</span>
8
+ </h3>
9
+ <button class="cart-drawer-close" aria-label="Close cart" data-cart-close>
10
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
11
+ <line x1="18" y1="6" x2="6" y2="18"></line>
12
+ <line x1="6" y1="6" x2="18" y2="18"></line>
13
+ </svg>
14
+ </button>
15
+ </header>
16
+
17
+ <div class="cart-drawer-content" data-cart-items>
18
+ <div class="cart-drawer-loading" data-cart-loading>
19
+ <p>Loading cart...</p>
20
+ </div>
21
+ <div class="cart-drawer-empty" data-cart-empty style="display: none;">
22
+ <svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1">
23
+ <circle cx="9" cy="21" r="1"></circle>
24
+ <circle cx="20" cy="21" r="1"></circle>
25
+ <path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
26
+ </svg>
27
+ <p>Your cart is empty</p>
28
+ {% comment %}Continue shopping - Check settings with proper boolean handling{% endcomment %}
29
+ {% liquid
30
+ assign continue_val = settings.show_continue_shopping
31
+ if continue_val == blank or continue_val == null
32
+ assign continue_val = true
33
+ endif
34
+ %}
35
+ {% if continue_val or continue_val == true or continue_val == 'true' or continue_val == 1 %}
36
+ <a href="/products" class="btn btn-outline">Continue shopping</a>
37
+ {% endif %}
38
+ </div>
39
+ <div class="cart-drawer-items" data-cart-items-list style="display: none;"></div>
40
+ </div>
41
+
42
+ <footer class="cart-drawer-footer" data-cart-footer style="display: none;">
43
+ <div class="cart-drawer-discount" data-cart-discount style="display: none;">
44
+ <button class="cart-drawer-discount-toggle" data-discount-toggle>
45
+ <span>Discount</span>
46
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
47
+ <polyline points="6 9 12 15 18 9"></polyline>
48
+ </svg>
49
+ </button>
50
+ <div class="cart-drawer-discount-content" data-discount-content style="display: none;">
51
+ <!-- Discount content will be added here -->
52
+ </div>
53
+ </div>
54
+ <div class="cart-drawer-total">
55
+ <span class="cart-drawer-total-label">Estimated total</span>
56
+ <span class="cart-drawer-total-amount" data-cart-total>$0.00</span>
57
+ </div>
58
+ <p class="cart-drawer-note">Taxes and shipping calculated at checkout.</p>
59
+ <button class="btn btn-primary btn-lg cart-drawer-checkout" id="cart-drawer-checkout-btn">Check out</button>
60
+ </footer>
61
+ </aside>
62
+ </div>
63
+
64
+ <style>
65
+ .cart-drawer {
66
+ position: fixed;
67
+ inset: 0;
68
+ z-index: var(--z-modal, 1050);
69
+ display: none;
70
+ pointer-events: none;
71
+ }
72
+
73
+ .cart-drawer.active {
74
+ display: block;
75
+ pointer-events: auto;
76
+ }
77
+
78
+ .cart-drawer-overlay {
79
+ position: absolute;
80
+ inset: 0;
81
+ background: rgba(0, 0, 0, calc(var(--shadow-opacity, 0.1) * 5));
82
+ opacity: 0;
83
+ transition: opacity var(--transition, 0.3s) var(--ease-out, ease);
84
+ }
85
+
86
+ .cart-drawer.active .cart-drawer-overlay {
87
+ opacity: 1;
88
+ }
89
+
90
+ .cart-drawer-panel {
91
+ position: absolute;
92
+ top: 0;
93
+ right: 0;
94
+ width: min(420px, 100%);
95
+ height: 100%;
96
+ background: var(--color-background, #fff);
97
+ border-left: 1px solid var(--color-border, #e5e7eb);
98
+ display: flex;
99
+ flex-direction: column;
100
+ transform: translateX(100%);
101
+ transition: transform var(--transition, 0.3s) var(--ease-out, ease);
102
+ box-shadow: -2px 0 var(--shadow-blur, 8px) rgba(0, 0, 0, var(--shadow-opacity, 0.1));
103
+ }
104
+
105
+ .cart-drawer.active .cart-drawer-panel {
106
+ transform: translateX(0);
107
+ }
108
+
109
+ .cart-drawer-header {
110
+ display: flex;
111
+ align-items: center;
112
+ justify-content: space-between;
113
+ padding: var(--spacing-component, 1.25rem) var(--spacing-component, 1.5rem);
114
+ border-bottom: 1px solid var(--color-border, #e5e7eb);
115
+ }
116
+
117
+ .cart-drawer-title {
118
+ margin: 0;
119
+ font-size: var(--text-2xl, 2.1rem);
120
+ font-weight: var(--font-weight-bold, 600);
121
+ color: var(--color-text, #333333);
122
+ font-family: var(--font-primary, var(--font-body));
123
+ display: inline-flex;
124
+ align-items: center;
125
+ gap: var(--spacing-element, 0.5rem);
126
+ line-height: var(--line-height-heading, 1.2);
127
+ }
128
+
129
+ .cart-drawer-title-text {
130
+ display: inline-block;
131
+ line-height: inherit;
132
+ }
133
+
134
+ .cart-drawer-title-badge,
135
+ .cart-drawer-title [data-cart-count] {
136
+ display: inline-flex;
137
+ align-items: center;
138
+ justify-content: center;
139
+ min-width: 24px;
140
+ height: 24px;
141
+ padding: 0 var(--spacing-element, 6px);
142
+ background: var(--color-surface, #E0E0E0);
143
+ color: var(--color-text, #333333);
144
+ border-radius: var(--radius-full, 50%);
145
+ font-size: var(--text-xs, 1.2rem);
146
+ font-weight: var(--font-weight-normal, 500);
147
+ line-height: 1;
148
+ margin-left: var(--spacing-element, 0.25rem);
149
+ margin-top: 0.1em;
150
+ flex-shrink: 0;
151
+ align-self: center;
152
+ }
153
+
154
+ .cart-drawer-close {
155
+ display: inline-flex;
156
+ align-items: center;
157
+ justify-content: center;
158
+ width: 32px;
159
+ height: 32px;
160
+ background: none;
161
+ border: none;
162
+ cursor: pointer;
163
+ color: var(--color-text-light, #6b7280);
164
+ padding: 0;
165
+ border-radius: var(--border-radius-small, 4px);
166
+ transition: background-color var(--transition-fast, 0.2s) var(--ease-out, ease);
167
+ }
168
+
169
+ .cart-drawer-close:hover {
170
+ background-color: var(--color-surface, #f3f4f6);
171
+ }
172
+
173
+ .cart-drawer-content {
174
+ flex: 1;
175
+ overflow-y: auto;
176
+ padding: 0;
177
+ }
178
+
179
+ .cart-drawer-loading,
180
+ .cart-drawer-empty {
181
+ display: flex;
182
+ flex-direction: column;
183
+ align-items: center;
184
+ justify-content: center;
185
+ padding: var(--spacing-section, 3rem) var(--spacing-component, 1.5rem);
186
+ text-align: center;
187
+ min-height: 300px;
188
+ }
189
+
190
+ .cart-drawer-empty svg {
191
+ color: var(--color-text-light, #9ca3af);
192
+ margin-bottom: var(--spacing-element, 1rem);
193
+ }
194
+
195
+ .cart-drawer-empty p {
196
+ margin: 0 0 var(--spacing-component, 1.5rem);
197
+ color: var(--color-text-light, #6b7280);
198
+ font-size: var(--font-size-base, 1.4rem);
199
+ font-family: var(--font-primary, var(--font-body));
200
+ }
201
+
202
+ .cart-drawer-items {
203
+ padding: var(--spacing-element, 1rem) 0;
204
+ }
205
+
206
+ .cart-drawer-item {
207
+ display: flex;
208
+ gap: var(--spacing-element, 1rem);
209
+ padding: var(--spacing-element, 1rem) var(--spacing-component, 1.5rem);
210
+ border-bottom: 1px solid var(--color-surface, #f3f4f6);
211
+ }
212
+
213
+ .cart-drawer-item:last-child {
214
+ border-bottom: none;
215
+ }
216
+
217
+ .cart-drawer-image {
218
+ flex-shrink: 0;
219
+ width: 80px;
220
+ height: 80px;
221
+ border: 1px solid var(--color-border, #e5e7eb);
222
+ border-radius: var(--border-radius-medium, 8px);
223
+ overflow: hidden;
224
+ display: block;
225
+ background: var(--color-surface, #f9fafb);
226
+ }
227
+
228
+ .cart-drawer-image img {
229
+ width: 100%;
230
+ height: 100%;
231
+ object-fit: cover;
232
+ display: block;
233
+ }
234
+
235
+ .cart-drawer-item-content {
236
+ flex: 1;
237
+ display: flex;
238
+ flex-direction: column;
239
+ gap: var(--spacing-element, 0.5rem);
240
+ min-width: 0;
241
+ }
242
+
243
+ .cart-drawer-item-title {
244
+ color: var(--color-text, #000000);
245
+ text-decoration: none;
246
+ font-weight: var(--font-weight-normal, 500);
247
+ font-size: var(--font-size-base, 1.4rem);
248
+ line-height: var(--line-height-base, 1.5);
249
+ display: block;
250
+ font-family: var(--font-primary, var(--font-body));
251
+ }
252
+
253
+ .cart-drawer-item-title:hover {
254
+ text-decoration: underline;
255
+ }
256
+
257
+ .cart-drawer-item-variant {
258
+ color: var(--color-text-light, #6b7280);
259
+ font-size: var(--font-size-base, 1.4rem);
260
+ font-family: var(--font-primary, var(--font-body));
261
+ }
262
+
263
+ .cart-drawer-item-row {
264
+ display: flex;
265
+ align-items: center;
266
+ justify-content: space-between;
267
+ gap: var(--spacing-element, 1rem);
268
+ margin-top: var(--spacing-element, 0.5rem);
269
+ }
270
+
271
+ .cart-drawer-qty {
272
+ display: inline-flex;
273
+ align-items: center;
274
+ border: 1px solid var(--color-border, #d1d5db);
275
+ border-radius: var(--border-radius-small, 6px);
276
+ overflow: hidden;
277
+ background: var(--color-background, #fff);
278
+ }
279
+
280
+ .qty-btn {
281
+ width: 32px;
282
+ height: 32px;
283
+ background: none;
284
+ border: none;
285
+ cursor: pointer;
286
+ color: var(--color-text, #374151);
287
+ display: flex;
288
+ align-items: center;
289
+ justify-content: center;
290
+ font-size: var(--text-lg, 1.125rem);
291
+ line-height: 1;
292
+ transition: background-color var(--transition-fast, 0.2s) var(--ease-out, ease);
293
+ }
294
+
295
+ .qty-btn:hover {
296
+ background-color: var(--color-surface, #f3f4f6);
297
+ }
298
+
299
+ .qty-input {
300
+ width: 48px;
301
+ height: 32px;
302
+ border: none;
303
+ text-align: center;
304
+ font-size: var(--font-size-base, 1.4rem);
305
+ color: var(--color-text, #000000);
306
+ background: transparent;
307
+ font-family: var(--font-primary, var(--font-body));
308
+ -moz-appearance: textfield;
309
+ }
310
+
311
+ .qty-input::-webkit-outer-spin-button,
312
+ .qty-input::-webkit-inner-spin-button {
313
+ -webkit-appearance: none;
314
+ margin: 0;
315
+ }
316
+
317
+ .cart-drawer-item-price {
318
+ font-weight: var(--font-weight-bold, 600);
319
+ color: var(--color-text, #000000);
320
+ font-size: var(--font-size-base, 1.4rem);
321
+ font-family: var(--font-primary, var(--font-body));
322
+ }
323
+
324
+ .cart-drawer-remove {
325
+ flex-shrink: 0;
326
+ width: 20px;
327
+ height: 20px;
328
+ background: none;
329
+ border: none;
330
+ color: var(--color-text-light, #9ca3af);
331
+ cursor: pointer;
332
+ padding: 0;
333
+ display: flex;
334
+ align-items: center;
335
+ justify-content: center;
336
+ transition: color var(--transition-fast, 0.2s) var(--ease-out, ease);
337
+ }
338
+
339
+ .cart-drawer-remove:hover {
340
+ color: var(--color-error, #ef4444);
341
+ }
342
+
343
+ .cart-drawer-remove svg {
344
+ width: 16px;
345
+ height: 16px;
346
+ }
347
+
348
+ .cart-drawer-footer {
349
+ border-top: 1px solid var(--color-border, #e5e7eb);
350
+ padding: var(--spacing-component, 1.5rem);
351
+ display: flex;
352
+ flex-direction: column;
353
+ gap: var(--spacing-element, 1rem);
354
+ background: var(--color-background, #fff);
355
+ }
356
+
357
+ .cart-drawer-discount {
358
+ border-bottom: 1px solid var(--color-border, #e5e7eb);
359
+ padding-bottom: var(--spacing-element, 1rem);
360
+ }
361
+
362
+ .cart-drawer-discount-toggle {
363
+ width: 100%;
364
+ display: flex;
365
+ align-items: center;
366
+ justify-content: space-between;
367
+ background: none;
368
+ border: none;
369
+ padding: var(--spacing-element, 0.5rem) 0;
370
+ cursor: pointer;
371
+ color: var(--color-text, #000000);
372
+ font-size: var(--font-size-base, 1.4rem);
373
+ font-family: var(--font-primary, var(--font-body));
374
+ }
375
+
376
+ .cart-drawer-discount-toggle svg {
377
+ transition: transform var(--transition-fast, 0.2s) var(--ease-out, ease);
378
+ }
379
+
380
+ .cart-drawer-discount-toggle[aria-expanded="true"] svg {
381
+ transform: rotate(180deg);
382
+ }
383
+
384
+ .cart-drawer-discount-content {
385
+ padding-top: var(--spacing-element, 0.75rem);
386
+ }
387
+
388
+ .cart-drawer-total {
389
+ display: flex;
390
+ align-items: center;
391
+ justify-content: space-between;
392
+ font-size: var(--font-size-base, 1.4rem);
393
+ font-family: var(--font-primary, var(--font-body));
394
+ }
395
+
396
+ .cart-drawer-total-label {
397
+ color: var(--color-text-light, #6b7280);
398
+ font-weight: var(--font-weight-normal, 500);
399
+ font-size: var(--font-size-base, 1.4rem);
400
+ }
401
+
402
+ .cart-drawer-total-amount {
403
+ font-weight: var(--font-weight-bold, 600);
404
+ color: var(--color-text, #000000);
405
+ font-size: var(--font-size-base, 1.4rem);
406
+ }
407
+
408
+ .cart-drawer-note {
409
+ margin: 0;
410
+ color: var(--color-text-light, #6b7280);
411
+ font-size: var(--text-xs, 1.2rem);
412
+ text-align: center;
413
+ font-family: var(--font-primary, var(--font-body));
414
+ }
415
+
416
+ .cart-drawer-checkout {
417
+ width: 100%;
418
+ padding: var(--button-padding-vertical, 1.4rem) var(--button-padding-tal, 1.5rem);
419
+ background: var(--color-primary, #000);
420
+ color: var(--color-white, #fff);
421
+ border: none;
422
+ border-radius: var(--border-radius-medium, 8px);
423
+ font-size: var(--text-sm, 1.4rem);
424
+ font-weight: var(--font-weight-normal, 500);
425
+ cursor: pointer;
426
+ transition: opacity var(--button-transition-speed, 0.2s) var(--ease-out, ease), background-color var(--transition-fast, 0.2s) var(--ease-out, ease);
427
+ font-family: var(--font-primary, var(--font-body));
428
+ display: inline-flex;
429
+ align-items: center;
430
+ justify-content: center;
431
+ gap: var(--spacing-element, 0.5rem);
432
+ position: relative;
433
+ }
434
+
435
+ .cart-drawer-checkout:hover:not(.loading):not(:disabled) {
436
+ opacity: 0.9;
437
+ }
438
+
439
+ .cart-drawer-checkout.loading,
440
+ .cart-drawer-checkout:disabled {
441
+ opacity: 0.7;
442
+ cursor: not-allowed;
443
+ pointer-events: none;
444
+ }
445
+
446
+ .cart-drawer-checkout .loading-spinner {
447
+ width: 16px;
448
+ height: 16px;
449
+ border: 2px solid rgba(255, 255, 255, 0.3);
450
+ border-top: 2px solid var(--color-white, #fff);
451
+ border-radius: 50%;
452
+ animation: spin 1s linear infinite;
453
+ flex-shrink: 0;
454
+ display: inline-block;
455
+ }
456
+
457
+ @keyframes spin {
458
+ 0% { transform: rotate(0deg); }
459
+ 100% { transform: rotate(360deg); }
460
+ }
461
+
462
+ @media (max-width: 768px) {
463
+ .cart-drawer-panel {
464
+ width: 100%;
465
+ }
466
+ }
467
+ </style>
@@ -0,0 +1,79 @@
1
+ {% comment %}
2
+ Delivery Zone City Selector
3
+ {% endcomment %}
4
+
5
+ <div class="delivery-zone-city-container">
6
+ <select
7
+ id="delivery-zone-city"
8
+ name="cityId"
9
+ class="delivery-zone-city-select"
10
+ required>
11
+ <option value="">Select a city</option>
12
+ {% comment %} Cities will be populated via JavaScript {% endcomment %}
13
+ </select>
14
+
15
+ <div class="delivery-zone-loading-cities" id="delivery-zone-loading-cities">
16
+ <div class="spinner-small"></div>
17
+ <span>Loading cities...</span>
18
+ </div>
19
+ </div>
20
+
21
+ <style>
22
+ .delivery-zone-city-container {
23
+ position: relative;
24
+ width: 100%;
25
+ }
26
+
27
+ .delivery-zone-city-select {
28
+ width: 100%;
29
+ padding: 14px 16px;
30
+ border: 2px solid #a78bfa;
31
+ border-radius: 12px;
32
+ font-size: 16px;
33
+ background: white;
34
+ cursor: pointer;
35
+ transition: all 0.2s ease;
36
+ appearance: none;
37
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23666' d='M6 9L1 4h10z'/%3E%3C/svg%3E");
38
+ background-repeat: no-repeat;
39
+ background-position: right 16px center;
40
+ padding-right: 40px;
41
+ }
42
+
43
+ .delivery-zone-city-select:focus {
44
+ outline: none;
45
+ border-color: #7c3aed;
46
+ box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.1);
47
+ }
48
+
49
+ .delivery-zone-loading-cities {
50
+ display: none;
51
+ position: absolute;
52
+ right: 16px;
53
+ top: 50%;
54
+ transform: translateY(-50%);
55
+ display: none;
56
+ align-items: center;
57
+ gap: 8px;
58
+ font-size: 12px;
59
+ color: #6b7280;
60
+ }
61
+
62
+ .delivery-zone-loading-cities.active {
63
+ display: flex;
64
+ }
65
+
66
+ .spinner-small {
67
+ width: 16px;
68
+ height: 16px;
69
+ border: 2px solid #e5e7eb;
70
+ border-top-color: #a78bfa;
71
+ border-radius: 50%;
72
+ animation: spin 0.8s linear infinite;
73
+ }
74
+
75
+ @keyframes spin {
76
+ to { transform: rotate(360deg); }
77
+ }
78
+ </style>
79
+