astro-component-kit 0.4.0 → 0.5.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.
Files changed (208) hide show
  1. package/README.md +139 -27
  2. package/bin/cli.js +67 -0
  3. package/bin/installer.js +179 -0
  4. package/package.json +35 -5
  5. package/src/components/index.ts +2 -0
  6. package/src/components/lib/Galaxy3D.astro +249 -137
  7. package/src/components/lib/app/AppSidebar.astro +249 -0
  8. package/src/components/lib/app/AppTopbar.astro +284 -0
  9. package/src/components/lib/app/ArrivalsBoard.astro +176 -0
  10. package/src/components/lib/app/AuthCard.astro +213 -0
  11. package/src/components/lib/app/DataTable.astro +346 -0
  12. package/src/components/lib/app/GuestProfileCard.astro +133 -0
  13. package/src/components/lib/app/HousekeepingBoard.astro +189 -0
  14. package/src/components/lib/app/PageHeader.astro +157 -0
  15. package/src/components/lib/app/PlanUsageCard.astro +112 -0
  16. package/src/components/lib/app/RoomRack.astro +207 -0
  17. package/src/components/lib/app/SettingsSection.astro +96 -0
  18. package/src/components/lib/app/SwitchRow.astro +71 -0
  19. package/src/components/lib/app/TeamMembers.astro +190 -0
  20. package/src/components/lib/app/app-icons.ts +52 -0
  21. package/src/components/lib/app/index.ts +19 -0
  22. package/src/components/lib/charts/AreaChart.astro +4 -4
  23. package/src/components/lib/charts/BarChart.astro +3 -3
  24. package/src/components/lib/charts/ChartFrame.astro +10 -10
  25. package/src/components/lib/charts/DonutChart.astro +2 -2
  26. package/src/components/lib/charts/DumbbellChart.astro +1 -1
  27. package/src/components/lib/charts/ForecastLineChart.astro +1 -1
  28. package/src/components/lib/charts/GaugeChart.astro +1 -1
  29. package/src/components/lib/charts/HeatmapChart.astro +1 -1
  30. package/src/components/lib/charts/HorizontalBarChart.astro +2 -2
  31. package/src/components/lib/charts/KpiStatTile.astro +4 -4
  32. package/src/components/lib/charts/LinearProgressGauge.astro +4 -4
  33. package/src/components/lib/charts/MetricDeltaTable.astro +3 -3
  34. package/src/components/lib/charts/RadarMetricChart.astro +4 -4
  35. package/src/components/lib/charts/RadialBarChart.astro +1 -1
  36. package/src/components/lib/charts/RetentionCohortTable.astro +2 -2
  37. package/src/components/lib/charts/TreemapChart.astro +1 -1
  38. package/src/components/lib/ecommerce/CartDrawer.astro +483 -0
  39. package/src/components/lib/ecommerce/CartPageList.astro +290 -0
  40. package/src/components/lib/ecommerce/CartToast.astro +276 -0
  41. package/src/components/lib/ecommerce/CategoryTiles.astro +143 -0
  42. package/src/components/lib/ecommerce/CheckoutForm.astro +423 -0
  43. package/src/components/lib/ecommerce/CountdownBanner.astro +230 -0
  44. package/src/components/lib/ecommerce/FilterBar.astro +278 -0
  45. package/src/components/lib/ecommerce/FilterSidebar.astro +405 -0
  46. package/src/components/lib/ecommerce/LiveActivityToast.astro +213 -0
  47. package/src/components/lib/ecommerce/OrderSummary.astro +295 -0
  48. package/src/components/lib/ecommerce/ProductBuyBox.astro +247 -0
  49. package/src/components/lib/ecommerce/ProductCardMinimal.astro +229 -0
  50. package/src/components/lib/ecommerce/ProductGallery.astro +145 -0
  51. package/src/components/lib/ecommerce/ProductGrid.astro +118 -0
  52. package/src/components/lib/ecommerce/ProductMedia.astro +113 -0
  53. package/src/components/lib/ecommerce/ProductRating.astro +78 -0
  54. package/src/components/lib/ecommerce/ProductToolbar.astro +93 -0
  55. package/src/components/lib/ecommerce/PromoBar.astro +145 -0
  56. package/src/components/lib/ecommerce/StockIndicator.astro +127 -0
  57. package/src/components/lib/ecommerce/StoreHeader.astro +446 -0
  58. package/src/components/lib/ecommerce/StoreHero.astro +260 -0
  59. package/src/components/lib/ecommerce/StoreProductCard.astro +307 -0
  60. package/src/components/lib/ecommerce/TrustBadges.astro +101 -0
  61. package/src/components/lib/ecommerce/VariantPicker.astro +145 -0
  62. package/src/components/lib/ecommerce/cart-store.ts +151 -0
  63. package/src/components/lib/ecommerce/catalog-filter.ts +62 -0
  64. package/src/components/lib/ecommerce/index.ts +34 -0
  65. package/src/components/lib/ecommerce/product-icons.ts +28 -0
  66. package/src/components/lib/ecommerce/types.ts +70 -0
  67. package/src/components/lib/forms/AnimatedInput.astro +4 -2
  68. package/src/components/lib/forms/CustomRadioGroup.astro +3 -1
  69. package/src/components/lib/index.ts +2 -0
  70. package/src/components/lib/layout/BentoGrid3.astro +6 -4
  71. package/src/components/lib/layout/CenterFixedBox.astro +2 -2
  72. package/src/components/lib/layout/CenteredContainer.astro +4 -2
  73. package/src/components/lib/layout/ClusterHorizontal.astro +2 -2
  74. package/src/components/lib/layout/FeatureHero.astro +4 -2
  75. package/src/components/lib/layout/FooterCenteredMinimal.astro +4 -2
  76. package/src/components/lib/layout/FullBleedSection.astro +2 -2
  77. package/src/components/lib/layout/GalleryGrid4.astro +2 -2
  78. package/src/components/lib/layout/HolyGrailGrid.astro +11 -9
  79. package/src/components/lib/layout/LandingSectionSplit.astro +5 -3
  80. package/src/components/lib/layout/MasonryGrid.astro +2 -2
  81. package/src/components/lib/layout/MinimalFooterGrid.astro +1 -1
  82. package/src/components/lib/layout/ScrollSnapSection.astro +1 -1
  83. package/src/components/lib/layout/SidebarLayoutWrapper.astro +4 -2
  84. package/src/components/lib/layout/SplitScreenLayout.astro +3 -3
  85. package/src/components/lib/layout/StepLayoutVertical.astro +1 -1
  86. package/src/components/lib/layout/StickySidebarWrapper.astro +4 -2
  87. package/src/components/lib/sections/AgencyContactBrief.astro +194 -0
  88. package/src/components/lib/sections/AgencyFooterCta.astro +94 -0
  89. package/src/components/lib/sections/AgencyHeader.astro +161 -0
  90. package/src/components/lib/sections/AgencyHeroKinetic.astro +172 -0
  91. package/src/components/lib/sections/AgencyServicesList.astro +113 -0
  92. package/src/components/lib/sections/AgencyTeamGrid.astro +111 -0
  93. package/src/components/lib/sections/AgencyWorkGrid.astro +147 -0
  94. package/src/components/lib/sections/BlogGridSection.astro +9 -7
  95. package/src/components/lib/sections/ButtonsShowcase.astro +20 -18
  96. package/src/components/lib/sections/CardsShowcase.astro +28 -26
  97. package/src/components/lib/sections/CareersOpenings.astro +10 -8
  98. package/src/components/lib/sections/ChangelogSection.astro +20 -7
  99. package/src/components/lib/sections/ContactGlassForm.astro +10 -8
  100. package/src/components/lib/sections/ContactSplitMap.astro +11 -9
  101. package/src/components/lib/sections/CtaAppDownload.astro +13 -11
  102. package/src/components/lib/sections/CtaGlowBanner.astro +12 -10
  103. package/src/components/lib/sections/CtaNewsletterSection.astro +13 -11
  104. package/src/components/lib/sections/CtaSplitImage.astro +13 -11
  105. package/src/components/lib/sections/DataShowcase.astro +23 -21
  106. package/src/components/lib/sections/FaqAccordionSection.astro +8 -8
  107. package/src/components/lib/sections/FaqTwoColumn.astro +9 -7
  108. package/src/components/lib/sections/FeatureAlternatingRows.astro +10 -8
  109. package/src/components/lib/sections/FeatureBentoGrid.astro +13 -11
  110. package/src/components/lib/sections/FeatureIconGrid.astro +6 -6
  111. package/src/components/lib/sections/FeatureTabsShowcase.astro +13 -11
  112. package/src/components/lib/sections/FeatureTimelineFlow.astro +8 -6
  113. package/src/components/lib/sections/FeedbackShowcase.astro +15 -13
  114. package/src/components/lib/sections/FooterMegaSection.astro +13 -11
  115. package/src/components/lib/sections/FormsShowcase.astro +22 -20
  116. package/src/components/lib/sections/HeroDashboardPreview.astro +11 -9
  117. package/src/components/lib/sections/HeroGlass.astro +22 -20
  118. package/src/components/lib/sections/HeroGradient.astro +15 -13
  119. package/src/components/lib/sections/HeroMinimalCentered.astro +10 -10
  120. package/src/components/lib/sections/HeroShowcaseSplit.astro +18 -16
  121. package/src/components/lib/sections/HeroSplit.astro +13 -11
  122. package/src/components/lib/sections/HeroTerminal.astro +14 -12
  123. package/src/components/lib/sections/HeroWaitlist.astro +10 -8
  124. package/src/components/lib/sections/HowItWorksSteps.astro +12 -10
  125. package/src/components/lib/sections/IntegrationsGrid.astro +7 -7
  126. package/src/components/lib/sections/LayoutShowcase.astro +21 -19
  127. package/src/components/lib/sections/LogoCloudSection.astro +4 -4
  128. package/src/components/lib/sections/LogoWallGrid.astro +6 -4
  129. package/src/components/lib/sections/NavigationShowcase.astro +15 -13
  130. package/src/components/lib/sections/OverlaysShowcase.astro +21 -19
  131. package/src/components/lib/sections/PricingComparisonMatrix.astro +15 -13
  132. package/src/components/lib/sections/PricingSinglePlan.astro +13 -11
  133. package/src/components/lib/sections/PricingTierCards.astro +11 -9
  134. package/src/components/lib/sections/PricingToggleCards.astro +13 -13
  135. package/src/components/lib/sections/ShopCategoryHero.astro +103 -0
  136. package/src/components/lib/sections/ShopCollectionMosaic.astro +131 -0
  137. package/src/components/lib/sections/ShopFooterWordmark.astro +100 -0
  138. package/src/components/lib/sections/ShopHeaderEditorial.astro +396 -0
  139. package/src/components/lib/sections/ShopHeroEditorial.astro +151 -0
  140. package/src/components/lib/sections/ShopLookbook.astro +250 -0
  141. package/src/components/lib/sections/ShopNewsletterEditorial.astro +128 -0
  142. package/src/components/lib/sections/ShopProductRail.astro +150 -0
  143. package/src/components/lib/sections/ShopReviewsEditorial.astro +133 -0
  144. package/src/components/lib/sections/ShopValuesMarquee.astro +91 -0
  145. package/src/components/lib/sections/StatsCounterBand.astro +9 -7
  146. package/src/components/lib/sections/StatsDashboardSection.astro +4 -2
  147. package/src/components/lib/sections/StatsMetricShowcase.astro +9 -7
  148. package/src/components/lib/sections/TeamGridSection.astro +12 -10
  149. package/src/components/lib/sections/TestimonialCarousel.astro +10 -8
  150. package/src/components/lib/sections/TestimonialFeatured.astro +7 -5
  151. package/src/components/lib/sections/TestimonialGridSection.astro +7 -7
  152. package/src/components/lib/sections/TestimonialWallGlass.astro +11 -9
  153. package/src/components/lib/sections/TypographyShowcase.astro +10 -8
  154. package/src/components/lib/sections/index.ts +10 -0
  155. package/src/components/lib/templates/ecommerce/StoreCategoryPage.astro +160 -0
  156. package/src/components/lib/templates/ecommerce/StoreCheckoutPage.astro +98 -0
  157. package/src/components/lib/templates/ecommerce/StoreHomePage.astro +191 -0
  158. package/src/components/lib/templates/ecommerce/StoreLayout.astro +169 -0
  159. package/src/components/lib/templates/ecommerce/StoreProductPage.astro +165 -0
  160. package/src/components/lib/templates/ecommerce/data.ts +187 -0
  161. package/src/components/lib/templates/ecommerce/index.ts +14 -0
  162. package/src/components/lib/templates/ecommerce-editorial/EditorialBagPage.astro +52 -0
  163. package/src/components/lib/templates/ecommerce-editorial/EditorialCheckoutPage.astro +123 -0
  164. package/src/components/lib/templates/ecommerce-editorial/EditorialHomePage.astro +102 -0
  165. package/src/components/lib/templates/ecommerce-editorial/EditorialLayout.astro +216 -0
  166. package/src/components/lib/templates/ecommerce-editorial/EditorialProductPage.astro +205 -0
  167. package/src/components/lib/templates/ecommerce-editorial/EditorialShopPage.astro +112 -0
  168. package/src/components/lib/templates/ecommerce-editorial/data.ts +125 -0
  169. package/src/components/lib/templates/ecommerce-editorial/index.ts +16 -0
  170. package/src/components/lib/templates/saas-hotel/AppLayout.astro +83 -0
  171. package/src/components/lib/templates/saas-hotel/DashboardPage.astro +66 -0
  172. package/src/components/lib/templates/saas-hotel/GuestsPage.astro +65 -0
  173. package/src/components/lib/templates/saas-hotel/LandingPage.astro +213 -0
  174. package/src/components/lib/templates/saas-hotel/ReportsPage.astro +63 -0
  175. package/src/components/lib/templates/saas-hotel/ReservationsPage.astro +49 -0
  176. package/src/components/lib/templates/saas-hotel/RoomsPage.astro +48 -0
  177. package/src/components/lib/templates/saas-hotel/SettingsPage.astro +115 -0
  178. package/src/components/lib/templates/saas-hotel/SignInPage.astro +50 -0
  179. package/src/components/lib/templates/saas-hotel/data.ts +229 -0
  180. package/src/components/lib/templates/saas-hotel/index.ts +19 -0
  181. package/src/components/lib/templates/saas-hotel/lobby-theme.css +90 -0
  182. package/src/data/registry/app.ts +93 -0
  183. package/src/data/registry/buttons.ts +3279 -0
  184. package/src/data/registry/cards.ts +1753 -0
  185. package/src/data/registry/charts-svg.ts +557 -0
  186. package/src/data/registry/charts.ts +500 -0
  187. package/src/data/registry/data.ts +986 -0
  188. package/src/data/registry/ecommerce.ts +269 -0
  189. package/src/data/registry/feedback.ts +1824 -0
  190. package/src/data/registry/forms.ts +2513 -0
  191. package/src/data/registry/index.ts +64 -0
  192. package/src/data/registry/layout.ts +206 -0
  193. package/src/data/registry/navigation.ts +936 -0
  194. package/src/data/registry/overlays.ts +1133 -0
  195. package/src/data/registry/sections-extra.ts +397 -0
  196. package/src/data/registry/sections.ts +361 -0
  197. package/src/data/registry/sources.ts +41 -0
  198. package/src/data/registry/templates.ts +414 -0
  199. package/src/data/registry/types.ts +30 -0
  200. package/src/data/registry/typography.ts +777 -0
  201. package/src/mcp/http-server.ts +324 -0
  202. package/src/mcp/index.ts +67 -0
  203. package/src/mcp/installer.ts +178 -0
  204. package/src/mcp/registry-adapter.ts +278 -0
  205. package/src/mcp/stdio-server.ts +11 -0
  206. package/src/mcp/tools.ts +247 -0
  207. package/src/mcp/types.ts +53 -0
  208. package/src/styles/global.css +95 -0
@@ -0,0 +1,187 @@
1
+ // src/components/lib/templates/ecommerce/data.ts
2
+ // Demo catalogue and settings for the e-commerce template.
3
+ // Copy this file, replace the products and settings with yours, and pass it as `store`.
4
+
5
+ import type { Product, ShippingRate, StoreCategory } from '../../ecommerce/types';
6
+
7
+ export interface StoreRoutes {
8
+ /** Store home. */
9
+ home: string;
10
+ /** Catalogue / category page. Category links add `?category=<id>`. */
11
+ shop: string;
12
+ /** Product URL prefix — product pages live at `${product}${slug}/`. */
13
+ product: string;
14
+ /** Checkout page. */
15
+ checkout: string;
16
+ }
17
+
18
+ export interface StoreConfig {
19
+ name: string;
20
+ tagline: string;
21
+ currency: string;
22
+ locale: string;
23
+ cartKey: string;
24
+ freeShippingThreshold: number;
25
+ taxRate: number;
26
+ promoCodes: Record<string, number>;
27
+ promoMessages: string[];
28
+ shippingRates: ShippingRate[];
29
+ categories: StoreCategory[];
30
+ products: Product[];
31
+ /** Recent purchases shown by LiveActivityToast (product = slug). */
32
+ recentBuyers: Array<{ name: string; city: string; product: string; ago: string }>;
33
+ /** Product slugs featured on the home page. */
34
+ bestSellers: string[];
35
+ newArrivals: string[];
36
+ footer: Array<{ title: string; links: Array<{ label: string; href: string }> }>;
37
+ }
38
+
39
+ export const defaultRoutes: StoreRoutes = {
40
+ home: '/',
41
+ shop: '/shop/',
42
+ product: '/product/',
43
+ checkout: '/checkout/',
44
+ };
45
+
46
+ const C = {
47
+ graphite: { name: 'Graphite', hex: '#2b2b2f' },
48
+ sand: { name: 'Sand', hex: '#d8c3a5' },
49
+ ocean: { name: 'Ocean', hex: '#3d6f9e' },
50
+ moss: { name: 'Moss', hex: '#5f7a4e' },
51
+ clay: { name: 'Clay', hex: '#b5654a' },
52
+ snow: { name: 'Snow', hex: '#e9e9ea' },
53
+ };
54
+
55
+ export const demoStore: StoreConfig = {
56
+ name: 'Nova Store',
57
+ tagline: 'Considered gear for everyday life. Designed in small batches, built to last.',
58
+ currency: 'USD',
59
+ locale: 'en-US',
60
+ cartKey: 'nova-cart',
61
+ freeShippingThreshold: 75,
62
+ taxRate: 0.08,
63
+ promoCodes: { ASTRO10: 10, WELCOME15: 15 },
64
+ promoMessages: [
65
+ 'Free shipping on orders over $75',
66
+ 'Use code ASTRO10 for 10% off your first order',
67
+ '30-day free returns on everything',
68
+ ],
69
+ shippingRates: [
70
+ { id: 'standard', label: 'Standard', eta: '3–5 business days', price: 6 },
71
+ { id: 'express', label: 'Express', eta: '1–2 business days', price: 14 },
72
+ { id: 'pickup', label: 'Store pickup', eta: 'Ready in 2 hours', price: 0 },
73
+ ],
74
+ categories: [
75
+ { id: 'audio', name: 'Audio', description: 'Headphones and speakers tuned for warm, detailed sound.', icon: 'headphones', hue: 38 },
76
+ { id: 'wearables', name: 'Wearables', description: 'Watches and eyewear that keep up with your day.', icon: 'watch', hue: 205 },
77
+ { id: 'bags', name: 'Bags', description: 'Backpacks and totes for commutes and weekends.', icon: 'backpack', hue: 150 },
78
+ { id: 'home', name: 'Home', description: 'Lamps, mugs and planters for calmer spaces.', icon: 'lamp', hue: 22 },
79
+ { id: 'apparel', name: 'Apparel', description: 'Layers and sneakers made from better materials.', icon: 'jacket', hue: 280 },
80
+ ],
81
+ products: [
82
+ {
83
+ slug: 'aurora-headphones', name: 'Aurora Wireless Headphones', price: 189, compareAt: 229, category: 'audio',
84
+ rating: 4.8, reviews: 312, badge: 'Bestseller', badgeVariant: 'warning', icon: 'headphones', hue: 38,
85
+ colors: [C.graphite, C.sand, C.ocean], inStock: true, stock: 4,
86
+ description: 'Adaptive noise cancelling, 40-hour battery and memory-foam cushions that disappear after five minutes. Tuned in-house for a warm, detailed sound.',
87
+ },
88
+ {
89
+ slug: 'pulse-speaker', name: 'Pulse Portable Speaker', price: 129, category: 'audio',
90
+ rating: 4.6, reviews: 184, badge: 'New', badgeVariant: 'info', icon: 'speaker', hue: 262,
91
+ colors: [C.graphite, C.clay, C.moss], inStock: true,
92
+ description: '360° sound in a waterproof aluminium shell. 20 hours of playback and a strap that clips to anything.',
93
+ },
94
+ {
95
+ slug: 'orbit-watch', name: 'Orbit Smart Watch', price: 249, category: 'wearables',
96
+ rating: 4.7, reviews: 226, badge: 'New', badgeVariant: 'info', icon: 'watch', hue: 205,
97
+ colors: [C.graphite, C.snow, C.ocean, C.clay, C.moss], inStock: true, stock: 2,
98
+ description: 'Sapphire glass, seven-day battery and health tracking that stays out of your way until you need it.',
99
+ },
100
+ {
101
+ slug: 'solace-sunglasses', name: 'Solace Polarised Sunglasses', price: 139, category: 'wearables',
102
+ rating: 4.5, reviews: 98, icon: 'sunglasses', hue: 18,
103
+ colors: [C.graphite, C.sand], inStock: true,
104
+ description: 'Hand-polished acetate frames with polarised, UV400 lenses and a lifetime hinge warranty.',
105
+ },
106
+ {
107
+ slug: 'trail-backpack', name: 'Trail 24L Backpack', price: 119, category: 'bags',
108
+ rating: 4.9, reviews: 402, badge: 'Bestseller', badgeVariant: 'warning', icon: 'backpack', hue: 150,
109
+ colors: [C.moss, C.graphite, C.sand], inStock: true,
110
+ description: 'Recycled ripstop, a padded 16" laptop sleeve and a clamshell opening that packs like a suitcase.',
111
+ },
112
+ {
113
+ slug: 'city-tote', name: 'City Canvas Tote', price: 69, compareAt: 89, category: 'bags',
114
+ rating: 4.4, reviews: 76, badge: '-22%', badgeVariant: 'danger', icon: 'bag', hue: 32,
115
+ colors: [C.sand, C.graphite], inStock: true,
116
+ description: 'Waxed organic canvas with leather handles and an inner zip pocket. Gets better with age.',
117
+ },
118
+ {
119
+ slug: 'halo-lamp', name: 'Halo Desk Lamp', price: 89, category: 'home',
120
+ rating: 4.6, reviews: 143, icon: 'lamp', hue: 45,
121
+ colors: [C.snow, C.graphite, C.clay], inStock: true,
122
+ description: 'Dimmable, flicker-free light with a warm-to-cool range and a touch strip on the base.',
123
+ },
124
+ {
125
+ slug: 'ember-mug', name: 'Ember Stoneware Mug', price: 34, category: 'home',
126
+ rating: 4.8, reviews: 268, icon: 'mug', hue: 12,
127
+ colors: [C.clay, C.snow, C.ocean], inStock: true,
128
+ description: 'Hand-thrown stoneware, 350 ml, dishwasher and microwave safe. Every glaze is slightly unique.',
129
+ },
130
+ {
131
+ slug: 'fern-planter', name: 'Fern Ceramic Planter', price: 42, category: 'home',
132
+ rating: 4.3, reviews: 51, icon: 'plant', hue: 120,
133
+ colors: [C.snow, C.moss], inStock: true,
134
+ description: 'Matte ceramic planter with a hidden drainage tray, sized for 15 cm pots.',
135
+ },
136
+ {
137
+ slug: 'nomad-bottle', name: 'Nomad Insulated Bottle', price: 39, category: 'home',
138
+ rating: 4.7, reviews: 189, icon: 'bottle', hue: 190,
139
+ colors: [C.ocean, C.graphite, C.moss], inStock: false,
140
+ description: 'Keeps drinks cold for 24 hours or hot for 12. Leak-proof lid, 750 ml.',
141
+ },
142
+ {
143
+ slug: 'drift-sneakers', name: 'Drift Everyday Sneakers', price: 149, category: 'apparel',
144
+ rating: 4.6, reviews: 211, badge: 'Restocked', badgeVariant: 'success', icon: 'sneaker', hue: 0,
145
+ colors: [C.snow, C.graphite, C.sand], sizes: ['38', '39', '40', '41', '42', '43', '44'], inStock: true, stock: 3,
146
+ description: 'A cushioned sugarcane-foam sole and a knit upper you can throw in the washing machine.',
147
+ },
148
+ {
149
+ slug: 'storm-jacket', name: 'Storm Shell Jacket', price: 219, compareAt: 259, category: 'apparel',
150
+ rating: 4.8, reviews: 133, badge: '-15%', badgeVariant: 'danger', icon: 'jacket', hue: 280,
151
+ colors: [C.graphite, C.ocean, C.clay], sizes: ['XS', 'S', 'M', 'L', 'XL'], inStock: true, stock: 6,
152
+ description: 'Three-layer waterproof shell with taped seams, pit zips and a helmet-compatible hood.',
153
+ },
154
+ ],
155
+ recentBuyers: [
156
+ { name: 'Lucía', city: 'Madrid', product: 'aurora-headphones', ago: '2 min ago' },
157
+ { name: 'Tom', city: 'Berlin', product: 'trail-backpack', ago: '5 min ago' },
158
+ { name: 'Aiko', city: 'Osaka', product: 'orbit-watch', ago: '9 min ago' },
159
+ { name: 'Marco', city: 'Milan', product: 'drift-sneakers', ago: '14 min ago' },
160
+ { name: 'Chloé', city: 'Lyon', product: 'ember-mug', ago: '21 min ago' },
161
+ ],
162
+ bestSellers: ['aurora-headphones', 'trail-backpack', 'orbit-watch', 'ember-mug'],
163
+ newArrivals: ['pulse-speaker', 'drift-sneakers', 'storm-jacket', 'halo-lamp'],
164
+ footer: [
165
+ { title: 'Shop', links: [{ label: 'Audio', href: '#' }, { label: 'Wearables', href: '#' }, { label: 'Bags', href: '#' }, { label: 'Home', href: '#' }] },
166
+ { title: 'Help', links: [{ label: 'Shipping', href: '#' }, { label: 'Returns', href: '#' }, { label: 'Order status', href: '#' }, { label: 'Contact', href: '#' }] },
167
+ { title: 'Company', links: [{ label: 'About', href: '#' }, { label: 'Journal', href: '#' }, { label: 'Stores', href: '#' }] },
168
+ { title: 'Legal', links: [{ label: 'Privacy', href: '#' }, { label: 'Terms', href: '#' }, { label: 'Cookies', href: '#' }] },
169
+ ],
170
+ };
171
+
172
+ /** Helpers shared by the template pages. */
173
+ export function productHref(routes: StoreRoutes, slug: string): string {
174
+ return `${routes.product}${slug}/`;
175
+ }
176
+
177
+ export function categoryHref(routes: StoreRoutes, id?: string): string {
178
+ return id ? `${routes.shop}?category=${encodeURIComponent(id)}` : routes.shop;
179
+ }
180
+
181
+ export function categoryNames(store: StoreConfig): Record<string, string> {
182
+ return Object.fromEntries(store.categories.map((c) => [c.id, c.name]));
183
+ }
184
+
185
+ export function pickProducts(store: StoreConfig, slugs: string[]): Product[] {
186
+ return slugs.map((s) => store.products.find((p) => p.slug === s)).filter((p): p is Product => Boolean(p));
187
+ }
@@ -0,0 +1,14 @@
1
+ // src/components/lib/templates/ecommerce/index.ts
2
+ // E-commerce template: complete store pages built from library components.
3
+ //
4
+ // import { StoreHomePage } from 'astro-component-kit/templates/ecommerce';
5
+ // <StoreHomePage store={myStore} routes={{ home: '/', shop: '/shop/', product: '/product/', checkout: '/checkout/' }} />
6
+
7
+ export { default as StoreLayout } from './StoreLayout.astro';
8
+ export { default as StoreHomePage } from './StoreHomePage.astro';
9
+ export { default as StoreCategoryPage } from './StoreCategoryPage.astro';
10
+ export { default as StoreProductPage } from './StoreProductPage.astro';
11
+ export { default as StoreCheckoutPage } from './StoreCheckoutPage.astro';
12
+
13
+ export { demoStore, defaultRoutes, productHref, categoryHref, categoryNames, pickProducts } from './data';
14
+ export type { StoreConfig, StoreRoutes } from './data';
@@ -0,0 +1,52 @@
1
+ ---
2
+ /**
3
+ * EditorialBagPage — Full shopping-bag page (CartPageList) with gift note and summary,
4
+ * followed by a "You may also like" ShopProductRail.
5
+ *
6
+ * Usage (src/pages/bag.astro):
7
+ * import { EditorialBagPage } from 'astro-component-kit/templates/ecommerce-editorial';
8
+ * <EditorialBagPage />
9
+ *
10
+ * @param {EditorialStore} store - Catalogue and settings.
11
+ * @param {EditorialRoutes} routes - Page URLs.
12
+ * @param {string} theme - Initial theme (light|dark|auto). Default 'light'.
13
+ * @param {boolean} seedCart - Pre-fill the bag with demo items. Default false.
14
+ * @param {boolean} noindex - Add robots noindex. Default true (bag pages should not be indexed).
15
+ */
16
+ import EditorialLayout from './EditorialLayout.astro';
17
+ import CartPageList from '../../ecommerce/CartPageList.astro';
18
+ import ShopProductRail from '../../sections/ShopProductRail.astro';
19
+ import { formaStore, editorialRoutes, pickEditorial, type EditorialStore, type EditorialRoutes } from './data';
20
+
21
+ interface Props {
22
+ store?: EditorialStore;
23
+ routes?: EditorialRoutes;
24
+ theme?: 'light' | 'dark' | 'auto';
25
+ seedCart?: boolean;
26
+ noindex?: boolean;
27
+ }
28
+
29
+ const { store = formaStore, routes = editorialRoutes, theme = 'light', seedCart = false, noindex = true } = Astro.props;
30
+ const suggestions = pickEditorial(store, ['kiln-mug', 'organic-tee', 'acetate-frames', 'paper-lamp', 'canvas-runner']);
31
+ ---
32
+
33
+ <EditorialLayout title="Your bag" description={`Your bag — ${store.name}`} store={store} routes={routes} currentHref={routes.bag} theme={theme} seedCart={seedCart} noindex={noindex}>
34
+ <div class="forma-wrap bag-page">
35
+ <CartPageList
36
+ cartKey={store.cartKey}
37
+ checkoutHref={routes.checkout}
38
+ continueHref={routes.shop}
39
+ freeShippingThreshold={store.freeShippingThreshold}
40
+ shippingFlat={store.shippingFlat}
41
+ currency={store.currency}
42
+ locale={store.locale}
43
+ />
44
+ </div>
45
+ <div class="forma-wrap section-space">
46
+ <ShopProductRail eyebrow="Before you go" title="You may also *like*" products={suggestions} productBase={routes.product} link={{ label: 'Shop all', href: routes.shop }} id="bag-rail" size="sm" currency={store.currency} locale={store.locale} cartKey={store.cartKey} />
47
+ </div>
48
+ </EditorialLayout>
49
+
50
+ <style>
51
+ .bag-page { padding-top: clamp(2rem, 5vw, 3.5rem); }
52
+ </style>
@@ -0,0 +1,123 @@
1
+ ---
2
+ /**
3
+ * EditorialCheckoutPage — Split-screen checkout in focus mode: CheckoutForm on the paper side,
4
+ * a full-height tinted panel with OrderSummary (promo codes, shipping, total) on the other.
5
+ *
6
+ * Usage (src/pages/checkout.astro):
7
+ * import { EditorialCheckoutPage } from 'astro-component-kit/templates/ecommerce-editorial';
8
+ * <EditorialCheckoutPage />
9
+ *
10
+ * @param {EditorialStore} store - Catalogue and settings.
11
+ * @param {EditorialRoutes} routes - Page URLs.
12
+ * @param {string} theme - Initial theme (light|dark|auto). Default 'light'.
13
+ * @param {boolean} seedCart - Pre-fill the bag with demo items. Default false.
14
+ * @param {boolean} noindex - Add robots noindex. Default true.
15
+ */
16
+ import EditorialLayout from './EditorialLayout.astro';
17
+ import CheckoutForm from '../../ecommerce/CheckoutForm.astro';
18
+ import OrderSummary from '../../ecommerce/OrderSummary.astro';
19
+ import { formaStore, editorialRoutes, type EditorialStore, type EditorialRoutes } from './data';
20
+
21
+ interface Props {
22
+ store?: EditorialStore;
23
+ routes?: EditorialRoutes;
24
+ theme?: 'light' | 'dark' | 'auto';
25
+ seedCart?: boolean;
26
+ noindex?: boolean;
27
+ }
28
+
29
+ const { store = formaStore, routes = editorialRoutes, theme = 'light', seedCart = false, noindex = true } = Astro.props;
30
+ ---
31
+
32
+ <EditorialLayout title="Checkout" description={`Secure checkout — ${store.name}`} store={store} routes={routes} theme={theme} seedCart={seedCart} noindex={noindex} minimal>
33
+ <div class="co-split">
34
+ <div class="co-split__form">
35
+ <div class="co-split__inner">
36
+ <nav class="co-steps" aria-label="Checkout steps">
37
+ <ol>
38
+ <li><a href={routes.bag}>Bag</a></li>
39
+ <li><span aria-current="step">Details &amp; payment</span></li>
40
+ <li><span>Confirmation</span></li>
41
+ </ol>
42
+ </nav>
43
+ <h1 class="co-title">Checkout</h1>
44
+ <CheckoutForm
45
+ id="checkout"
46
+ variant="plain"
47
+ shippingRates={store.shippingRates}
48
+ freeShippingThreshold={store.freeShippingThreshold}
49
+ countries={[
50
+ { label: 'Spain', value: 'ES' },
51
+ { label: 'Portugal', value: 'PT' },
52
+ { label: 'France', value: 'FR' },
53
+ { label: 'Germany', value: 'DE' },
54
+ { label: 'Italy', value: 'IT' },
55
+ { label: 'United Kingdom', value: 'GB' },
56
+ ]}
57
+ cartKey={store.cartKey}
58
+ currency={store.currency}
59
+ locale={store.locale}
60
+ continueHref={routes.home}
61
+ />
62
+ </div>
63
+ </div>
64
+ <div class="co-split__summary">
65
+ <OrderSummary
66
+ title="In your bag"
67
+ variant="plain"
68
+ cartKey={store.cartKey}
69
+ shippingRates={store.shippingRates}
70
+ freeShippingThreshold={store.freeShippingThreshold}
71
+ taxRate={store.taxRate}
72
+ promoCodes={store.promoCodes}
73
+ editHref={routes.bag}
74
+ currency={store.currency}
75
+ locale={store.locale}
76
+ />
77
+ </div>
78
+ </div>
79
+ </EditorialLayout>
80
+
81
+ <script>
82
+ document.addEventListener('ack:order-placed', () => {
83
+ const steps = document.querySelectorAll<HTMLElement>('.co-steps li');
84
+ steps.forEach((li, i) => {
85
+ const el = li.firstElementChild as HTMLElement | null;
86
+ if (!el) return;
87
+ if (i === steps.length - 1) el.setAttribute('aria-current', 'step');
88
+ else el.removeAttribute('aria-current');
89
+ });
90
+ });
91
+ </script>
92
+
93
+ <style>
94
+ .co-split { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); min-height: calc(100vh - var(--shop-header-h)); }
95
+ .co-split__form { padding: clamp(1.5rem, 4vw, 3.5rem) clamp(1rem, 4vw, 4.5rem) clamp(3rem, 6vw, 5rem); }
96
+ .co-split__inner { max-width: 640px; margin-left: auto; }
97
+ .co-split__summary { padding: clamp(1.5rem, 4vw, 3.5rem) clamp(1rem, 4vw, 4rem); background: var(--c-bg-2); border-left: 1px solid var(--c-border); }
98
+ .co-split__summary > :global(.o-summary) { max-width: 460px; position: sticky; top: calc(var(--shop-header-h) + 1.5rem); }
99
+ .co-steps ol { display: flex; flex-wrap: wrap; gap: 0.6rem; margin: 0 0 var(--sp-5); padding: 0; list-style: none; font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--c-text-2); }
100
+ .co-steps li + li::before { content: '→'; margin-right: 0.6rem; opacity: 0.5; }
101
+ .co-steps a { color: inherit; }
102
+ .co-steps [aria-current] { color: var(--c-text-1); font-weight: 700; }
103
+ .co-title { margin: 0 0 var(--sp-6); font-family: var(--font-display); font-size: clamp(2.4rem, 5vw, 3.8rem); font-weight: 400; letter-spacing: -0.04em; line-height: 1; color: var(--c-text-1); }
104
+
105
+ /* Editorial tuning of the shared checkout components */
106
+ .co-split :global(.checkout__section) { padding-bottom: var(--sp-6); border-bottom: 1px solid var(--c-border); }
107
+ .co-split :global(.checkout__section legend) { font-family: var(--font-display); font-size: 1.5rem; font-weight: 400; letter-spacing: -0.02em; }
108
+ .co-split :global(.checkout__num) { background: transparent; border: 1px solid var(--c-text-1); color: var(--c-text-1); font-family: var(--font-sans); }
109
+ .co-split :global(.checkout__rate) { border-radius: var(--r-sm); }
110
+ .co-split :global(.checkout__pay) { border-radius: var(--r-sm); background: var(--c-text-1); color: var(--c-bg); letter-spacing: 0.06em; text-transform: uppercase; font-size: 0.9rem; }
111
+ .co-split :global(.checkout__pay:hover) { background: var(--shop-accent); color: var(--c-on-primary); filter: none; }
112
+ .co-split :global(.checkout__done) { border-radius: var(--r-sm); }
113
+ .co-split :global(.o-summary__title) { font-family: var(--font-display); font-size: 1.6rem; font-weight: 400; }
114
+ .co-split :global(.o-summary__promo input), .co-split :global(.o-summary__promo button) { border-radius: var(--r-sm); }
115
+ .co-split :global(.o-line__media) { border-radius: var(--r-sm); }
116
+
117
+ @media (max-width: 960px) {
118
+ .co-split { grid-template-columns: 1fr; }
119
+ .co-split__summary { order: -1; border-left: 0; border-bottom: 1px solid var(--c-border); }
120
+ .co-split__summary > :global(.o-summary) { position: static; max-width: none; }
121
+ .co-split__inner { margin-left: 0; max-width: none; }
122
+ }
123
+ </style>
@@ -0,0 +1,102 @@
1
+ ---
2
+ /**
3
+ * EditorialHomePage — Editorial store home: magazine hero with ticker, collection mosaic,
4
+ * new-in product rail, shoppable lookbook, values marquee, reviews and newsletter.
5
+ *
6
+ * Usage (src/pages/index.astro):
7
+ * import { EditorialHomePage } from 'astro-component-kit/templates/ecommerce-editorial';
8
+ * <EditorialHomePage />
9
+ *
10
+ * @param {EditorialStore} store - Catalogue and settings. Default: Forma demo store.
11
+ * @param {EditorialRoutes} routes - Page URLs.
12
+ * @param {string} theme - Initial theme (light|dark|auto). Default 'light'.
13
+ * @param {boolean} seedCart - Pre-fill the bag with demo items. Default false.
14
+ * @param {boolean} noindex - Add robots noindex. Default false.
15
+ */
16
+ import EditorialLayout from './EditorialLayout.astro';
17
+ import ShopHeroEditorial from '../../sections/ShopHeroEditorial.astro';
18
+ import ShopCollectionMosaic from '../../sections/ShopCollectionMosaic.astro';
19
+ import ShopProductRail from '../../sections/ShopProductRail.astro';
20
+ import ShopLookbook from '../../sections/ShopLookbook.astro';
21
+ import ShopValuesMarquee from '../../sections/ShopValuesMarquee.astro';
22
+ import ShopReviewsEditorial from '../../sections/ShopReviewsEditorial.astro';
23
+ import ShopNewsletterEditorial from '../../sections/ShopNewsletterEditorial.astro';
24
+ import { formaStore, editorialRoutes, editorialProductHref, editorialCategoryHref, pickEditorial, type EditorialStore, type EditorialRoutes } from './data';
25
+
26
+ interface Props {
27
+ store?: EditorialStore;
28
+ routes?: EditorialRoutes;
29
+ theme?: 'light' | 'dark' | 'auto';
30
+ seedCart?: boolean;
31
+ noindex?: boolean;
32
+ }
33
+
34
+ const { store = formaStore, routes = editorialRoutes, theme = 'light', seedCart = false, noindex = false } = Astro.props;
35
+
36
+ const count = (id: string) => store.products.filter((p) => p.category === id).length;
37
+ const cat = (id: string) => store.categories.find((c) => c.id === id);
38
+ const mosaic = ['clothing', 'objects', 'bags', 'shoes']
39
+ .map((id) => cat(id))
40
+ .filter((c): c is NonNullable<typeof c> => Boolean(c))
41
+ .map((c) => ({ title: c.name, text: c.description, href: editorialCategoryHref(routes, c.id), count: count(c.id), icon: c.icon, hue: c.hue }));
42
+ const coat = store.products.find((p) => p.slug === 'wool-overcoat') ?? store.products[0];
43
+ const fmt = (n: number) => new Intl.NumberFormat(store.locale, { style: 'currency', currency: store.currency, maximumFractionDigits: 0 }).format(n);
44
+ const look = store.look
45
+ .map((l) => {
46
+ const product = store.products.find((p) => p.slug === l.slug);
47
+ return product ? { x: l.x, y: l.y, product, href: editorialProductHref(routes, product.slug) } : null;
48
+ })
49
+ .filter((s): s is NonNullable<typeof s> => Boolean(s));
50
+ const money = { currency: store.currency, locale: store.locale, cartKey: store.cartKey };
51
+ ---
52
+
53
+ <EditorialLayout title={`${store.name} Studio — ${store.tagline.split(',')[0]}`} description={store.tagline} store={store} routes={routes} currentHref={routes.home} theme={theme} seedCart={seedCart} noindex={noindex}>
54
+ <ShopHeroEditorial
55
+ kicker="Autumn / Winter 26"
56
+ issue="N° 04"
57
+ title="Quiet *objects* for everyday rituals"
58
+ text={store.tagline}
59
+ primary={{ label: 'Shop the collection', href: routes.shop }}
60
+ secondary={{ label: 'New in', href: `${routes.shop}?sort=featured` }}
61
+ media={{ icon: coat.icon, hue: coat.hue, caption: `${coat.name}, in ${coat.colors?.[0]?.name ?? 'Rust'} — ${fmt(coat.price)}`, href: editorialProductHref(routes, coat.slug) }}
62
+ />
63
+
64
+ <div class="forma-wrap section-space">
65
+ <ShopCollectionMosaic eyebrow={`${store.categories.length} categories`} title="Shop by *intention*" items={mosaic} />
66
+ </div>
67
+
68
+ <div class="forma-wrap section-space home-tight">
69
+ <ShopProductRail
70
+ eyebrow="Just in"
71
+ title="New this *week*"
72
+ products={pickEditorial(store, store.newIn)}
73
+ productBase={routes.product}
74
+ link={{ label: 'View all', href: routes.shop }}
75
+ id="new-in"
76
+ {...money}
77
+ />
78
+ </div>
79
+
80
+ <div class="forma-wrap section-space">
81
+ <ShopLookbook
82
+ eyebrow="Lookbook · N° 04"
83
+ title="A Sunday *uniform*"
84
+ text="Linen, canvas and stoneware: three pieces that make a slow morning feel deliberate."
85
+ media={{ icon: 'jacket', hue: 26 }}
86
+ spots={look}
87
+ {...money}
88
+ />
89
+ </div>
90
+
91
+ <ShopValuesMarquee values={store.values} />
92
+
93
+ <div class="forma-wrap section-space">
94
+ <ShopReviewsEditorial score={4.9} count={1284} reviews={store.reviews} />
95
+ </div>
96
+
97
+ <ShopNewsletterEditorial variant="accent" />
98
+ </EditorialLayout>
99
+
100
+ <style>
101
+ .home-tight { padding-top: 0; }
102
+ </style>