@spwig/theme-cli 1.0.0 → 2.0.0
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/CHANGELOG.md +77 -0
- package/README.md +0 -0
- package/dist/cli.d.ts +0 -0
- package/dist/cli.d.ts.map +0 -0
- package/dist/cli.js +14 -22
- package/dist/cli.js.map +1 -1
- package/dist/commands/component.d.ts +0 -0
- package/dist/commands/component.d.ts.map +0 -0
- package/dist/commands/component.js +0 -0
- package/dist/commands/component.js.map +0 -0
- package/dist/commands/dev.d.ts +14 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +310 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/init.d.ts +5 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +80 -115
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/package.d.ts +0 -0
- package/dist/commands/package.d.ts.map +1 -1
- package/dist/commands/package.js +0 -2
- package/dist/commands/package.js.map +1 -1
- package/dist/commands/validate.d.ts +1 -2
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +10 -112
- package/dist/commands/validate.js.map +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/schemas/component_manifest_schema.json +0 -0
- package/dist/schemas/theme_manifest_schema.json +5 -63
- package/dist/templates/assets/logo.svg.template +6 -0
- package/dist/templates/assets/theme.js.template +150 -0
- package/dist/templates/components/blank.template.html.template +0 -0
- package/dist/templates/components/footer.manifest.json.template +0 -0
- package/dist/templates/components/footer.schema.json.template +22 -0
- package/dist/templates/components/footer.styles.css.template +80 -0
- package/dist/templates/components/footer.template.html.template +0 -0
- package/dist/templates/components/header.manifest.json.template +0 -0
- package/dist/templates/components/header.schema.json.template +0 -0
- package/dist/templates/components/header.styles.css.template +104 -0
- package/dist/templates/components/header.template.html.template +0 -0
- package/dist/templates/components/schema.json.template +0 -0
- package/dist/templates/components/section.manifest.json.template +2 -2
- package/dist/templates/components/section.schema.json.template +40 -0
- package/dist/templates/components/section.styles.css.template +60 -0
- package/dist/templates/components/section.template.html.template +0 -0
- package/dist/templates/components/utility.manifest.json.template +0 -0
- package/dist/templates/pages/cart.html.template +104 -0
- package/dist/templates/pages/collection.html.template +86 -0
- package/dist/templates/pages/home.html.template +51 -0
- package/dist/templates/pages/layout.html.template +48 -0
- package/dist/templates/pages/product.html.template +90 -0
- package/dist/templates/presets/footer.json.template +16 -0
- package/dist/templates/presets/header.json.template +16 -0
- package/dist/templates/theme/README.md.template +51 -21
- package/dist/templates/theme/design_tokens.json.template +0 -0
- package/dist/templates/theme/manifest.json.template +6 -28
- package/dist/templates/theme/tokens.json.template +1254 -0
- package/dist/utils/file-system.d.ts +0 -0
- package/dist/utils/file-system.d.ts.map +0 -0
- package/dist/utils/file-system.js +0 -0
- package/dist/utils/file-system.js.map +0 -0
- package/dist/utils/validation.d.ts +0 -0
- package/dist/utils/validation.d.ts.map +0 -0
- package/dist/utils/validation.js +0 -0
- package/dist/utils/validation.js.map +0 -0
- package/package.json +6 -3
- package/schemas/theme_manifest_schema.json +5 -63
- package/schemas/component_manifest_schema.json +0 -221
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"title": "Theme Package Manifest Schema",
|
|
4
|
-
"description": "Schema for Spwig theme package manifests
|
|
4
|
+
"description": "Schema for Spwig v2.0 theme package manifests",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"required": [
|
|
7
7
|
"name",
|
|
@@ -41,74 +41,16 @@
|
|
|
41
41
|
"maxLength": 100,
|
|
42
42
|
"description": "Theme author/vendor name"
|
|
43
43
|
},
|
|
44
|
+
"sdk_version": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"description": "SDK version used to create this theme (e.g., '2.0')"
|
|
47
|
+
},
|
|
44
48
|
"license": {
|
|
45
49
|
"type": "string",
|
|
46
50
|
"enum": ["MIT", "Apache-2.0", "GPL-3.0", "Proprietary"],
|
|
47
51
|
"default": "Proprietary",
|
|
48
52
|
"description": "Theme license type"
|
|
49
53
|
},
|
|
50
|
-
"bundled_components": {
|
|
51
|
-
"type": "array",
|
|
52
|
-
"items": {
|
|
53
|
-
"type": "object",
|
|
54
|
-
"required": ["type", "name", "path"],
|
|
55
|
-
"properties": {
|
|
56
|
-
"type": {
|
|
57
|
-
"type": "string",
|
|
58
|
-
"enum": ["header", "footer", "section", "utility"],
|
|
59
|
-
"description": "Component type"
|
|
60
|
-
},
|
|
61
|
-
"name": {
|
|
62
|
-
"type": "string",
|
|
63
|
-
"pattern": "^[a-z][a-z0-9_-]*$",
|
|
64
|
-
"description": "Component name"
|
|
65
|
-
},
|
|
66
|
-
"path": {
|
|
67
|
-
"type": "string",
|
|
68
|
-
"pattern": "^components/",
|
|
69
|
-
"description": "Relative path to component directory"
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
"description": "List of components bundled with this theme"
|
|
74
|
-
},
|
|
75
|
-
"page_schemas": {
|
|
76
|
-
"type": "object",
|
|
77
|
-
"properties": {
|
|
78
|
-
"home": {
|
|
79
|
-
"type": "string",
|
|
80
|
-
"description": "Path to home page schema"
|
|
81
|
-
},
|
|
82
|
-
"product": {
|
|
83
|
-
"type": "string",
|
|
84
|
-
"description": "Path to product page schema"
|
|
85
|
-
},
|
|
86
|
-
"collection": {
|
|
87
|
-
"type": "string",
|
|
88
|
-
"description": "Path to collection page schema"
|
|
89
|
-
},
|
|
90
|
-
"cart": {
|
|
91
|
-
"type": "string",
|
|
92
|
-
"description": "Path to cart page schema"
|
|
93
|
-
},
|
|
94
|
-
"checkout": {
|
|
95
|
-
"type": "string",
|
|
96
|
-
"description": "Path to checkout page schema"
|
|
97
|
-
},
|
|
98
|
-
"landing": {
|
|
99
|
-
"type": "string",
|
|
100
|
-
"description": "Path to landing page schema"
|
|
101
|
-
}
|
|
102
|
-
},
|
|
103
|
-
"additionalProperties": {
|
|
104
|
-
"type": "string"
|
|
105
|
-
},
|
|
106
|
-
"description": "Page schema file paths"
|
|
107
|
-
},
|
|
108
|
-
"design_tokens": {
|
|
109
|
-
"type": "string",
|
|
110
|
-
"description": "Path to design tokens file (colors, fonts, spacing)"
|
|
111
|
-
},
|
|
112
54
|
"preview_image": {
|
|
113
55
|
"type": "string",
|
|
114
56
|
"pattern": "^.+\\.(png|jpg|jpeg|webp)$",
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 60" width="200" height="60">
|
|
2
|
+
<rect width="200" height="60" fill="#f3f4f6" rx="4"/>
|
|
3
|
+
<text x="100" y="38" text-anchor="middle" font-family="system-ui, sans-serif" font-size="14" fill="#9ca3af">
|
|
4
|
+
Your Logo
|
|
5
|
+
</text>
|
|
6
|
+
</svg>
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {{displayName}} - Theme JavaScript
|
|
3
|
+
*
|
|
4
|
+
* Main entry point for theme interactivity
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
(function() {
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Initialize theme when DOM is ready
|
|
12
|
+
*/
|
|
13
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
14
|
+
initProductGallery();
|
|
15
|
+
initQuantitySelectors();
|
|
16
|
+
initMobileMenu();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Product image gallery functionality
|
|
21
|
+
*/
|
|
22
|
+
function initProductGallery() {
|
|
23
|
+
const thumbnails = document.querySelectorAll('.thumbnail');
|
|
24
|
+
const mainImage = document.getElementById('main-product-image');
|
|
25
|
+
|
|
26
|
+
if (!mainImage || thumbnails.length === 0) return;
|
|
27
|
+
|
|
28
|
+
thumbnails.forEach(function(thumbnail) {
|
|
29
|
+
thumbnail.addEventListener('click', function() {
|
|
30
|
+
const newSrc = this.getAttribute('data-image');
|
|
31
|
+
if (newSrc) {
|
|
32
|
+
mainImage.src = newSrc;
|
|
33
|
+
|
|
34
|
+
// Update active state
|
|
35
|
+
thumbnails.forEach(t => t.classList.remove('active'));
|
|
36
|
+
this.classList.add('active');
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Quantity selector +/- buttons
|
|
44
|
+
*/
|
|
45
|
+
function initQuantitySelectors() {
|
|
46
|
+
const quantityInputs = document.querySelectorAll('.qty-input');
|
|
47
|
+
|
|
48
|
+
quantityInputs.forEach(function(input) {
|
|
49
|
+
input.addEventListener('change', function() {
|
|
50
|
+
const form = this.closest('form');
|
|
51
|
+
if (form && form.classList.contains('quantity-form')) {
|
|
52
|
+
form.submit();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Mobile menu toggle
|
|
60
|
+
*/
|
|
61
|
+
function initMobileMenu() {
|
|
62
|
+
const menuToggle = document.querySelector('.mobile-menu-toggle');
|
|
63
|
+
const mobileMenu = document.querySelector('.mobile-menu');
|
|
64
|
+
|
|
65
|
+
if (!menuToggle || !mobileMenu) return;
|
|
66
|
+
|
|
67
|
+
menuToggle.addEventListener('click', function() {
|
|
68
|
+
const isOpen = mobileMenu.classList.toggle('is-open');
|
|
69
|
+
menuToggle.setAttribute('aria-expanded', isOpen);
|
|
70
|
+
document.body.classList.toggle('menu-open', isOpen);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Add to cart with AJAX (optional enhancement)
|
|
76
|
+
*/
|
|
77
|
+
function initAjaxCart() {
|
|
78
|
+
const addToCartForms = document.querySelectorAll('.add-to-cart-form');
|
|
79
|
+
|
|
80
|
+
addToCartForms.forEach(function(form) {
|
|
81
|
+
form.addEventListener('submit', function(e) {
|
|
82
|
+
// Comment out to enable AJAX cart
|
|
83
|
+
// e.preventDefault();
|
|
84
|
+
// const formData = new FormData(form);
|
|
85
|
+
//
|
|
86
|
+
// fetch('/cart/add/', {
|
|
87
|
+
// method: 'POST',
|
|
88
|
+
// body: formData,
|
|
89
|
+
// headers: {
|
|
90
|
+
// 'X-Requested-With': 'XMLHttpRequest'
|
|
91
|
+
// }
|
|
92
|
+
// })
|
|
93
|
+
// .then(response => response.json())
|
|
94
|
+
// .then(data => {
|
|
95
|
+
// // Update cart count
|
|
96
|
+
// updateCartCount(data.item_count);
|
|
97
|
+
// // Show success message
|
|
98
|
+
// showNotification('Added to cart');
|
|
99
|
+
// })
|
|
100
|
+
// .catch(error => {
|
|
101
|
+
// console.error('Error:', error);
|
|
102
|
+
// });
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Update cart item count in header
|
|
109
|
+
*/
|
|
110
|
+
function updateCartCount(count) {
|
|
111
|
+
const cartCount = document.querySelector('.cart-count');
|
|
112
|
+
if (cartCount) {
|
|
113
|
+
cartCount.textContent = count;
|
|
114
|
+
cartCount.style.display = count > 0 ? 'flex' : 'none';
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Show notification message
|
|
120
|
+
*/
|
|
121
|
+
function showNotification(message, type) {
|
|
122
|
+
type = type || 'success';
|
|
123
|
+
|
|
124
|
+
const notification = document.createElement('div');
|
|
125
|
+
notification.className = 'notification notification-' + type;
|
|
126
|
+
notification.textContent = message;
|
|
127
|
+
|
|
128
|
+
document.body.appendChild(notification);
|
|
129
|
+
|
|
130
|
+
// Trigger animation
|
|
131
|
+
setTimeout(function() {
|
|
132
|
+
notification.classList.add('is-visible');
|
|
133
|
+
}, 10);
|
|
134
|
+
|
|
135
|
+
// Remove after delay
|
|
136
|
+
setTimeout(function() {
|
|
137
|
+
notification.classList.remove('is-visible');
|
|
138
|
+
setTimeout(function() {
|
|
139
|
+
notification.remove();
|
|
140
|
+
}, 300);
|
|
141
|
+
}, 3000);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Expose functions globally if needed
|
|
145
|
+
window.ThemeHelpers = {
|
|
146
|
+
updateCartCount: updateCartCount,
|
|
147
|
+
showNotification: showNotification
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
})();
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"settings": [
|
|
3
|
+
{
|
|
4
|
+
"id": "background_color",
|
|
5
|
+
"type": "color",
|
|
6
|
+
"label": "Background Color",
|
|
7
|
+
"default": "#f9fafb"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"id": "show_powered_by",
|
|
11
|
+
"type": "checkbox",
|
|
12
|
+
"label": "Show Powered by Spwig",
|
|
13
|
+
"default": true
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"id": "show_social_links",
|
|
17
|
+
"type": "checkbox",
|
|
18
|
+
"label": "Show Social Links",
|
|
19
|
+
"default": true
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/* Footer Component Styles */
|
|
2
|
+
|
|
3
|
+
.site-footer {
|
|
4
|
+
background-color: var(--background-secondary, #f9fafb);
|
|
5
|
+
border-top: 1px solid var(--border-color, #e5e7eb);
|
|
6
|
+
padding: var(--spacing-xl, 3rem) 0 var(--spacing-lg, 2rem);
|
|
7
|
+
margin-top: auto;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.footer-content {
|
|
11
|
+
display: grid;
|
|
12
|
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
13
|
+
gap: var(--spacing-lg, 2rem);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.footer-section h3 {
|
|
17
|
+
font-size: var(--heading-size-sm, 1.125rem);
|
|
18
|
+
font-weight: 600;
|
|
19
|
+
margin-bottom: var(--spacing-md, 1rem);
|
|
20
|
+
color: var(--text-color, #1f2937);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.footer-nav {
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
gap: var(--spacing-xs, 0.5rem);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.footer-nav a {
|
|
30
|
+
color: var(--text-secondary, #6b7280);
|
|
31
|
+
font-size: 0.875rem;
|
|
32
|
+
transition: color 0.2s;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.footer-nav a:hover {
|
|
36
|
+
color: var(--primary-color, #3b82f6);
|
|
37
|
+
text-decoration: none;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.contact-info {
|
|
41
|
+
display: flex;
|
|
42
|
+
flex-direction: column;
|
|
43
|
+
gap: var(--spacing-xs, 0.5rem);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.contact-info p {
|
|
47
|
+
color: var(--text-secondary, #6b7280);
|
|
48
|
+
font-size: 0.875rem;
|
|
49
|
+
margin: 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.footer-bottom {
|
|
53
|
+
grid-column: 1 / -1;
|
|
54
|
+
border-top: 1px solid var(--border-color, #e5e7eb);
|
|
55
|
+
margin-top: var(--spacing-lg, 2rem);
|
|
56
|
+
padding-top: var(--spacing-lg, 2rem);
|
|
57
|
+
display: flex;
|
|
58
|
+
justify-content: space-between;
|
|
59
|
+
align-items: center;
|
|
60
|
+
flex-wrap: wrap;
|
|
61
|
+
gap: var(--spacing-sm, 0.75rem);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.footer-bottom p {
|
|
65
|
+
margin: 0;
|
|
66
|
+
font-size: 0.875rem;
|
|
67
|
+
color: var(--text-secondary, #6b7280);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* Responsive */
|
|
71
|
+
@media (max-width: 768px) {
|
|
72
|
+
.footer-content {
|
|
73
|
+
grid-template-columns: 1fr;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.footer-bottom {
|
|
77
|
+
flex-direction: column;
|
|
78
|
+
text-align: center;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/* Header Component Styles */
|
|
2
|
+
|
|
3
|
+
.site-header {
|
|
4
|
+
background-color: var(--background-color, #ffffff);
|
|
5
|
+
border-bottom: 1px solid var(--border-color, #e5e7eb);
|
|
6
|
+
padding: var(--spacing-md, 1rem) 0;
|
|
7
|
+
position: sticky;
|
|
8
|
+
top: 0;
|
|
9
|
+
z-index: 100;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.header-content {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
justify-content: space-between;
|
|
16
|
+
gap: var(--spacing-md, 1rem);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.header-logo {
|
|
20
|
+
flex-shrink: 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.logo-image {
|
|
24
|
+
max-height: 48px;
|
|
25
|
+
width: auto;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.logo-text {
|
|
29
|
+
font-size: var(--heading-size-lg, 1.5rem);
|
|
30
|
+
font-weight: 700;
|
|
31
|
+
color: var(--text-color, #1f2937);
|
|
32
|
+
text-decoration: none;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.logo-text:hover {
|
|
36
|
+
text-decoration: none;
|
|
37
|
+
color: var(--primary-color, #3b82f6);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.main-navigation {
|
|
41
|
+
display: flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
gap: var(--spacing-md, 1rem);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.nav-link {
|
|
47
|
+
color: var(--text-color, #1f2937);
|
|
48
|
+
font-weight: 500;
|
|
49
|
+
padding: var(--spacing-xs, 0.5rem) var(--spacing-sm, 0.75rem);
|
|
50
|
+
border-radius: var(--border-radius, 4px);
|
|
51
|
+
transition: background-color 0.2s, color 0.2s;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.nav-link:hover {
|
|
55
|
+
background-color: var(--background-secondary, #f3f4f6);
|
|
56
|
+
color: var(--primary-color, #3b82f6);
|
|
57
|
+
text-decoration: none;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.header-actions {
|
|
61
|
+
display: flex;
|
|
62
|
+
align-items: center;
|
|
63
|
+
gap: var(--spacing-sm, 0.75rem);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.cart-link {
|
|
67
|
+
position: relative;
|
|
68
|
+
display: flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
padding: var(--spacing-xs, 0.5rem);
|
|
71
|
+
color: var(--text-color, #1f2937);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.cart-link:hover {
|
|
75
|
+
color: var(--primary-color, #3b82f6);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.cart-icon {
|
|
79
|
+
width: 24px;
|
|
80
|
+
height: 24px;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.cart-count {
|
|
84
|
+
position: absolute;
|
|
85
|
+
top: -4px;
|
|
86
|
+
right: -4px;
|
|
87
|
+
background-color: var(--primary-color, #3b82f6);
|
|
88
|
+
color: white;
|
|
89
|
+
font-size: 0.75rem;
|
|
90
|
+
font-weight: 600;
|
|
91
|
+
min-width: 18px;
|
|
92
|
+
height: 18px;
|
|
93
|
+
border-radius: 50%;
|
|
94
|
+
display: flex;
|
|
95
|
+
align-items: center;
|
|
96
|
+
justify-content: center;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* Responsive */
|
|
100
|
+
@media (max-width: 768px) {
|
|
101
|
+
.main-navigation {
|
|
102
|
+
display: none;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"settings": [
|
|
3
|
+
{
|
|
4
|
+
"id": "title",
|
|
5
|
+
"type": "text",
|
|
6
|
+
"label": "Title",
|
|
7
|
+
"default": "Welcome"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"id": "description",
|
|
11
|
+
"type": "textarea",
|
|
12
|
+
"label": "Description",
|
|
13
|
+
"default": "Discover our amazing products"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"id": "background_color",
|
|
17
|
+
"type": "color",
|
|
18
|
+
"label": "Background Color",
|
|
19
|
+
"default": "#ffffff"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "show_button",
|
|
23
|
+
"type": "checkbox",
|
|
24
|
+
"label": "Show Button",
|
|
25
|
+
"default": true
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"id": "button_text",
|
|
29
|
+
"type": "text",
|
|
30
|
+
"label": "Button Text",
|
|
31
|
+
"default": "Shop Now"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"id": "button_url",
|
|
35
|
+
"type": "url",
|
|
36
|
+
"label": "Button URL",
|
|
37
|
+
"default": "/products"
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/* Hero Section Component Styles */
|
|
2
|
+
|
|
3
|
+
.hero-section {
|
|
4
|
+
padding: var(--spacing-xxl, 5rem) 0;
|
|
5
|
+
background-color: var(--background-color, #ffffff);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.hero-content {
|
|
9
|
+
max-width: 800px;
|
|
10
|
+
margin: 0 auto;
|
|
11
|
+
text-align: center;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.hero-title {
|
|
15
|
+
font-family: var(--heading-font, inherit);
|
|
16
|
+
font-size: var(--heading-size-xxl, 3rem);
|
|
17
|
+
font-weight: 700;
|
|
18
|
+
color: var(--text-color, #1f2937);
|
|
19
|
+
margin-bottom: var(--spacing-md, 1rem);
|
|
20
|
+
line-height: 1.2;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.hero-description {
|
|
24
|
+
font-size: var(--text-lg, 1.25rem);
|
|
25
|
+
color: var(--text-secondary, #6b7280);
|
|
26
|
+
margin-bottom: var(--spacing-lg, 2rem);
|
|
27
|
+
line-height: 1.6;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.hero-button {
|
|
31
|
+
display: inline-block;
|
|
32
|
+
padding: var(--spacing-sm, 0.75rem) var(--spacing-lg, 2rem);
|
|
33
|
+
background-color: var(--primary-color, #3b82f6);
|
|
34
|
+
color: white;
|
|
35
|
+
font-weight: 600;
|
|
36
|
+
border-radius: var(--border-radius, 4px);
|
|
37
|
+
text-decoration: none;
|
|
38
|
+
transition: background-color 0.2s, transform 0.2s;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.hero-button:hover {
|
|
42
|
+
background-color: var(--primary-dark, #2563eb);
|
|
43
|
+
text-decoration: none;
|
|
44
|
+
transform: translateY(-1px);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* Responsive */
|
|
48
|
+
@media (max-width: 768px) {
|
|
49
|
+
.hero-section {
|
|
50
|
+
padding: var(--spacing-xl, 3rem) 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.hero-title {
|
|
54
|
+
font-size: var(--heading-size-xl, 2rem);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.hero-description {
|
|
58
|
+
font-size: var(--text-md, 1rem);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
{% extends "layout.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}Shopping Cart - {{ store.name }}{% endblock %}
|
|
4
|
+
|
|
5
|
+
{% block body_class %}page-cart{% endblock %}
|
|
6
|
+
|
|
7
|
+
{% block content %}
|
|
8
|
+
<div class="cart-page">
|
|
9
|
+
<div class="container">
|
|
10
|
+
<h1 class="page-title">Shopping Cart</h1>
|
|
11
|
+
|
|
12
|
+
{% if cart.items %}
|
|
13
|
+
<div class="cart-layout">
|
|
14
|
+
<!-- Cart Items -->
|
|
15
|
+
<div class="cart-items">
|
|
16
|
+
{% for item in cart.items %}
|
|
17
|
+
<div class="cart-item" data-item-id="{{ item.id }}">
|
|
18
|
+
<div class="item-image">
|
|
19
|
+
{% if item.image %}
|
|
20
|
+
<img src="{{ item.image }}" alt="{{ item.title }}">
|
|
21
|
+
{% endif %}
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<div class="item-details">
|
|
25
|
+
<h3 class="item-title">
|
|
26
|
+
<a href="{{ item.url }}">{{ item.title }}</a>
|
|
27
|
+
</h3>
|
|
28
|
+
{% if item.variant_title %}
|
|
29
|
+
<p class="item-variant">{{ item.variant_title }}</p>
|
|
30
|
+
{% endif %}
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<div class="item-quantity">
|
|
34
|
+
<form action="/cart/update/" method="post" class="quantity-form">
|
|
35
|
+
{% csrf_token %}
|
|
36
|
+
<input type="hidden" name="item_id" value="{{ item.id }}">
|
|
37
|
+
<button type="button" class="qty-btn minus" onclick="this.nextElementSibling.stepDown(); this.form.submit();">-</button>
|
|
38
|
+
<input type="number" name="quantity" value="{{ item.quantity }}" min="0" max="99" class="qty-input">
|
|
39
|
+
<button type="button" class="qty-btn plus" onclick="this.previousElementSibling.stepUp(); this.form.submit();">+</button>
|
|
40
|
+
</form>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<div class="item-price">
|
|
44
|
+
{{ item.line_price|currency }}
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<form action="/cart/remove/" method="post" class="remove-form">
|
|
48
|
+
{% csrf_token %}
|
|
49
|
+
<input type="hidden" name="item_id" value="{{ item.id }}">
|
|
50
|
+
<button type="submit" class="remove-btn" aria-label="Remove item">
|
|
51
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
52
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
53
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
54
|
+
</svg>
|
|
55
|
+
</button>
|
|
56
|
+
</form>
|
|
57
|
+
</div>
|
|
58
|
+
{% endfor %}
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<!-- Cart Summary -->
|
|
62
|
+
<div class="cart-summary">
|
|
63
|
+
<h2>Order Summary</h2>
|
|
64
|
+
|
|
65
|
+
<div class="summary-line">
|
|
66
|
+
<span>Subtotal</span>
|
|
67
|
+
<span>{{ cart.subtotal|currency }}</span>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
{% if cart.discount %}
|
|
71
|
+
<div class="summary-line discount">
|
|
72
|
+
<span>Discount</span>
|
|
73
|
+
<span>-{{ cart.discount|currency }}</span>
|
|
74
|
+
</div>
|
|
75
|
+
{% endif %}
|
|
76
|
+
|
|
77
|
+
<div class="summary-line shipping">
|
|
78
|
+
<span>Shipping</span>
|
|
79
|
+
<span>Calculated at checkout</span>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<div class="summary-total">
|
|
83
|
+
<span>Total</span>
|
|
84
|
+
<span>{{ cart.total|currency }}</span>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<a href="/checkout/" class="checkout-button">
|
|
88
|
+
Proceed to Checkout
|
|
89
|
+
</a>
|
|
90
|
+
|
|
91
|
+
<a href="/" class="continue-shopping">
|
|
92
|
+
Continue Shopping
|
|
93
|
+
</a>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
{% else %}
|
|
97
|
+
<div class="cart-empty">
|
|
98
|
+
<p>Your cart is empty.</p>
|
|
99
|
+
<a href="/" class="continue-shopping-button">Continue Shopping</a>
|
|
100
|
+
</div>
|
|
101
|
+
{% endif %}
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
{% endblock %}
|