@deneb-ui/ui 2.0.62 → 2.0.63

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/README.md CHANGED
@@ -217,6 +217,12 @@ reactive `SiteDataProvider` catalog, retries `api.catalogUrl`, and renders safe
217
217
  loading, network-error, and not-found states. `usePlatformProductDetail()` is
218
218
  also exported for developers who need complete control of the page markup.
219
219
 
220
+ If the template already has a native `/products/[id]` design, the stable page
221
+ must reuse that renderer through `renderProduct` (or render the same component
222
+ from `usePlatformProductDetail`). The validator rejects a generic stable page
223
+ next to a different native detail layout because newly-created products would
224
+ otherwise look different from products present at build time.
225
+
220
226
  ---
221
227
 
222
228
  ## Data Fetching & Backend Integration Hooks
@@ -61,27 +61,53 @@ function findProduct(products, productId) {
61
61
  };
62
62
  }
63
63
  function normalizeProductForDetail(product, siteData) {
64
- const image = (typeof product.featuredImage === 'string' && product.featuredImage) ||
65
- (typeof product.imageUrl === 'string' && product.imageUrl) ||
66
- (typeof product.image === 'string' && product.image) ||
64
+ const customData = (0, SiteDataProvider_1.isRecord)(product.customData) ? product.customData : {};
65
+ // Public catalog rows keep template-specific variants in customData. Flatten
66
+ // them for custom renderers while preserving explicit top-level fields.
67
+ const mergedProduct = {
68
+ ...customData,
69
+ ...product,
70
+ };
71
+ const name = (typeof mergedProduct.name === 'string' && mergedProduct.name) ||
72
+ (typeof mergedProduct.title === 'string' && mergedProduct.title) ||
73
+ undefined;
74
+ const image = (typeof mergedProduct.featuredImage === 'string' && mergedProduct.featuredImage) ||
75
+ (typeof mergedProduct.imageUrl === 'string' && mergedProduct.imageUrl) ||
76
+ (typeof mergedProduct.image === 'string' && mergedProduct.image) ||
67
77
  undefined;
68
- const images = Array.isArray(product.gallery)
69
- ? product.gallery
70
- : Array.isArray(product.images)
71
- ? product.images
72
- : undefined;
78
+ const images = Array.isArray(mergedProduct.gallery)
79
+ ? mergedProduct.gallery
80
+ : Array.isArray(mergedProduct.images)
81
+ ? mergedProduct.images
82
+ : Array.isArray(mergedProduct.additionalImages)
83
+ ? mergedProduct.additionalImages.filter((value) => typeof value === 'string' && Boolean(value.trim()))
84
+ : undefined;
85
+ const compareAtPrice = mergedProduct.compareAtPrice ?? mergedProduct.originalPrice;
73
86
  const shop = (0, SiteDataProvider_1.isRecord)(siteData.shop) ? siteData.shop : {};
74
87
  const merchant = (0, SiteDataProvider_1.isRecord)(siteData.merchant) ? siteData.merchant : {};
75
- const whatsappNumber = (typeof product.whatsappNumber === 'string' && product.whatsappNumber) ||
88
+ const whatsappNumber = (typeof mergedProduct.whatsappNumber === 'string' && mergedProduct.whatsappNumber) ||
76
89
  (typeof shop.whatsapp === 'string' && shop.whatsapp) ||
77
90
  (typeof shop.whatsappNumber === 'string' && shop.whatsappNumber) ||
78
91
  (typeof merchant.whatsapp === 'string' && merchant.whatsapp) ||
79
92
  undefined;
80
93
  return {
81
- ...product,
82
- ...(image && !product.featuredImage ? { featuredImage: image } : {}),
83
- ...(images && !product.gallery ? { gallery: images } : {}),
84
- ...(whatsappNumber && !product.whatsappNumber ? { whatsappNumber } : {}),
94
+ ...mergedProduct,
95
+ ...(name
96
+ ? {
97
+ name,
98
+ title: typeof mergedProduct.title === 'string' && mergedProduct.title
99
+ ? mergedProduct.title
100
+ : name,
101
+ }
102
+ : {}),
103
+ ...(image
104
+ ? { featuredImage: image, imageUrl: image, image }
105
+ : {}),
106
+ ...(images ? { gallery: images, images } : {}),
107
+ ...(compareAtPrice !== undefined
108
+ ? { compareAtPrice, originalPrice: compareAtPrice }
109
+ : {}),
110
+ ...(whatsappNumber ? { whatsappNumber } : {}),
85
111
  };
86
112
  }
87
113
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deneb-ui/ui",
3
- "version": "2.0.62",
3
+ "version": "2.0.63",
4
4
  "description": "Visual-first React component library for editable commerce storefronts. Built for Next.js and Fivora.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -50,7 +50,7 @@
50
50
  ],
51
51
  "license": "MIT",
52
52
  "dependencies": {
53
- "@deneb-ui/core": "^2.0.62"
53
+ "@deneb-ui/core": "^2.0.63"
54
54
  },
55
55
  "peerDependencies": {
56
56
  "react": "^18.0.0 || ^19.0.0",