@cartbase/storefront 0.13.0 → 0.14.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cartbase/storefront",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "Storefront SDK + UI component library for Cartbase stores: typed API client, checkout orchestration, cart drawer, product/catalog components, tracking. Source-shipped TypeScript — add it to transpilePackages.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -40,10 +40,35 @@ export interface StorefrontLocale {
40
40
  }
41
41
 
42
42
  /**
43
- * The two areas that read labels from a PROP rather than a context
44
- * (`store` and `reviews`) are handed their pack by the app:
45
- * `<StoreTemplate labels={locale.store} />`. The other four are served by
46
- * `StorefrontLocaleProvider`. That split is the components' existing
47
- * shape, not a decision of this layer.
43
+ * THE AREAS WHOSE PACK THE APP MUST HAND OVER AS A PROP.
44
+ *
45
+ * Not a style choice and not a gap in this layer: a React SERVER component
46
+ * cannot read a client context, and these areas are rendered on the server.
47
+ * `StorefrontLocaleProvider` therefore reaches the client components and
48
+ * nothing else, and a server-rendered heading stays English however many
49
+ * providers are mounted above it.
50
+ *
51
+ * Corrected 2026-09-13: this used to list `store` and `reviews` only, and
52
+ * Alexander found the consequence on evoo, a Bulgarian store whose product
53
+ * page ended in the English "Related products / You might also want to
54
+ * check out these products". `products` and `order` belong here too, and
55
+ * `ProductTemplate` was not even passing the pack down to its own
56
+ * related-products strip, which made that strip untranslatable without
57
+ * ejecting a file.
58
+ *
59
+ * Hand the pack to each page-level template once and everything inside it
60
+ * follows:
61
+ *
62
+ * <ProductTemplate labels={locale.products} /> // + the related strip
63
+ * <StoreTemplate labels={locale.store} />
64
+ * <SearchTemplate labels={locale.store} />
65
+ * <OrderCompletedTemplate labels={locale.order} />
66
+ * <ReviewWidget labels={locale.reviews} />
67
+ *
68
+ * The cart drawer is the same case for a different reason: it owns the
69
+ * cart's state, so the app mounts it and hands it `locale.cartDrawer`.
48
70
  */
49
- export type PropLabelAreas = Pick<StorefrontLocale, "store" | "reviews">
71
+ export type PropLabelAreas = Pick<
72
+ StorefrontLocale,
73
+ "products" | "store" | "order" | "reviews" | "cartDrawer"
74
+ >
@@ -21,6 +21,7 @@ import { ImageGallery } from "./image-gallery"
21
21
  import { ProductActions, type AddToCartInput } from "./product-actions"
22
22
  import { ProductTabs, type ProductSection } from "./product-tabs"
23
23
  import type { ProductPromise } from "./product-promises"
24
+ import type { ProductLabels } from "./labels"
24
25
  import { RelatedProducts } from "./related-products"
25
26
  import { ProductInfo } from "./product-info"
26
27
  import { ProductActionsWrapper } from "./product-actions-wrapper"
@@ -39,6 +40,17 @@ type ProductTemplateProps = {
39
40
  * the library cannot promise anything on a merchant's behalf.
40
41
  */
41
42
  promises?: ProductPromise[]
43
+ /**
44
+ * The store's product pack. REQUIRED FOR A TRANSLATED PAGE even when a
45
+ * `StorefrontLocaleProvider` is mounted: the related-products strip is a
46
+ * SERVER component and a server component cannot read a client context,
47
+ * so its heading stays English unless the pack arrives as a prop. Until
48
+ * 2026-09-13 this template did not accept one at all and did not pass one
49
+ * down, which made that strip untranslatable without ejecting the file
50
+ * (Alexander found it on evoo: a Bulgarian page ending in "Related
51
+ * products / You might also want to check out these products").
52
+ */
53
+ labels?: Partial<ProductLabels>
42
54
  /** Drop the physical-facts section even for a product that has facts. */
43
55
  hideSpecs?: boolean
44
56
  /** Anything else the store wants in the accordion, appended in order. */
@@ -53,6 +65,7 @@ export function ProductTemplate({
53
65
  onAddToCart,
54
66
  openCart,
55
67
  promises,
68
+ labels,
56
69
  hideSpecs,
57
70
  sections,
58
71
  }: ProductTemplateProps) {
@@ -123,6 +136,7 @@ export function ProductTemplate({
123
136
  client={client}
124
137
  product={product}
125
138
  pricingContext={pricingContext}
139
+ labels={labels}
126
140
  />
127
141
  </Suspense>
128
142
  </div>
@@ -31,7 +31,13 @@ type RelatedProductsProps = {
31
31
  pricingContext?: PricingContextQuery
32
32
  /** 1–24, server default 12. */
33
33
  limit?: number
34
- labels?: Pick<ProductLabels, "relatedProducts" | "relatedProductsDescription">
34
+ /**
35
+ * The store's product pack, or just the two keys this strip uses. It has
36
+ * to arrive as a PROP: this is a server component, so it cannot read
37
+ * `ProductLabelsProvider`, and its heading stays English without one.
38
+ * `ProductTemplate` passes the pack it is given straight through.
39
+ */
40
+ labels?: Partial<ProductLabels>
35
41
  /** Override the default ProductPreview with a store-specific card. */
36
42
  renderProduct?: ComponentType<{ product: StoreProduct }>
37
43
  }