@osimart/create-storefront 0.0.0-stage → 1.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.
Files changed (206) hide show
  1. package/README.md +80 -2
  2. package/THEME_DEV_API.md +80 -0
  3. package/app/app.vue +154 -0
  4. package/app/assets/css/osi-controls.css +824 -0
  5. package/app/components/SectionRenderer.vue +46 -0
  6. package/app/components/builder/BuilderOverlay.vue +582 -0
  7. package/app/components/checkout/ExtraFees.vue +329 -0
  8. package/app/components/checkout/PaymentHandoff.vue +388 -0
  9. package/app/components/common/Banner.vue +35 -0
  10. package/app/components/common/ConfirmDeleteModal.vue +117 -0
  11. package/app/components/common/DropdownSelect.vue +432 -0
  12. package/app/components/common/Loader.vue +32 -0
  13. package/app/components/common/OsiField.vue +218 -0
  14. package/app/components/common/PhoneNumInput.vue +434 -0
  15. package/app/composables/UseBodyScrollLock.js +122 -0
  16. package/app/composables/UseThemeGroup.js +575 -0
  17. package/app/composables/useAddToCart.js +87 -0
  18. package/app/composables/useAnalytics.js +15 -0
  19. package/app/composables/useAnnouncements.js +29 -0
  20. package/app/composables/useApiErrorToast.js +104 -0
  21. package/app/composables/useAuth.js +99 -0
  22. package/app/composables/useBanners.js +25 -0
  23. package/app/composables/useBuilderPreview.js +320 -0
  24. package/app/composables/useButtonStyle.js +107 -0
  25. package/app/composables/useCarousel.js +160 -0
  26. package/app/composables/useCart.js +109 -0
  27. package/app/composables/useCheckout.js +76 -0
  28. package/app/composables/useClassificationItems.js +269 -0
  29. package/app/composables/useClassificationPage.js +545 -0
  30. package/app/composables/useClassificationUrl.js +63 -0
  31. package/app/composables/useColorScheme.js +44 -0
  32. package/app/composables/useContactForm.js +53 -0
  33. package/app/composables/useContentTree.js +770 -0
  34. package/app/composables/useDragScroll.js +73 -0
  35. package/app/composables/useFooterSocials.js +107 -0
  36. package/app/composables/useInputStyle.js +45 -0
  37. package/app/composables/useLayoutShell.js +114 -0
  38. package/app/composables/useLazyVideo.js +36 -0
  39. package/app/composables/useMediaTypes.js +66 -0
  40. package/app/composables/useMediaUrl.js +71 -0
  41. package/app/composables/useMenu.js +100 -0
  42. package/app/composables/useNavStyle.js +219 -0
  43. package/app/composables/usePlaceholders.js +294 -0
  44. package/app/composables/usePolicies.js +26 -0
  45. package/app/composables/useProductCardMedia.js +135 -0
  46. package/app/composables/useProductCardStyle.js +132 -0
  47. package/app/composables/useProductDetail.js +982 -0
  48. package/app/composables/useProductGallery.js +166 -0
  49. package/app/composables/useProductItems.js +270 -0
  50. package/app/composables/useProductUrl.js +60 -0
  51. package/app/composables/useProductVariants.js +210 -0
  52. package/app/composables/useQuickShop.js +115 -0
  53. package/app/composables/useRelatedProducts.js +186 -0
  54. package/app/composables/useRenderContext.js +45 -0
  55. package/app/composables/useScopedCss.js +106 -0
  56. package/app/composables/useSearch.js +35 -0
  57. package/app/composables/useSectionData.js +462 -0
  58. package/app/composables/useSectionShell.js +113 -0
  59. package/app/composables/useSidebar.js +69 -0
  60. package/app/composables/useStoreData.js +57 -0
  61. package/app/composables/useStoreInit.js +52 -0
  62. package/app/composables/useStorefront.js +239 -0
  63. package/app/composables/useT.js +21 -0
  64. package/app/composables/useTextStyles.js +84 -0
  65. package/app/composables/useThemeControls.js +34 -0
  66. package/app/composables/useThemeSeo.js +91 -0
  67. package/app/composables/useThemeTokens.js +171 -0
  68. package/app/composables/useWishlist.js +66 -0
  69. package/app/logic/components/AnnouncementBar.js +118 -0
  70. package/app/logic/components/CardGrid.js +125 -0
  71. package/app/logic/components/CardList.js +98 -0
  72. package/app/logic/components/CartDrawer.js +273 -0
  73. package/app/logic/components/CartItem.js +31 -0
  74. package/app/logic/components/ClassificationBento.js +6 -0
  75. package/app/logic/components/ClassificationCard.js +6 -0
  76. package/app/logic/components/ClassificationCarousel.js +115 -0
  77. package/app/logic/components/ClassificationEditorial.js +41 -0
  78. package/app/logic/components/ClassificationFeatured.js +57 -0
  79. package/app/logic/components/ClassificationGrid.js +6 -0
  80. package/app/logic/components/ClassificationNav.js +61 -0
  81. package/app/logic/components/ClassificationPart.js +72 -0
  82. package/app/logic/components/FooterBlock.js +91 -0
  83. package/app/logic/components/FooterSocials.js +60 -0
  84. package/app/logic/components/HeaderDropdownList.js +29 -0
  85. package/app/logic/components/HeaderIcon.js +68 -0
  86. package/app/logic/components/HeaderLogo.js +39 -0
  87. package/app/logic/components/HeaderNav.js +268 -0
  88. package/app/logic/components/MobileMenu.js +280 -0
  89. package/app/logic/components/ProductBuyButtons.js +66 -0
  90. package/app/logic/components/ProductCard.js +160 -0
  91. package/app/logic/components/ProductFilters.js +37 -0
  92. package/app/logic/components/ProductGallery.js +19 -0
  93. package/app/logic/components/ProductInfoBlock.js +411 -0
  94. package/app/logic/components/ProductLightbox.js +12 -0
  95. package/app/logic/components/ProductQuantity.js +31 -0
  96. package/app/logic/components/ProductVariantPicker.js +125 -0
  97. package/app/logic/components/QuickBuy.js +194 -0
  98. package/app/logic/components/SearchOverlay.js +41 -0
  99. package/app/logic/components/SidebarMenuItem.js +39 -0
  100. package/app/logic/components/SiteFooter.js +476 -0
  101. package/app/logic/components/SiteHeader.js +266 -0
  102. package/app/logic/components/WhatsAppButton.js +75 -0
  103. package/app/logic/layouts/default.js +66 -0
  104. package/app/logic/sections/AnnouncementBarSection.js +6 -0
  105. package/app/logic/sections/BlockCarousel.js +103 -0
  106. package/app/logic/sections/ClassificationListSection.js +40 -0
  107. package/app/logic/sections/ContactFormSection.js +294 -0
  108. package/app/logic/sections/ContactInfoSection.js +419 -0
  109. package/app/logic/sections/ContentNode.js +189 -0
  110. package/app/logic/sections/CountdownSection.js +254 -0
  111. package/app/logic/sections/CustomHtmlSection.js +51 -0
  112. package/app/logic/sections/DividerSection.js +31 -0
  113. package/app/logic/sections/FaqSection.js +53 -0
  114. package/app/logic/sections/FeatureListSection.js +6 -0
  115. package/app/logic/sections/FeaturedProductSection.js +40 -0
  116. package/app/logic/sections/FooterSection.js +16 -0
  117. package/app/logic/sections/FooterUtilitiesSection.js +24 -0
  118. package/app/logic/sections/GallerySection.js +232 -0
  119. package/app/logic/sections/HeaderSection.js +24 -0
  120. package/app/logic/sections/HeroSection.js +24 -0
  121. package/app/logic/sections/LogoListSection.js +6 -0
  122. package/app/logic/sections/MainClassificationSection.js +473 -0
  123. package/app/logic/sections/MainProductSection.js +211 -0
  124. package/app/logic/sections/MainSearchSection.js +6 -0
  125. package/app/logic/sections/MapSection.js +92 -0
  126. package/app/logic/sections/MediaContentSection.js +38 -0
  127. package/app/logic/sections/MediaWithTextSection.js +238 -0
  128. package/app/logic/sections/NewsletterSection.js +126 -0
  129. package/app/logic/sections/ProductHighlightSection.js +201 -0
  130. package/app/logic/sections/ProductListSection.js +45 -0
  131. package/app/logic/sections/ProductRecommendationsSection.js +113 -0
  132. package/app/logic/sections/RichTextSection.js +6 -0
  133. package/app/logic/sections/ScrollingTextSection.js +69 -0
  134. package/app/logic/sections/SearchHeaderSection.js +22 -0
  135. package/app/logic/sections/SlideshowSection.js +118 -0
  136. package/app/logic/sections/SpacerSection.js +37 -0
  137. package/app/logic/sections/SplitShowcaseSection.js +6 -0
  138. package/app/logic/sections/TestimonialListSection.js +6 -0
  139. package/app/logic/sections/VideoSection.js +235 -0
  140. package/app/pages/[category]/[product].vue +196 -0
  141. package/app/pages/__builder-preview.vue +38 -0
  142. package/app/pages/categories/[slug].vue +208 -0
  143. package/app/pages/checkout.vue +1972 -0
  144. package/app/pages/forgot-password.vue +115 -0
  145. package/app/pages/index.vue +64 -0
  146. package/app/pages/login.vue +585 -0
  147. package/app/pages/order-detail.vue +442 -0
  148. package/app/pages/pages/[handle].vue +58 -0
  149. package/app/pages/privacy-policy.vue +46 -0
  150. package/app/pages/resetpassword.vue +138 -0
  151. package/app/pages/resetverificationcode.vue +163 -0
  152. package/app/pages/result.vue +203 -0
  153. package/app/pages/return-policy.vue +50 -0
  154. package/app/pages/search.vue +100 -0
  155. package/app/pages/shipping-policy.vue +46 -0
  156. package/app/pages/user-profile/components/AddAddressModal.vue +452 -0
  157. package/app/pages/user-profile/components/Whishlist.vue +137 -0
  158. package/app/pages/user-profile/components/left-bar.vue +233 -0
  159. package/app/pages/user-profile/components/orders.vue +162 -0
  160. package/app/pages/user-profile/components/profile-details.vue +566 -0
  161. package/app/pages/user-profile/components/settings.vue +194 -0
  162. package/app/pages/user-profile/index.vue +252 -0
  163. package/app/pages/verificationcode.vue +188 -0
  164. package/app/plugins/analytics.client.js +99 -0
  165. package/app/plugins/geo.ts +24 -0
  166. package/app/plugins/reveal.client.js +53 -0
  167. package/app/plugins/toast.js +10 -0
  168. package/app/plugins/vue-query.ts +5 -0
  169. package/app/services/ApiServices.js +74 -0
  170. package/app/services/AuthBus.js +162 -0
  171. package/app/services/Authentication/AuthenticationService.js +133 -0
  172. package/app/services/Authentication/TokenService.js +62 -0
  173. package/app/services/CartServices.js +91 -0
  174. package/app/services/CartToken.js +26 -0
  175. package/app/services/CategoryServices.js +54 -0
  176. package/app/services/CheckoutServices.js +113 -0
  177. package/app/services/HomeServices.js +133 -0
  178. package/app/services/NewsletterServices.js +29 -0
  179. package/app/services/PaymentServices.js +71 -0
  180. package/app/services/PoliciesServices.js +16 -0
  181. package/app/services/ProductServices.js +79 -0
  182. package/app/services/SearchServices.js +18 -0
  183. package/app/services/UserServices.js +105 -0
  184. package/app/services/UtilsServices.js +46 -0
  185. package/app/services/WishlistServices.js +51 -0
  186. package/app/services/storefront.service.js +57 -0
  187. package/app/stores/userStore.js +13 -0
  188. package/app/theme/categoryTree.js +68 -0
  189. package/app/theme/controls.js +88 -0
  190. package/app/theme/registry.js +56 -0
  191. package/app/utils/analytics.js +864 -0
  192. package/app/utils/device.js +50 -0
  193. package/app/utils/eventBus.js +24 -0
  194. package/app/utils/icon-presets.js +24 -0
  195. package/app/utils/productOffers.js +118 -0
  196. package/app/utils/requestCache.js +36 -0
  197. package/app/utils/scrollToError.js +59 -0
  198. package/app/utils/toPlainError.js +30 -0
  199. package/bin/osimart-theme.mjs +259 -0
  200. package/nuxt/osi-sections.ts +56 -0
  201. package/nuxt.config.ts +60 -0
  202. package/package.json +43 -3
  203. package/public/css/input.css +29 -0
  204. package/public/css/output.css +2716 -0
  205. package/public/favicon-32x32.png +0 -0
  206. package/public/robots.txt +2 -0
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Product card appearance.
3
+ *
4
+ * Two rules behind the shape of this:
5
+ *
6
+ * 1. **Theme settings first, section override second.** A card that looks one
7
+ * way in the homepage rail and another on the category page is a bug, not a
8
+ * feature — the merchant sets it once for the store. The per-section
9
+ * override exists for genuine exceptions (a compact upsell rail), and it's
10
+ * a partial: only the keys it sets win.
11
+ *
12
+ * 2. **Everything ships as CSS custom properties, not classes.** One set of
13
+ * markup, positions driven by variables, so adding a setting doesn't mean
14
+ * another branch in the template. The three genuinely structural choices
15
+ * (where the text sits, where the CTA sits, where the heart sits) are the
16
+ * only ones that also produce a class.
17
+ *
18
+ * What this deliberately does NOT do is arbitrary reordering — "price above the
19
+ * name", "swatches between them". That needs card content to become an ordered
20
+ * list of blocks, which is a much bigger surface than a settings group. The
21
+ * ordering merchants actually ask for is a preset, not a design tool.
22
+ */
23
+
24
+ const RATIOS = {
25
+ PORTRAIT: "3 / 4",
26
+ SQUARE: "1 / 1",
27
+ LANDSCAPE: "4 / 3",
28
+ NATURAL: "auto",
29
+ };
30
+
31
+ const ALIGN = { START: "start", CENTER: "center", END: "end" };
32
+
33
+ export function useProductCardStyle(override) {
34
+ const theme = useThemeGroup("PRODUCT_CARD");
35
+
36
+ /** Only keys the override actually sets win — a partial, not a replacement. */
37
+ const settings = computed(() => {
38
+ const base = theme.value;
39
+ const patch = toValue(override) ?? {};
40
+ const merged = { ...base };
41
+
42
+ for (const [key, value] of Object.entries(patch)) {
43
+ if (value !== undefined && value !== null && value !== "") merged[key] = value;
44
+ }
45
+ return merged;
46
+ });
47
+
48
+ const textPosition = computed(() => settings.value.CARD_TEXT_POSITION);
49
+ const ctaStyle = computed(() => settings.value.CARD_CTA_STYLE);
50
+ const wishlistPosition = computed(() => settings.value.CARD_WISHLIST_POSITION);
51
+
52
+ const isOverlayText = computed(() => textPosition.value.startsWith("OVERLAY"));
53
+
54
+ const cardStyle = computed(() => {
55
+ const s = settings.value;
56
+ const style = {
57
+ "--osi-card-ratio": RATIOS[s.CARD_IMAGE_RATIO] ?? RATIOS.PORTRAIT,
58
+ "--osi-card-fit": s.CARD_IMAGE_FIT === "CONTAIN" ? "contain" : "cover",
59
+ "--osi-card-align": ALIGN[s.CARD_TEXT_ALIGN] ?? "start",
60
+ "--osi-card-gap": `${s.CARD_CONTENT_GAP}px`,
61
+ "--osi-card-pad": `${s.CARD_CONTENT_PADDING}px`,
62
+ "--osi-card-radius": `${s.CARD_BORDER_RADIUS}px`,
63
+ "--osi-card-name-size": `${s.CARD_NAME_SIZE}px`,
64
+ "--osi-card-price-size": `${s.CARD_PRICE_SIZE}px`,
65
+ // Overlay text needs a scrim or it's unreadable over a light photo.
66
+ "--osi-card-scrim": isOverlayText.value ? s.CARD_OVERLAY_SCRIM : "transparent",
67
+ };
68
+
69
+ if (s.CARD_BACKGROUND) style["--osi-card-bg"] = s.CARD_BACKGROUND;
70
+ if (s.CARD_TEXT_COLOR) style["--osi-card-text"] = s.CARD_TEXT_COLOR;
71
+
72
+ // Badges (CARD_BADGE_* / CARD_SALE_BADGE_* / CARD_SOLD_OUT_BADGE_*): only what's set.
73
+ const has = (v) => v !== undefined && v !== null && v !== "";
74
+ const px = (v) => (has(v) && Number.isFinite(Number(v)) ? `${Number(v)}px` : undefined);
75
+ const badge = {
76
+ "--osi-badge-bg": s.CARD_BADGE_BG,
77
+ "--osi-badge-color": s.CARD_BADGE_TEXT_COLOR,
78
+ "--osi-badge-border": s.CARD_BADGE_BORDER_COLOR,
79
+ "--osi-badge-bw": px(s.CARD_BADGE_BORDER_WIDTH),
80
+ "--osi-badge-r": px(s.CARD_BADGE_RADIUS),
81
+ "--osi-badge-fs": px(s.CARD_BADGE_FONT_SIZE),
82
+ "--osi-badge-tt": has(s.CARD_BADGE_CASE)
83
+ ? (String(s.CARD_BADGE_CASE).toUpperCase() === "NONE" ? "none" : "uppercase")
84
+ : undefined,
85
+ "--osi-badge-sale-bg": s.CARD_SALE_BADGE_BG,
86
+ "--osi-badge-sale-color": s.CARD_SALE_BADGE_TEXT_COLOR,
87
+ "--osi-badge-sale-border": s.CARD_SALE_BADGE_BORDER_COLOR,
88
+ "--osi-badge-out-bg": s.CARD_SOLD_OUT_BADGE_BG,
89
+ "--osi-badge-out-color": s.CARD_SOLD_OUT_BADGE_TEXT_COLOR,
90
+ "--osi-badge-out-border": s.CARD_SOLD_OUT_BADGE_BORDER_COLOR,
91
+ };
92
+ for (const [key, value] of Object.entries(badge)) if (has(value)) style[key] = value;
93
+
94
+ return style;
95
+ });
96
+
97
+ const cardClasses = computed(() => [
98
+ `osi-card--text-${textPosition.value.toLowerCase().replace(/_/g, "-")}`,
99
+ `osi-card--cta-${ctaStyle.value.toLowerCase().replace(/_/g, "-")}`,
100
+ `osi-card--badge-${settings.value.CARD_BADGE_POSITION.toLowerCase().replace(/_/g, "-")}`,
101
+ { "osi-card--cta-block": settings.value.CARD_CTA_FULL_WIDTH },
102
+ ]);
103
+
104
+ // Injected once per distinct stylesheet, not once per card: the fixed key
105
+ // dedupes in useHead, so a 24-product grid still emits one <style>.
106
+ const customCss = useScopedCss(
107
+ () => settings.value.CARD_CUSTOM_CSS,
108
+ "[data-osi-card]",
109
+ "osi-product-card-css"
110
+ );
111
+
112
+ return {
113
+ settings,
114
+ cardStyle,
115
+ cardClasses,
116
+ textPosition,
117
+ ctaStyle,
118
+ wishlistPosition,
119
+ isOverlayText,
120
+ customCss,
121
+
122
+ // Convenience flags the template reads directly.
123
+ showWishlist: computed(() => wishlistPosition.value !== "NONE"),
124
+ wishlistOnMedia: computed(() => wishlistPosition.value.startsWith("TOP_")),
125
+ wishlistWithTitle: computed(() => wishlistPosition.value === "WITH_TITLE"),
126
+ showCta: computed(() => ctaStyle.value !== "NONE"),
127
+ ctaOnMedia: computed(() => ctaStyle.value === "HOVER_OVER_IMAGE"),
128
+ showSwatches: computed(() => !!settings.value.CARD_SHOW_SWATCHES),
129
+ showQuickShop: computed(() => !!settings.value.CARD_SHOW_QUICK_SHOP),
130
+ showSecondImage: computed(() => !!settings.value.CARD_SHOW_SECOND_IMAGE_ON_HOVER),
131
+ };
132
+ }