@deneb-ui/ui 2.0.127 → 2.0.128
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.
|
@@ -36,6 +36,12 @@ export interface ProductItem {
|
|
|
36
36
|
reviewsCount?: number | string;
|
|
37
37
|
isNew?: boolean;
|
|
38
38
|
isBestSeller?: boolean;
|
|
39
|
+
isAvailable?: boolean;
|
|
40
|
+
inStock?: boolean;
|
|
41
|
+
available?: boolean;
|
|
42
|
+
isActive?: boolean;
|
|
43
|
+
active?: boolean;
|
|
44
|
+
status?: string;
|
|
39
45
|
whatsappNumber?: string;
|
|
40
46
|
whatsappButtonText?: string;
|
|
41
47
|
addToCartButtonText?: string;
|
|
@@ -451,7 +451,7 @@ function EditableProductCard({ itemPath, product: productProp, item: itemProp, c
|
|
|
451
451
|
fontSize: '0.8rem',
|
|
452
452
|
fontWeight: 500,
|
|
453
453
|
color: 'var(--muted-text, #64748b)',
|
|
454
|
-
} })) : null] })) : !effectiveShowPrice ? ((0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', alignItems: 'center', gap: '0.5rem' }, children: (0, jsx_runtime_1.jsx)("span", { style: {
|
|
454
|
+
} })) : null] })) : (!effectiveShowPrice || !hasPrice) ? ((0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', alignItems: 'center', gap: '0.5rem' }, children: (0, jsx_runtime_1.jsx)("span", { style: {
|
|
455
455
|
display: 'inline-flex',
|
|
456
456
|
alignItems: 'center',
|
|
457
457
|
padding: '4px 10px',
|
|
@@ -4,8 +4,16 @@ export interface ServiceItem {
|
|
|
4
4
|
name?: string;
|
|
5
5
|
title?: string;
|
|
6
6
|
price?: string | number;
|
|
7
|
+
cost?: string | number;
|
|
8
|
+
amount?: string | number;
|
|
9
|
+
rate?: string | number;
|
|
10
|
+
serviceFee?: string | number;
|
|
11
|
+
servicePrice?: string | number;
|
|
12
|
+
compareAtPrice?: string | number;
|
|
13
|
+
originalPrice?: string | number;
|
|
7
14
|
priceLabel?: string;
|
|
8
15
|
showPrice?: boolean;
|
|
16
|
+
currency?: string;
|
|
9
17
|
customData?: Record<string, unknown>;
|
|
10
18
|
description?: string;
|
|
11
19
|
imageUrl?: string;
|
|
@@ -14,6 +22,12 @@ export interface ServiceItem {
|
|
|
14
22
|
images?: string[];
|
|
15
23
|
additionalImages?: string[];
|
|
16
24
|
features?: unknown[];
|
|
25
|
+
badge?: string;
|
|
26
|
+
tag?: string;
|
|
27
|
+
isActive?: boolean;
|
|
28
|
+
active?: boolean;
|
|
29
|
+
isAvailable?: boolean;
|
|
30
|
+
available?: boolean;
|
|
17
31
|
[key: string]: unknown;
|
|
18
32
|
}
|
|
19
33
|
export interface EditableServiceCardProps extends React.HTMLAttributes<HTMLElement> {
|
|
@@ -38,9 +52,17 @@ export interface EditableServiceCardProps extends React.HTMLAttributes<HTMLEleme
|
|
|
38
52
|
*/
|
|
39
53
|
align?: 'left' | 'center' | 'right';
|
|
40
54
|
showPrice?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Whether to show active/inactive status badge (default: true).
|
|
57
|
+
*/
|
|
58
|
+
showStatusBadge?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Currency code override (e.g. "LKR", "USD"). If omitted, auto-resolves from live shop profile.
|
|
61
|
+
*/
|
|
62
|
+
currency?: string;
|
|
41
63
|
}
|
|
42
64
|
/**
|
|
43
65
|
* EditableServiceCard standardizes service presentation across Home and Services pages.
|
|
44
66
|
* Supports service name, description, image, and repeatable features checklist.
|
|
45
67
|
*/
|
|
46
|
-
export declare function EditableServiceCard({ itemPath, service, imageFallback, as: Component, align, showPrice, className, style, children, ...props }: EditableServiceCardProps): React.JSX.Element;
|
|
68
|
+
export declare function EditableServiceCard({ itemPath, service, imageFallback, as: Component, align, showPrice, showStatusBadge, currency: currencyOverride, className, style, children, ...props }: EditableServiceCardProps): React.JSX.Element;
|
|
@@ -5,11 +5,17 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
5
5
|
const EditableText_1 = require("./EditableText");
|
|
6
6
|
const EditableImage_1 = require("./EditableImage");
|
|
7
7
|
const catalogMedia_1 = require("./utils/catalogMedia");
|
|
8
|
+
const SiteDataProvider_1 = require("./SiteDataProvider");
|
|
8
9
|
/**
|
|
9
10
|
* EditableServiceCard standardizes service presentation across Home and Services pages.
|
|
10
11
|
* Supports service name, description, image, and repeatable features checklist.
|
|
11
12
|
*/
|
|
12
|
-
function EditableServiceCard({ itemPath, service, imageFallback = '/placeholder.svg', as: Component = 'article', align = 'left', showPrice = true, className = '', style, children, ...props }) {
|
|
13
|
+
function EditableServiceCard({ itemPath, service, imageFallback = '/placeholder.svg', as: Component = 'article', align = 'left', showPrice = true, showStatusBadge = true, currency: currencyOverride, className = '', style, children, ...props }) {
|
|
14
|
+
const isServiceActive = service?.isActive !== false &&
|
|
15
|
+
service?.active !== false &&
|
|
16
|
+
service?.isAvailable !== false &&
|
|
17
|
+
service?.available !== false;
|
|
18
|
+
const badgeCandidate = service?.badge || service?.tag;
|
|
13
19
|
const name = String(service?.name || service?.title || '');
|
|
14
20
|
const description = String(service?.description || '');
|
|
15
21
|
const itemShowPrice = service.showPrice !== undefined
|
|
@@ -22,38 +28,95 @@ function EditableServiceCard({ itemPath, service, imageFallback = '/placeholder.
|
|
|
22
28
|
const hasRawPrice = rawPriceCandidate !== undefined && rawPriceCandidate !== null && String(rawPriceCandidate).trim() !== '';
|
|
23
29
|
const priceLabel = service?.priceLabel ? String(service.priceLabel) : '';
|
|
24
30
|
const hasPrice = effectiveShowPrice && (hasRawPrice || Boolean(priceLabel));
|
|
31
|
+
const liveCurrency = (0, SiteDataProvider_1.useCurrency)();
|
|
32
|
+
const currency = currencyOverride || service?.currency || liveCurrency;
|
|
25
33
|
const formattedPrice = hasRawPrice
|
|
26
34
|
? typeof rawPriceCandidate === 'number'
|
|
27
|
-
? '
|
|
28
|
-
: String(rawPriceCandidate).includes(
|
|
35
|
+
? currency + ' ' + rawPriceCandidate.toLocaleString()
|
|
36
|
+
: String(rawPriceCandidate).match(/^[A-Z]{3}\s/) || String(rawPriceCandidate).includes(currency)
|
|
29
37
|
? String(rawPriceCandidate)
|
|
30
|
-
: '
|
|
38
|
+
: currency + ' ' + String(rawPriceCandidate)
|
|
39
|
+
: '';
|
|
40
|
+
const rawCompareCandidate = service?.compareAtPrice || service?.originalPrice;
|
|
41
|
+
const hasComparePrice = effectiveShowPrice &&
|
|
42
|
+
rawCompareCandidate !== undefined &&
|
|
43
|
+
rawCompareCandidate !== null &&
|
|
44
|
+
String(rawCompareCandidate).trim() !== '' &&
|
|
45
|
+
Number(rawCompareCandidate) > Number(rawPriceCandidate);
|
|
46
|
+
const formattedComparePrice = hasComparePrice
|
|
47
|
+
? typeof rawCompareCandidate === 'number'
|
|
48
|
+
? currency + ' ' + rawCompareCandidate.toLocaleString()
|
|
49
|
+
: String(rawCompareCandidate).match(/^[A-Z]{3}\s/) || String(rawCompareCandidate).includes(currency)
|
|
50
|
+
? String(rawCompareCandidate)
|
|
51
|
+
: currency + ' ' + String(rawCompareCandidate)
|
|
31
52
|
: '';
|
|
32
53
|
const serviceImages = (0, catalogMedia_1.resolveCatalogImages)(service);
|
|
33
54
|
const imageUrl = serviceImages[0] || '';
|
|
34
55
|
const features = Array.isArray(service?.features) ? service.features : [];
|
|
35
56
|
const mergedStyle = {
|
|
36
57
|
textAlign: align,
|
|
58
|
+
opacity: !isServiceActive ? 0.72 : 1,
|
|
37
59
|
...style,
|
|
38
60
|
};
|
|
39
|
-
|
|
61
|
+
const badgeElement = (badgeCandidate || (!isServiceActive && showStatusBadge)) ? ((0, jsx_runtime_1.jsx)("div", { className: "service-card-badge-wrap", style: {
|
|
62
|
+
position: 'absolute',
|
|
63
|
+
top: '0.75rem',
|
|
64
|
+
left: '0.75rem',
|
|
65
|
+
zIndex: 3,
|
|
66
|
+
display: 'flex',
|
|
67
|
+
gap: '0.375rem',
|
|
68
|
+
pointerEvents: 'none',
|
|
69
|
+
}, children: !isServiceActive && showStatusBadge ? ((0, jsx_runtime_1.jsxs)("span", { className: "service-card-status-badge inactive", style: {
|
|
70
|
+
display: 'inline-flex',
|
|
71
|
+
alignItems: 'center',
|
|
72
|
+
gap: '0.25rem',
|
|
73
|
+
padding: '0.25rem 0.625rem',
|
|
74
|
+
borderRadius: '9999px',
|
|
75
|
+
fontSize: '0.6875rem',
|
|
76
|
+
fontWeight: 700,
|
|
77
|
+
textTransform: 'uppercase',
|
|
78
|
+
letterSpacing: '0.05em',
|
|
79
|
+
backgroundColor: 'rgba(239, 68, 68, 0.95)',
|
|
80
|
+
color: '#ffffff',
|
|
81
|
+
boxShadow: '0 2px 4px rgba(0,0,0,0.15)',
|
|
82
|
+
}, children: [(0, jsx_runtime_1.jsx)("span", { style: { width: 6, height: 6, borderRadius: '50%', backgroundColor: 'currentColor' } }), "Unavailable"] })) : badgeCandidate ? ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.badge`, "data-preview-field-path": `${itemPath}.badge`, defaultValue: String(badgeCandidate), className: "service-card-badge", style: {
|
|
83
|
+
display: 'inline-flex',
|
|
84
|
+
alignItems: 'center',
|
|
85
|
+
padding: '0.25rem 0.625rem',
|
|
86
|
+
borderRadius: '9999px',
|
|
87
|
+
fontSize: '0.6875rem',
|
|
88
|
+
fontWeight: 700,
|
|
89
|
+
textTransform: 'uppercase',
|
|
90
|
+
letterSpacing: '0.05em',
|
|
91
|
+
backgroundColor: 'var(--brand-color, #2563eb)',
|
|
92
|
+
color: '#ffffff',
|
|
93
|
+
boxShadow: '0 2px 4px rgba(0,0,0,0.15)',
|
|
94
|
+
pointerEvents: 'auto',
|
|
95
|
+
} })) : null })) : null;
|
|
96
|
+
return ((0, jsx_runtime_1.jsxs)(Component, { "data-preview-item-path": itemPath, className: `editable-service-card ${!isServiceActive ? 'is-inactive is-unavailable' : ''} ${className}`.trim(), style: mergedStyle, ...props, children: [(imageUrl || service?.imageUrl !== undefined || service?.image !== undefined) ? ((0, jsx_runtime_1.jsxs)("div", { className: "service-card-image-wrap", style: { position: 'relative' }, children: [badgeElement, (0, jsx_runtime_1.jsx)(EditableImage_1.EditableImage, { id: `${itemPath}.imageUrl`, "data-preview-field-path": `${itemPath}.imageUrl`, src: imageUrl, fallbackSrc: imageFallback, alt: name, className: "service-card-image" })] })) : badgeElement ? ((0, jsx_runtime_1.jsx)("div", { style: { position: 'relative', width: '100%', height: '1.75rem', marginBottom: '0.5rem' }, children: badgeElement })) : null, (0, jsx_runtime_1.jsxs)("div", { className: "service-card-body", children: [(0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "h2", id: `${itemPath}.name`, "data-preview-field-path": `${itemPath}.name`, defaultValue: name, className: "service-card-title" }), (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "p", id: `${itemPath}.description`, "data-preview-field-path": `${itemPath}.description`, defaultValue: description, className: "service-card-description" }), hasPrice ? ((0, jsx_runtime_1.jsxs)("div", { className: "service-card-price-wrap", style: { margin: '0.5rem 0', display: 'flex', alignItems: 'baseline', gap: '0.5rem', flexWrap: 'wrap' }, children: [hasRawPrice && ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.price`, "data-preview-field-path": `${itemPath}.price`, defaultValue: formattedPrice, className: "service-card-price", style: {
|
|
40
97
|
fontSize: '1.125rem',
|
|
41
98
|
fontWeight: 700,
|
|
42
99
|
color: 'var(--brand-color, #2563eb)',
|
|
43
|
-
} })),
|
|
100
|
+
} })), hasComparePrice && ((0, jsx_runtime_1.jsx)("span", { className: "service-card-compare-price", style: {
|
|
101
|
+
fontSize: '0.875rem',
|
|
102
|
+
fontWeight: 500,
|
|
103
|
+
color: 'var(--muted-text, #94a3b8)',
|
|
104
|
+
textDecoration: 'line-through',
|
|
105
|
+
}, children: formattedComparePrice })), priceLabel && ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.priceLabel`, "data-preview-field-path": `${itemPath}.priceLabel`, defaultValue: priceLabel, className: "service-card-price-label", style: {
|
|
44
106
|
fontSize: '0.8125rem',
|
|
45
107
|
fontWeight: 500,
|
|
46
108
|
color: 'var(--muted-text, #94a3b8)',
|
|
47
|
-
} }))] })) : !effectiveShowPrice ? ((0, jsx_runtime_1.jsx)("div", { className: "service-card-price-wrap", style: { margin: '0.5rem 0' }, children: (0, jsx_runtime_1.jsx)("span", { style: {
|
|
109
|
+
} }))] })) : (!effectiveShowPrice || (!hasRawPrice && !priceLabel)) ? ((0, jsx_runtime_1.jsx)("div", { className: "service-card-price-wrap", style: { margin: '0.5rem 0' }, children: (0, jsx_runtime_1.jsx)("span", { style: {
|
|
48
110
|
display: 'inline-flex',
|
|
49
111
|
alignItems: 'center',
|
|
50
|
-
padding: '
|
|
51
|
-
borderRadius: '
|
|
52
|
-
fontSize: '0.
|
|
112
|
+
padding: '4px 10px',
|
|
113
|
+
borderRadius: '8px',
|
|
114
|
+
fontSize: '0.8125rem',
|
|
53
115
|
fontWeight: 600,
|
|
54
116
|
backgroundColor: 'rgba(255, 255, 255, 0.08)',
|
|
55
117
|
color: 'var(--muted-text, #94a3b8)',
|
|
56
118
|
border: '1px solid rgba(255, 255, 255, 0.12)',
|
|
119
|
+
letterSpacing: '0.01em',
|
|
57
120
|
}, children: "Quote on Request" }) })) : null, (features.length > 0 || Array.isArray(service?.features)) && ((0, jsx_runtime_1.jsx)("ul", { "data-preview-list-path": `${itemPath}.features`, className: "service-card-features", children: features.map((feature, featureIndex) => {
|
|
58
121
|
const featureText = typeof feature === 'string'
|
|
59
122
|
? feature
|
|
@@ -11,7 +11,6 @@ export declare const LEGACY_PREVIEW_READY_MESSAGE: string;
|
|
|
11
11
|
export declare const DENEB_PREVIEW_FOCUS_MESSAGE = "DENEB_PREVIEW_FOCUS_PAGE";
|
|
12
12
|
export declare const PREVIEW_FOCUS_MESSAGE = "FIVORA_PREVIEW_FOCUS_PAGE";
|
|
13
13
|
export declare const LEGACY_PREVIEW_FOCUS_MESSAGE: string;
|
|
14
|
-
export declare const DENEB_REFRESH_LIVE_CATALOG_EVENT = "deneb:refresh-live-catalog";
|
|
15
14
|
export declare const PREVIEW_FIELD_ATTRIBUTE = "data-preview-field-path";
|
|
16
15
|
export { STYLE_PATCH_MESSAGE, DENEB_STYLE_PATCH_MESSAGE } from '@deneb-ui/core';
|
|
17
16
|
export type GenericRecord = Record<string, any>;
|
|
@@ -113,14 +112,24 @@ export declare function formatWeeklyHoursToString(value: unknown): string;
|
|
|
113
112
|
export declare function normalizeProductItem(p: unknown): ProductItem;
|
|
114
113
|
/**
|
|
115
114
|
* Universal Service Normalizer
|
|
115
|
+
* Ensures every service object has both canonical and alias keys simultaneously populated
|
|
116
|
+
* with clean numbers and resolved image URLs, matching the product normalizer's robustness.
|
|
116
117
|
*/
|
|
117
118
|
export declare function normalizeServiceItem(s: unknown): ServiceItem;
|
|
118
|
-
export
|
|
119
|
+
export interface UseProductsOptions {
|
|
120
|
+
inStockOnly?: boolean;
|
|
121
|
+
activeOnly?: boolean;
|
|
122
|
+
}
|
|
123
|
+
export declare function useProducts(fallback?: ProductItem[], options?: UseProductsOptions): ProductItem[];
|
|
124
|
+
export interface UseServicesOptions {
|
|
125
|
+
activeOnly?: boolean;
|
|
126
|
+
}
|
|
119
127
|
/**
|
|
120
128
|
* Hook to retrieve services cleanly from SiteData, supporting both
|
|
121
129
|
* top-level content.services and nested content.home.services.
|
|
130
|
+
* Supports optional { activeOnly: true } filtering to mirror product availability.
|
|
122
131
|
*/
|
|
123
|
-
export declare function useServices(fallback?: ServiceItem[]): ServiceItem[];
|
|
132
|
+
export declare function useServices(fallback?: ServiceItem[], options?: UseServicesOptions): ServiceItem[];
|
|
124
133
|
/**
|
|
125
134
|
* Hook to access official Fivora backend API endpoints (catalogUrl, contactUrl, analyticsUrl).
|
|
126
135
|
*/
|
|
@@ -179,3 +188,31 @@ export interface SyncedBranding {
|
|
|
179
188
|
* Hierarchy: Visual Editor Edits (content.common) -> Live Merchant Shop Profile -> Template Fallback.
|
|
180
189
|
*/
|
|
181
190
|
export declare function useSyncedBranding(fallback?: Partial<SyncedBranding>): SyncedBranding;
|
|
191
|
+
/**
|
|
192
|
+
* Hook to retrieve the live store currency code (e.g. "LKR", "USD", "EUR").
|
|
193
|
+
* Auto-hydrates from the merchant portal's shop profile.
|
|
194
|
+
* Hierarchy: shop.currency → content.common.currency → merchant.currency → fallback.
|
|
195
|
+
*/
|
|
196
|
+
export declare function useCurrency(fallback?: string): string;
|
|
197
|
+
export interface SocialLinksMap {
|
|
198
|
+
facebook: string;
|
|
199
|
+
instagram: string;
|
|
200
|
+
tiktok: string;
|
|
201
|
+
youtube: string;
|
|
202
|
+
linkedin: string;
|
|
203
|
+
twitter: string;
|
|
204
|
+
website: string;
|
|
205
|
+
[key: string]: string;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Hook to retrieve the live social links map from the merchant profile.
|
|
209
|
+
* Auto-hydrates from the shop owner's Fivora Portal social configuration.
|
|
210
|
+
* Returns a map like { facebook: "https://...", instagram: "https://...", ... }.
|
|
211
|
+
*/
|
|
212
|
+
export declare function useSocial(fallback?: Partial<SocialLinksMap>): SocialLinksMap;
|
|
213
|
+
/**
|
|
214
|
+
* Hook to retrieve the live shop front / cover / banner image URL.
|
|
215
|
+
* Auto-hydrates from the merchant portal's shop profile.
|
|
216
|
+
* Hierarchy: shop.coverImage → shop.shopImage → shop.bannerImage → shop.heroImage → content.common.shopImage → fallback.
|
|
217
|
+
*/
|
|
218
|
+
export declare function useShopImage(fallback?: string): string;
|
package/dist/SiteDataProvider.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
'use client';
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.DUMMY_PREVIEW_SHOP_NAME = exports.DUMMY_PREVIEW_ADDRESS = exports.DUMMY_PREVIEW_EMAIL = exports.DUMMY_PREVIEW_WHATSAPP = exports.DUMMY_PREVIEW_PHONE = exports.DenebDataContext = exports.useDenebData = exports.DenebDataProvider = exports.resolveAsset = exports.withBasePath = exports.SiteDataContext = exports.DENEB_STYLE_PATCH_MESSAGE = exports.STYLE_PATCH_MESSAGE = exports.PREVIEW_FIELD_ATTRIBUTE = exports.
|
|
4
|
+
exports.DUMMY_PREVIEW_SHOP_NAME = exports.DUMMY_PREVIEW_ADDRESS = exports.DUMMY_PREVIEW_EMAIL = exports.DUMMY_PREVIEW_WHATSAPP = exports.DUMMY_PREVIEW_PHONE = exports.DenebDataContext = exports.useDenebData = exports.DenebDataProvider = exports.resolveAsset = exports.withBasePath = exports.SiteDataContext = exports.DENEB_STYLE_PATCH_MESSAGE = exports.STYLE_PATCH_MESSAGE = exports.PREVIEW_FIELD_ATTRIBUTE = exports.LEGACY_PREVIEW_FOCUS_MESSAGE = exports.PREVIEW_FOCUS_MESSAGE = exports.DENEB_PREVIEW_FOCUS_MESSAGE = exports.LEGACY_PREVIEW_READY_MESSAGE = exports.PREVIEW_READY_MESSAGE = exports.DENEB_PREVIEW_READY_MESSAGE = exports.LEGACY_PREVIEW_DATA_MESSAGE = exports.PREVIEW_DATA_MESSAGE = exports.DENEB_PREVIEW_DATA_MESSAGE = void 0;
|
|
5
5
|
exports.isRecord = isRecord;
|
|
6
6
|
exports.isDarkColor = isDarkColor;
|
|
7
7
|
exports.syncThemeToDocument = syncThemeToDocument;
|
|
@@ -32,6 +32,9 @@ exports.isPreviewValidation = isPreviewValidation;
|
|
|
32
32
|
exports.useCommon = useCommon;
|
|
33
33
|
exports.useContact = useContact;
|
|
34
34
|
exports.useSyncedBranding = useSyncedBranding;
|
|
35
|
+
exports.useCurrency = useCurrency;
|
|
36
|
+
exports.useSocial = useSocial;
|
|
37
|
+
exports.useShopImage = useShopImage;
|
|
35
38
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
36
39
|
const useCart_1 = require("./cart/useCart");
|
|
37
40
|
const react_1 = require("react");
|
|
@@ -56,7 +59,6 @@ exports.LEGACY_PREVIEW_READY_MESSAGE = previousPreviewMessage('READY');
|
|
|
56
59
|
exports.DENEB_PREVIEW_FOCUS_MESSAGE = 'DENEB_PREVIEW_FOCUS_PAGE';
|
|
57
60
|
exports.PREVIEW_FOCUS_MESSAGE = 'FIVORA_PREVIEW_FOCUS_PAGE';
|
|
58
61
|
exports.LEGACY_PREVIEW_FOCUS_MESSAGE = previousPreviewMessage('FOCUS_PAGE');
|
|
59
|
-
exports.DENEB_REFRESH_LIVE_CATALOG_EVENT = 'deneb:refresh-live-catalog';
|
|
60
62
|
exports.PREVIEW_FIELD_ATTRIBUTE = 'data-preview-field-path';
|
|
61
63
|
var core_2 = require("@deneb-ui/core");
|
|
62
64
|
Object.defineProperty(exports, "STYLE_PATCH_MESSAGE", { enumerable: true, get: function () { return core_2.STYLE_PATCH_MESSAGE; } });
|
|
@@ -368,9 +370,6 @@ function SiteDataProvider({ children, initialSiteData, fallbackSiteData, liveCat
|
|
|
368
370
|
}
|
|
369
371
|
return {
|
|
370
372
|
...current,
|
|
371
|
-
liveCatalogUpdatedAt: typeof live.updatedAt === 'string'
|
|
372
|
-
? live.updatedAt
|
|
373
|
-
: new Date().toISOString(),
|
|
374
373
|
shop: nextShop,
|
|
375
374
|
merchant: nextMerchant,
|
|
376
375
|
reviews: nextReviews ?? current.reviews,
|
|
@@ -393,36 +392,6 @@ function SiteDataProvider({ children, initialSiteData, fallbackSiteData, liveCat
|
|
|
393
392
|
...(currentContent?.store && typeof currentContent.store === 'object' && nextProducts !== undefined
|
|
394
393
|
? { store: { ...currentContent.store, products: nextProducts } }
|
|
395
394
|
: {}),
|
|
396
|
-
...(currentContent?.servicesPage &&
|
|
397
|
-
typeof currentContent.servicesPage === 'object' &&
|
|
398
|
-
nextServices !== undefined
|
|
399
|
-
? {
|
|
400
|
-
servicesPage: {
|
|
401
|
-
...currentContent.servicesPage,
|
|
402
|
-
services: nextServices,
|
|
403
|
-
},
|
|
404
|
-
}
|
|
405
|
-
: {}),
|
|
406
|
-
...(currentContent?.company &&
|
|
407
|
-
typeof currentContent.company === 'object' &&
|
|
408
|
-
nextServices !== undefined
|
|
409
|
-
? {
|
|
410
|
-
company: {
|
|
411
|
-
...currentContent.company,
|
|
412
|
-
services: nextServices,
|
|
413
|
-
},
|
|
414
|
-
}
|
|
415
|
-
: {}),
|
|
416
|
-
...(currentContent?.business &&
|
|
417
|
-
typeof currentContent.business === 'object' &&
|
|
418
|
-
nextServices !== undefined
|
|
419
|
-
? {
|
|
420
|
-
business: {
|
|
421
|
-
...currentContent.business,
|
|
422
|
-
services: nextServices,
|
|
423
|
-
},
|
|
424
|
-
}
|
|
425
|
-
: {}),
|
|
426
395
|
...(currentHome || Object.keys(nextHome).length > 0
|
|
427
396
|
? {
|
|
428
397
|
home: {
|
|
@@ -493,19 +462,9 @@ function SiteDataProvider({ children, initialSiteData, fallbackSiteData, liveCat
|
|
|
493
462
|
void loadLiveCatalog();
|
|
494
463
|
}
|
|
495
464
|
};
|
|
496
|
-
const refreshNow = () => {
|
|
497
|
-
if (document.visibilityState !== 'visible')
|
|
498
|
-
return;
|
|
499
|
-
if (retryTimer !== null)
|
|
500
|
-
window.clearTimeout(retryTimer);
|
|
501
|
-
retryTimer = null;
|
|
502
|
-
void loadLiveCatalog();
|
|
503
|
-
};
|
|
504
465
|
void loadLiveCatalog();
|
|
505
466
|
window.addEventListener("focus", refreshIfStale);
|
|
506
467
|
window.addEventListener("online", refreshIfStale);
|
|
507
|
-
window.addEventListener('pageshow', refreshIfStale);
|
|
508
|
-
window.addEventListener(exports.DENEB_REFRESH_LIVE_CATALOG_EVENT, refreshNow);
|
|
509
468
|
document.addEventListener("visibilitychange", refreshIfStale);
|
|
510
469
|
return () => {
|
|
511
470
|
stopped = true;
|
|
@@ -514,8 +473,6 @@ function SiteDataProvider({ children, initialSiteData, fallbackSiteData, liveCat
|
|
|
514
473
|
window.clearTimeout(retryTimer);
|
|
515
474
|
window.removeEventListener("focus", refreshIfStale);
|
|
516
475
|
window.removeEventListener("online", refreshIfStale);
|
|
517
|
-
window.removeEventListener('pageshow', refreshIfStale);
|
|
518
|
-
window.removeEventListener(exports.DENEB_REFRESH_LIVE_CATALOG_EVENT, refreshNow);
|
|
519
476
|
document.removeEventListener("visibilitychange", refreshIfStale);
|
|
520
477
|
};
|
|
521
478
|
}, [liveCatalogEndpoint, siteSlug, initialSiteData]);
|
|
@@ -931,6 +888,27 @@ function normalizeProductItem(p) {
|
|
|
931
888
|
const explicitMax = p.maxPrice ?? customData.maxPrice;
|
|
932
889
|
const explicitRange = p.priceRange ?? customData.priceRange;
|
|
933
890
|
const isRange = Boolean(p.isPriceRange || customData.isPriceRange || (explicitMax && explicitMin));
|
|
891
|
+
const isAvailableCandidate = p.isAvailable !== undefined
|
|
892
|
+
? Boolean(p.isAvailable)
|
|
893
|
+
: p.available !== undefined
|
|
894
|
+
? Boolean(p.available)
|
|
895
|
+
: p.inStock !== undefined
|
|
896
|
+
? Boolean(p.inStock)
|
|
897
|
+
: customData.isAvailable !== undefined
|
|
898
|
+
? Boolean(customData.isAvailable)
|
|
899
|
+
: true;
|
|
900
|
+
const isActiveCandidate = p.isActive !== undefined
|
|
901
|
+
? Boolean(p.isActive)
|
|
902
|
+
: p.active !== undefined
|
|
903
|
+
? Boolean(p.active)
|
|
904
|
+
: customData.isActive !== undefined
|
|
905
|
+
? Boolean(customData.isActive)
|
|
906
|
+
: true;
|
|
907
|
+
const showPriceCandidate = p.showPrice !== undefined
|
|
908
|
+
? Boolean(p.showPrice)
|
|
909
|
+
: customData.showPrice !== undefined
|
|
910
|
+
? Boolean(customData.showPrice)
|
|
911
|
+
: true;
|
|
934
912
|
return {
|
|
935
913
|
...customData,
|
|
936
914
|
...p,
|
|
@@ -938,6 +916,12 @@ function normalizeProductItem(p) {
|
|
|
938
916
|
title: titleCandidate,
|
|
939
917
|
productName: (titleCandidate ?? nameCandidate),
|
|
940
918
|
itemTitle: (titleCandidate ?? nameCandidate),
|
|
919
|
+
isAvailable: isAvailableCandidate,
|
|
920
|
+
inStock: isAvailableCandidate,
|
|
921
|
+
available: isAvailableCandidate,
|
|
922
|
+
isActive: isActiveCandidate,
|
|
923
|
+
active: isActiveCandidate,
|
|
924
|
+
showPrice: showPriceCandidate,
|
|
941
925
|
minPrice: explicitMin !== undefined ? explicitMin : undefined,
|
|
942
926
|
priceMin: (explicitMin ?? p.priceMin) !== undefined ? (explicitMin ?? p.priceMin) : undefined,
|
|
943
927
|
maxPrice: explicitMax !== undefined ? explicitMax : undefined,
|
|
@@ -991,6 +975,8 @@ function normalizeProductItem(p) {
|
|
|
991
975
|
}
|
|
992
976
|
/**
|
|
993
977
|
* Universal Service Normalizer
|
|
978
|
+
* Ensures every service object has both canonical and alias keys simultaneously populated
|
|
979
|
+
* with clean numbers and resolved image URLs, matching the product normalizer's robustness.
|
|
994
980
|
*/
|
|
995
981
|
function normalizeServiceItem(s) {
|
|
996
982
|
if (!isRecord(s))
|
|
@@ -1008,13 +994,90 @@ function normalizeServiceItem(s) {
|
|
|
1008
994
|
(Array.isArray(s.images) ? s.images[0] : undefined) ??
|
|
1009
995
|
(Array.isArray(s.additionalImages) ? s.additionalImages[0] : undefined);
|
|
1010
996
|
const catalogImages = (0, catalogMedia_1.resolveCatalogImages)(s);
|
|
997
|
+
// Price normalization — parse string prices to clean numbers, support aliases
|
|
998
|
+
const rawPrice = s.price !== undefined
|
|
999
|
+
? s.price
|
|
1000
|
+
: s.cost !== undefined
|
|
1001
|
+
? s.cost
|
|
1002
|
+
: s.amount !== undefined
|
|
1003
|
+
? s.amount
|
|
1004
|
+
: s.rate !== undefined
|
|
1005
|
+
? s.rate
|
|
1006
|
+
: s.serviceFee !== undefined
|
|
1007
|
+
? s.serviceFee
|
|
1008
|
+
: s.servicePrice !== undefined
|
|
1009
|
+
? s.servicePrice
|
|
1010
|
+
: customData.price !== undefined
|
|
1011
|
+
? customData.price
|
|
1012
|
+
: undefined;
|
|
1013
|
+
let numPrice = rawPrice;
|
|
1014
|
+
if (typeof rawPrice === "string" && rawPrice.trim()) {
|
|
1015
|
+
const isRangeStr = rawPrice.includes("-") || rawPrice.includes("–") || rawPrice.includes("—") || /\bto\b/i.test(rawPrice);
|
|
1016
|
+
if (!isRangeStr) {
|
|
1017
|
+
const match = rawPrice.match(/-?\d+(?:,\d{3})*(?:\.\d+)?|-?\d+(?:\.\d+)?/);
|
|
1018
|
+
if (match) {
|
|
1019
|
+
const parsed = parseFloat(match[0].replace(/,/g, ""));
|
|
1020
|
+
if (!isNaN(parsed) && Number.isFinite(parsed)) {
|
|
1021
|
+
numPrice = parsed;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
// Compare/original price normalization for services
|
|
1027
|
+
const rawCompare = s.compareAtPrice !== undefined
|
|
1028
|
+
? s.compareAtPrice
|
|
1029
|
+
: s.originalPrice !== undefined
|
|
1030
|
+
? s.originalPrice
|
|
1031
|
+
: s.oldPrice !== undefined
|
|
1032
|
+
? s.oldPrice
|
|
1033
|
+
: s.regularPrice !== undefined
|
|
1034
|
+
? s.regularPrice
|
|
1035
|
+
: customData.compareAtPrice !== undefined
|
|
1036
|
+
? customData.compareAtPrice
|
|
1037
|
+
: undefined;
|
|
1038
|
+
let numCompare = rawCompare;
|
|
1039
|
+
if (typeof rawCompare === "string" && rawCompare.trim()) {
|
|
1040
|
+
const match = rawCompare.match(/-?\d+(?:,\d{3})*(?:\.\d+)?|-?\d+(?:\.\d+)?/);
|
|
1041
|
+
if (match) {
|
|
1042
|
+
const parsed = parseFloat(match[0].replace(/,/g, ""));
|
|
1043
|
+
if (!isNaN(parsed) && Number.isFinite(parsed)) {
|
|
1044
|
+
numCompare = parsed;
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
const priceLabelCandidate = s.priceLabel ?? customData.priceLabel;
|
|
1049
|
+
const isActiveCandidate = s.isActive !== undefined
|
|
1050
|
+
? Boolean(s.isActive)
|
|
1051
|
+
: s.active !== undefined
|
|
1052
|
+
? Boolean(s.active)
|
|
1053
|
+
: s.isAvailable !== undefined
|
|
1054
|
+
? Boolean(s.isAvailable)
|
|
1055
|
+
: s.available !== undefined
|
|
1056
|
+
? Boolean(s.available)
|
|
1057
|
+
: customData.isActive !== undefined
|
|
1058
|
+
? Boolean(customData.isActive)
|
|
1059
|
+
: customData.isAvailable !== undefined
|
|
1060
|
+
? Boolean(customData.isAvailable)
|
|
1061
|
+
: true;
|
|
1062
|
+
const showPriceCandidate = s.showPrice !== undefined
|
|
1063
|
+
? Boolean(s.showPrice)
|
|
1064
|
+
: customData.showPrice !== undefined
|
|
1065
|
+
? Boolean(customData.showPrice)
|
|
1066
|
+
: true;
|
|
1067
|
+
const badgeCandidate = s.badge ?? s.tag ?? s.label ?? customData.badge ?? customData.tag;
|
|
1011
1068
|
return {
|
|
1012
1069
|
...customData,
|
|
1013
1070
|
...s,
|
|
1014
1071
|
name: nameCandidate,
|
|
1015
1072
|
title: titleCandidate,
|
|
1073
|
+
isActive: isActiveCandidate,
|
|
1074
|
+
active: isActiveCandidate,
|
|
1075
|
+
isAvailable: isActiveCandidate,
|
|
1076
|
+
available: isActiveCandidate,
|
|
1077
|
+
showPrice: showPriceCandidate,
|
|
1016
1078
|
...(descCandidate !== undefined ? { description: descCandidate, desc: descCandidate, details: descCandidate } : {}),
|
|
1017
1079
|
...(imageCandidate !== undefined ? { imageUrl: imageCandidate, image: imageCandidate, photo: imageCandidate } : {}),
|
|
1080
|
+
...(badgeCandidate !== undefined ? { badge: String(badgeCandidate), tag: String(badgeCandidate) } : {}),
|
|
1018
1081
|
...(catalogImages.length > 0
|
|
1019
1082
|
? {
|
|
1020
1083
|
gallery: catalogImages,
|
|
@@ -1022,20 +1085,30 @@ function normalizeServiceItem(s) {
|
|
|
1022
1085
|
additionalImages: catalogImages.slice(1),
|
|
1023
1086
|
}
|
|
1024
1087
|
: {}),
|
|
1088
|
+
...(numPrice !== undefined
|
|
1089
|
+
? {
|
|
1090
|
+
price: numPrice,
|
|
1091
|
+
cost: numPrice,
|
|
1092
|
+
amount: numPrice,
|
|
1093
|
+
rate: numPrice,
|
|
1094
|
+
serviceFee: numPrice,
|
|
1095
|
+
servicePrice: numPrice,
|
|
1096
|
+
}
|
|
1097
|
+
: {}),
|
|
1098
|
+
...(numCompare !== undefined
|
|
1099
|
+
? {
|
|
1100
|
+
compareAtPrice: numCompare,
|
|
1101
|
+
originalPrice: numCompare,
|
|
1102
|
+
}
|
|
1103
|
+
: {}),
|
|
1104
|
+
...(priceLabelCandidate !== undefined ? { priceLabel: priceLabelCandidate } : {}),
|
|
1025
1105
|
};
|
|
1026
1106
|
}
|
|
1027
|
-
function useProducts(fallback = []) {
|
|
1107
|
+
function useProducts(fallback = [], options) {
|
|
1028
1108
|
const siteData = useSiteData();
|
|
1029
1109
|
const content = isRecord(siteData?.content) ? siteData.content : null;
|
|
1030
1110
|
if (!content)
|
|
1031
1111
|
return fallback;
|
|
1032
|
-
// Once the public catalog endpoint has answered, its top-level collection is
|
|
1033
|
-
// authoritative even when it is empty. This prevents deleted products from
|
|
1034
|
-
// falling back to stale products embedded in the generated site bundle.
|
|
1035
|
-
if (typeof siteData.liveCatalogUpdatedAt === 'string' &&
|
|
1036
|
-
Array.isArray(content.products)) {
|
|
1037
|
-
return content.products.map(normalizeProductItem);
|
|
1038
|
-
}
|
|
1039
1112
|
let rawList = null;
|
|
1040
1113
|
const candidates = [
|
|
1041
1114
|
content.products,
|
|
@@ -1057,23 +1130,26 @@ function useProducts(fallback = []) {
|
|
|
1057
1130
|
}
|
|
1058
1131
|
if (!rawList)
|
|
1059
1132
|
return fallback;
|
|
1060
|
-
|
|
1133
|
+
let list = rawList.map(normalizeProductItem);
|
|
1134
|
+
if (options?.activeOnly) {
|
|
1135
|
+
list = list.filter((p) => p.isActive !== false && p.status !== 'ARCHIVED' && p.status !== 'DRAFT');
|
|
1136
|
+
}
|
|
1137
|
+
if (options?.inStockOnly) {
|
|
1138
|
+
list = list.filter((p) => p.isAvailable !== false && p.inStock !== false);
|
|
1139
|
+
}
|
|
1140
|
+
return list;
|
|
1061
1141
|
}
|
|
1062
1142
|
/**
|
|
1063
1143
|
* Hook to retrieve services cleanly from SiteData, supporting both
|
|
1064
1144
|
* top-level content.services and nested content.home.services.
|
|
1145
|
+
* Supports optional { activeOnly: true } filtering to mirror product availability.
|
|
1065
1146
|
*/
|
|
1066
|
-
function useServices(fallback = []) {
|
|
1147
|
+
function useServices(fallback = [], options) {
|
|
1067
1148
|
const siteData = useSiteData();
|
|
1068
1149
|
const content = isRecord(siteData?.content) ? siteData.content : null;
|
|
1069
1150
|
if (!content)
|
|
1070
1151
|
return fallback;
|
|
1071
|
-
|
|
1072
|
-
// resurrect build-time services from a nested legacy collection or fallback.
|
|
1073
|
-
if (typeof siteData.liveCatalogUpdatedAt === 'string' &&
|
|
1074
|
-
Array.isArray(content.services)) {
|
|
1075
|
-
return content.services.map(normalizeServiceItem);
|
|
1076
|
-
}
|
|
1152
|
+
let rawList = null;
|
|
1077
1153
|
const candidates = [
|
|
1078
1154
|
content.services,
|
|
1079
1155
|
content.servicesPage?.services,
|
|
@@ -1084,10 +1160,15 @@ function useServices(fallback = []) {
|
|
|
1084
1160
|
];
|
|
1085
1161
|
for (const candidate of candidates) {
|
|
1086
1162
|
if (Array.isArray(candidate) && candidate.length > 0) {
|
|
1087
|
-
|
|
1163
|
+
rawList = candidate;
|
|
1164
|
+
break;
|
|
1088
1165
|
}
|
|
1089
1166
|
}
|
|
1090
|
-
|
|
1167
|
+
const list = rawList ? rawList.map(normalizeServiceItem) : fallback;
|
|
1168
|
+
if (options?.activeOnly) {
|
|
1169
|
+
return list.filter((s) => s.isActive !== false && s.isAvailable !== false);
|
|
1170
|
+
}
|
|
1171
|
+
return list;
|
|
1091
1172
|
}
|
|
1092
1173
|
/**
|
|
1093
1174
|
* Hook to access official Fivora backend API endpoints (catalogUrl, contactUrl, analyticsUrl).
|
|
@@ -1314,3 +1395,79 @@ function useSyncedBranding(fallback = {}) {
|
|
|
1314
1395
|
faviconUrl,
|
|
1315
1396
|
};
|
|
1316
1397
|
}
|
|
1398
|
+
/**
|
|
1399
|
+
* Hook to retrieve the live store currency code (e.g. "LKR", "USD", "EUR").
|
|
1400
|
+
* Auto-hydrates from the merchant portal's shop profile.
|
|
1401
|
+
* Hierarchy: shop.currency → content.common.currency → merchant.currency → fallback.
|
|
1402
|
+
*/
|
|
1403
|
+
function useCurrency(fallback = 'LKR') {
|
|
1404
|
+
const siteData = useSiteData();
|
|
1405
|
+
const content = isRecord(siteData?.content) ? siteData.content : null;
|
|
1406
|
+
const common = isRecord(content?.common) ? content.common : {};
|
|
1407
|
+
const shop = useShop();
|
|
1408
|
+
return ((typeof shop.currency === 'string' && shop.currency.trim()) ||
|
|
1409
|
+
(typeof common.currency === 'string' && common.currency.trim()) ||
|
|
1410
|
+
(typeof shop.currencyCode === 'string' && shop.currencyCode.trim()) ||
|
|
1411
|
+
(typeof common.currencyCode === 'string' && common.currencyCode.trim()) ||
|
|
1412
|
+
fallback);
|
|
1413
|
+
}
|
|
1414
|
+
/**
|
|
1415
|
+
* Hook to retrieve the live social links map from the merchant profile.
|
|
1416
|
+
* Auto-hydrates from the shop owner's Fivora Portal social configuration.
|
|
1417
|
+
* Returns a map like { facebook: "https://...", instagram: "https://...", ... }.
|
|
1418
|
+
*/
|
|
1419
|
+
function useSocial(fallback = {}) {
|
|
1420
|
+
const siteData = useSiteData();
|
|
1421
|
+
const content = isRecord(siteData?.content) ? siteData.content : null;
|
|
1422
|
+
const common = isRecord(content?.common) ? content.common : {};
|
|
1423
|
+
const shop = useShop();
|
|
1424
|
+
const shopSocial = isRecord(shop.socialLinks) ? shop.socialLinks : (isRecord(shop.social) ? shop.social : {});
|
|
1425
|
+
const commonSocial = isRecord(common.socialLinks) ? common.socialLinks : (isRecord(common.social) ? common.social : {});
|
|
1426
|
+
const extractString = (key) => {
|
|
1427
|
+
const candidates = [
|
|
1428
|
+
shopSocial[key],
|
|
1429
|
+
commonSocial[key],
|
|
1430
|
+
shop[key],
|
|
1431
|
+
common[key],
|
|
1432
|
+
fallback[key],
|
|
1433
|
+
];
|
|
1434
|
+
for (const candidate of candidates) {
|
|
1435
|
+
if (typeof candidate === 'string' && candidate.trim()) {
|
|
1436
|
+
return candidate.trim();
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
return '';
|
|
1440
|
+
};
|
|
1441
|
+
return {
|
|
1442
|
+
facebook: extractString('facebook') || extractString('facebookUrl'),
|
|
1443
|
+
instagram: extractString('instagram') || extractString('instagramUrl'),
|
|
1444
|
+
tiktok: extractString('tiktok') || extractString('tiktokUrl'),
|
|
1445
|
+
youtube: extractString('youtube') || extractString('youtubeUrl'),
|
|
1446
|
+
linkedin: extractString('linkedin') || extractString('linkedinUrl'),
|
|
1447
|
+
twitter: extractString('twitter') || extractString('twitterUrl') || extractString('x'),
|
|
1448
|
+
website: extractString('website') || extractString('websiteUrl'),
|
|
1449
|
+
...Object.fromEntries(Object.entries({ ...fallback, ...commonSocial, ...shopSocial })
|
|
1450
|
+
.filter(([, v]) => typeof v === 'string' && v.trim())
|
|
1451
|
+
.map(([k, v]) => [k, String(v).trim()])),
|
|
1452
|
+
};
|
|
1453
|
+
}
|
|
1454
|
+
/**
|
|
1455
|
+
* Hook to retrieve the live shop front / cover / banner image URL.
|
|
1456
|
+
* Auto-hydrates from the merchant portal's shop profile.
|
|
1457
|
+
* Hierarchy: shop.coverImage → shop.shopImage → shop.bannerImage → shop.heroImage → content.common.shopImage → fallback.
|
|
1458
|
+
*/
|
|
1459
|
+
function useShopImage(fallback = '') {
|
|
1460
|
+
const siteData = useSiteData();
|
|
1461
|
+
const content = isRecord(siteData?.content) ? siteData.content : null;
|
|
1462
|
+
const common = isRecord(content?.common) ? content.common : {};
|
|
1463
|
+
const shop = useShop();
|
|
1464
|
+
return ((typeof shop.coverImage === 'string' && shop.coverImage.trim()) ||
|
|
1465
|
+
(typeof shop.shopImage === 'string' && shop.shopImage.trim()) ||
|
|
1466
|
+
(typeof shop.bannerImage === 'string' && shop.bannerImage.trim()) ||
|
|
1467
|
+
(typeof shop.heroImage === 'string' && shop.heroImage.trim()) ||
|
|
1468
|
+
(typeof shop.shopFrontImage === 'string' && shop.shopFrontImage.trim()) ||
|
|
1469
|
+
(typeof common.shopImage === 'string' && common.shopImage.trim()) ||
|
|
1470
|
+
(typeof common.coverImage === 'string' && common.coverImage.trim()) ||
|
|
1471
|
+
(typeof common.bannerImage === 'string' && common.bannerImage.trim()) ||
|
|
1472
|
+
fallback);
|
|
1473
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deneb-ui/ui",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.128",
|
|
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.
|
|
53
|
+
"@deneb-ui/core": "^2.0.128"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"react": "^18.0.0 || ^19.0.0",
|