storefront-layouts 1.0.18 → 1.0.19
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/dist/components/ui/category-tree.d.ts +5 -1
- package/dist/components/ui/category-tree.d.ts.map +1 -1
- package/dist/components/ui/category-tree.js +36 -12
- package/dist/components/ui/product-card.d.ts +1 -1
- package/dist/components/ui/product-card.d.ts.map +1 -1
- package/dist/components/ui/product-card.js +15 -15
- package/dist/editor/alignment-schemas/booking.d.ts.map +1 -1
- package/dist/editor/alignment-schemas/booking.js +104 -61
- package/dist/editor/alignment-schemas/clothing-minimal.d.ts.map +1 -1
- package/dist/editor/alignment-schemas/clothing-minimal.js +74 -30
- package/dist/editor/alignment-schemas/clothing.d.ts.map +1 -1
- package/dist/editor/alignment-schemas/clothing.js +87 -32
- package/dist/editor/alignment-schemas/food.d.ts.map +1 -1
- package/dist/editor/alignment-schemas/food.js +103 -48
- package/dist/editor/payaza-form/PayazaFormEditor.d.ts.map +1 -1
- package/dist/editor/payaza-form/PayazaFormEditor.js +13 -1
- package/dist/editor/payaza-form/components/ImageField.d.ts.map +1 -1
- package/dist/editor/payaza-form/components/ImageField.js +1 -1
- package/dist/editor/payaza-form/components/ToggleField.d.ts.map +1 -1
- package/dist/editor/payaza-form/components/ToggleField.js +2 -1
- package/dist/editor/payaza-form/data-merger.d.ts.map +1 -1
- package/dist/editor/payaza-form/data-merger.js +61 -9
- package/dist/editor/shared/EditorHeader.d.ts.map +1 -1
- package/dist/editor/shared/EditorHeader.js +20 -25
- package/dist/editor/shared/IframePreview.d.ts.map +1 -1
- package/dist/editor/shared/IframePreview.js +46 -22
- package/dist/hooks/use-payaza-checkout.d.ts.map +1 -1
- package/dist/hooks/use-payaza-checkout.js +0 -2
- package/dist/layouts/booking/components/booking-about-defaults.d.ts +16 -0
- package/dist/layouts/booking/components/booking-about-defaults.d.ts.map +1 -1
- package/dist/layouts/booking/components/booking-about-defaults.js +171 -1
- package/dist/layouts/booking/components/booking-footer-defaults.d.ts +2 -2
- package/dist/layouts/booking/components/booking-footer-defaults.d.ts.map +1 -1
- package/dist/layouts/booking/components/booking-footer-defaults.js +5 -8
- package/dist/layouts/booking/pages/AboutPage.d.ts.map +1 -1
- package/dist/layouts/booking/pages/AboutPage.js +43 -36
- package/dist/layouts/booking/pages/ContactPage.d.ts.map +1 -1
- package/dist/layouts/booking/pages/ContactPage.js +2 -2
- package/dist/layouts/booking-agenda/pages/AboutPage.d.ts.map +1 -1
- package/dist/layouts/booking-agenda/pages/AboutPage.js +7 -24
- package/dist/layouts/booking-agenda/pages/ContactPage.d.ts.map +1 -1
- package/dist/layouts/booking-agenda/pages/ContactPage.js +2 -2
- package/dist/layouts/clothing/pages/AboutPage.d.ts.map +1 -1
- package/dist/layouts/clothing/pages/AboutPage.js +34 -17
- package/dist/layouts/clothing/pages/ContactPage.d.ts.map +1 -1
- package/dist/layouts/clothing/pages/ContactPage.js +3 -3
- package/dist/layouts/clothing/pages/ProductsPage.d.ts.map +1 -1
- package/dist/layouts/clothing/pages/ProductsPage.js +18 -4
- package/dist/layouts/clothing/styles/clothing.css +28 -1
- package/dist/layouts/clothing-minimal/pages/AboutPage.d.ts.map +1 -1
- package/dist/layouts/clothing-minimal/pages/AboutPage.js +36 -36
- package/dist/layouts/clothing-minimal/pages/ContactPage.d.ts.map +1 -1
- package/dist/layouts/clothing-minimal/pages/ContactPage.js +2 -2
- package/dist/layouts/electronics/components/ElectronicsStoreFooter.d.ts.map +1 -1
- package/dist/layouts/electronics/components/ElectronicsStoreFooter.js +1 -1
- package/dist/layouts/electronics/pages/AboutPage.d.ts.map +1 -1
- package/dist/layouts/electronics/pages/AboutPage.js +7 -24
- package/dist/layouts/electronics/pages/ContactPage.d.ts.map +1 -1
- package/dist/layouts/electronics/pages/ContactPage.js +2 -2
- package/dist/layouts/electronics-grid/components/ElectronicsHomePageGrid.d.ts.map +1 -1
- package/dist/layouts/electronics-grid/components/ElectronicsHomePageGrid.js +1 -1
- package/dist/layouts/electronics-grid/pages/AboutPage.d.ts.map +1 -1
- package/dist/layouts/electronics-grid/pages/AboutPage.js +7 -24
- package/dist/layouts/electronics-grid/pages/ContactPage.d.ts.map +1 -1
- package/dist/layouts/electronics-grid/pages/ContactPage.js +2 -2
- package/dist/layouts/food/pages/AboutPage.d.ts.map +1 -1
- package/dist/layouts/food/pages/AboutPage.js +48 -56
- package/dist/layouts/food/pages/ContactPage.d.ts.map +1 -1
- package/dist/layouts/food/pages/ContactPage.js +2 -2
- package/dist/layouts/food-modern/pages/AboutPage.d.ts.map +1 -1
- package/dist/layouts/food-modern/pages/AboutPage.js +7 -24
- package/dist/layouts/food-modern/pages/ContactPage.d.ts.map +1 -1
- package/dist/layouts/food-modern/pages/ContactPage.js +2 -2
- package/dist/layouts/motivational-speaker/pages/AboutPage.d.ts.map +1 -1
- package/dist/layouts/motivational-speaker/pages/AboutPage.js +7 -24
- package/dist/layouts/motivational-speaker/pages/ContactPage.d.ts.map +1 -1
- package/dist/layouts/motivational-speaker/pages/ContactPage.js +2 -2
- package/dist/layouts/shared/components/StoreFooter.d.ts.map +1 -1
- package/dist/layouts/shared/components/StoreFooter.js +4 -6
- package/dist/layouts/shared/components/StoreHeader.d.ts.map +1 -1
- package/dist/layouts/shared/components/StoreHeader.js +60 -6
- package/dist/layouts/shared/pages/CheckoutPage.d.ts.map +1 -1
- package/dist/layouts/shared/pages/CheckoutPage.js +0 -78
- package/dist/layouts/shared/wrappers/ClothingLayout.d.ts.map +1 -1
- package/dist/layouts/shared/wrappers/ClothingLayout.js +17 -0
- package/dist/lib/mock-stores.js +1 -1
- package/dist/lib/payaza-checkout.d.ts.map +1 -1
- package/dist/lib/payaza-checkout.js +0 -33
- package/dist/lib/preview-data.d.ts.map +1 -1
- package/dist/lib/preview-data.js +3 -2
- package/dist/lib/utils/category-tree.d.ts +2 -0
- package/dist/lib/utils/category-tree.d.ts.map +1 -1
- package/dist/lib/utils/category-tree.js +15 -0
- package/dist/lib/utils/footer-nav-defaults.d.ts +11 -2
- package/dist/lib/utils/footer-nav-defaults.d.ts.map +1 -1
- package/dist/lib/utils/footer-nav-defaults.js +29 -22
- package/dist/styles/index.css +203 -212
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorHeader.d.ts","sourceRoot":"","sources":["../../../src/editor/shared/EditorHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"EditorHeader.d.ts","sourceRoot":"","sources":["../../../src/editor/shared/EditorHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoE,MAAM,OAAO,CAAC;AA4BzF,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAuJtD,UAAU,iBAAiB;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACtC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,QAAQ,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC3C,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,KAAK,IAAI,CAAC;IACnE,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IAClD,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;IAClC,8DAA8D;IAC9D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,2CAA2C;IAC3C,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC7D,sFAAsF;IACtF,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,oEAAoE;IACpE,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAChD,uDAAuD;IACvD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6DAA6D;IAC7D,kBAAkB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,yDAAyD;IACzD,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;CACzD;AA0DD,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAgfpD,CAAC"}
|
|
@@ -3,30 +3,43 @@ import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react
|
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
4
|
import { motion, AnimatePresence } from 'framer-motion';
|
|
5
5
|
import { cn } from '../../lib/utils/index.js';
|
|
6
|
-
import { ArrowLeft, Layout, Save, Smartphone, Monitor, Tablet, Eye, Pencil, PanelLeft, ChevronDown, Home, ShoppingBag, ShoppingCart, FileText, Settings, Undo2, Redo2, Send, Sparkles, Image as ImageIcon, Palette, Check,
|
|
7
|
-
import { PREVIEW_ZOOM_OPTIONS } from './preview-viewport.js';
|
|
6
|
+
import { ArrowLeft, Layout, Save, Smartphone, Monitor, Tablet, Eye, Pencil, PanelLeft, ChevronDown, Home, ShoppingBag, ShoppingCart, FileText, Settings, Undo2, Redo2, Send, Sparkles, Image as ImageIcon, Palette, Check, } from 'lucide-react';
|
|
8
7
|
const Tooltip = ({ text, children }) => {
|
|
9
8
|
const [isVisible, setIsVisible] = useState(false);
|
|
10
9
|
const [coords, setCoords] = useState({ top: 0, left: 0 });
|
|
11
10
|
const showTimeoutRef = useRef(null);
|
|
12
11
|
const hideTimeoutRef = useRef(null);
|
|
13
12
|
const triggerRef = useRef(null);
|
|
13
|
+
const bubbleRef = useRef(null);
|
|
14
14
|
const visibleRef = useRef(false);
|
|
15
15
|
const updatePosition = useCallback(() => {
|
|
16
16
|
const el = triggerRef.current;
|
|
17
17
|
if (!el)
|
|
18
18
|
return;
|
|
19
|
+
const pad = 12;
|
|
19
20
|
const r = el.getBoundingClientRect();
|
|
20
|
-
|
|
21
|
+
const bubble = bubbleRef.current;
|
|
22
|
+
const bubbleWidth = bubble?.offsetWidth ?? Math.min(352, window.innerWidth - pad * 2);
|
|
23
|
+
const bubbleHeight = bubble?.offsetHeight ?? 44;
|
|
24
|
+
const centerX = r.left + r.width / 2;
|
|
25
|
+
let left = centerX - bubbleWidth / 2;
|
|
26
|
+
left = Math.max(pad, Math.min(left, window.innerWidth - pad - bubbleWidth));
|
|
27
|
+
let top = r.bottom + 8;
|
|
28
|
+
if (top + bubbleHeight > window.innerHeight - pad) {
|
|
29
|
+
top = Math.max(pad, r.top - 8 - bubbleHeight);
|
|
30
|
+
}
|
|
31
|
+
setCoords({ top, left });
|
|
21
32
|
}, []);
|
|
22
33
|
useLayoutEffect(() => {
|
|
23
34
|
if (!isVisible)
|
|
24
35
|
return;
|
|
25
36
|
updatePosition();
|
|
37
|
+
const raf = requestAnimationFrame(() => updatePosition());
|
|
26
38
|
const onReposition = () => updatePosition();
|
|
27
39
|
window.addEventListener('scroll', onReposition, true);
|
|
28
40
|
window.addEventListener('resize', onReposition);
|
|
29
41
|
return () => {
|
|
42
|
+
cancelAnimationFrame(raf);
|
|
30
43
|
window.removeEventListener('scroll', onReposition, true);
|
|
31
44
|
window.removeEventListener('resize', onReposition);
|
|
32
45
|
};
|
|
@@ -73,12 +86,12 @@ const Tooltip = ({ text, children }) => {
|
|
|
73
86
|
}
|
|
74
87
|
scheduleHide();
|
|
75
88
|
};
|
|
76
|
-
const tooltipBubble = typeof document !== 'undefined' ? (createPortal(_jsx(AnimatePresence, { children: isVisible && (_jsx(motion.div, { initial: { opacity: 0, y: 6, scale: 0.97 }, animate: { opacity: 1, y: 0, scale: 1 }, exit: { opacity: 0, y: 6, scale: 0.97 }, transition: { duration: 0.15, ease: [0.23, 1, 0.32, 1] }, style: {
|
|
89
|
+
const tooltipBubble = typeof document !== 'undefined' ? (createPortal(_jsx(AnimatePresence, { children: isVisible && (_jsx(motion.div, { ref: bubbleRef, initial: { opacity: 0, y: 6, scale: 0.97 }, animate: { opacity: 1, y: 0, scale: 1 }, exit: { opacity: 0, y: 6, scale: 0.97 }, transition: { duration: 0.15, ease: [0.23, 1, 0.32, 1] }, style: {
|
|
77
90
|
position: 'fixed',
|
|
78
91
|
top: coords.top,
|
|
79
92
|
left: coords.left,
|
|
80
|
-
transform: 'translateX(-50%)',
|
|
81
93
|
zIndex: 200000,
|
|
94
|
+
maxWidth: 'min(22rem, calc(100vw - 24px))',
|
|
82
95
|
}, className: "pointer-events-auto", onMouseEnter: cancelHide, onMouseLeave: scheduleHide, children: _jsx("div", { "data-payaza-header-tooltip": true, className: "max-w-[min(92vw,22rem)] rounded-lg border border-white/12 border-l-[3px] border-l-shopaza-green bg-shopaza-ink px-3 py-2 text-left text-[12px] font-medium leading-relaxed tracking-tight text-white shadow-[0_12px_40px_rgba(27,0,41,0.38)] ring-1 ring-black/20", children: text }) }, text)) }), document.body)) : null;
|
|
83
96
|
return (_jsxs(_Fragment, { children: [_jsx("div", { ref: triggerRef, className: "relative flex items-center justify-center", onMouseEnter: onTriggerEnter, onMouseLeave: onTriggerLeave, onFocusCapture: onTriggerEnter, onBlurCapture: onTriggerLeave, children: children }), tooltipBubble] }));
|
|
84
97
|
};
|
|
@@ -104,24 +117,6 @@ function Cluster({ children, className }) {
|
|
|
104
117
|
function Divider() {
|
|
105
118
|
return _jsx("span", { className: "mx-1 inline-block h-6 w-px shrink-0 bg-[#eef1f5]", "aria-hidden": true });
|
|
106
119
|
}
|
|
107
|
-
function PreviewZoomDropdown({ previewZoom, onPreviewZoomChange }) {
|
|
108
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
109
|
-
const activeLabel = PREVIEW_ZOOM_OPTIONS.find((option) => option.value === previewZoom)?.label ?? 'Fit';
|
|
110
|
-
useEffect(() => {
|
|
111
|
-
const onClickOutside = (e) => {
|
|
112
|
-
if (!e.target.closest('.zoom-dropdown-container')) {
|
|
113
|
-
setIsOpen(false);
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
if (isOpen)
|
|
117
|
-
document.addEventListener('mousedown', onClickOutside);
|
|
118
|
-
return () => document.removeEventListener('mousedown', onClickOutside);
|
|
119
|
-
}, [isOpen]);
|
|
120
|
-
return (_jsxs("div", { className: "zoom-dropdown-container relative", children: [_jsx(Tooltip, { text: "Preview zoom level", children: _jsxs("button", { type: "button", onClick: () => setIsOpen((v) => !v), "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-label": `Preview zoom: ${activeLabel}`, className: "flex h-8 min-w-[4.75rem] items-center gap-1.5 rounded-lg border border-[#e6e9ee] bg-white px-2.5 text-[12px] font-semibold text-[#374151] shadow-[0_1px_2px_rgba(15,23,42,0.05)] transition-colors hover:border-[#d4dae3] hover:bg-[#fcfdff]", children: [_jsx(ZoomIn, { className: "h-3.5 w-3.5 shrink-0 text-[#440066]", strokeWidth: 2 }), _jsx("span", { className: "tabular-nums", children: activeLabel }), _jsx(ChevronDown, { className: cn('ml-auto h-3.5 w-3.5 shrink-0 text-[#9aa3b2] transition-transform', isOpen && 'rotate-180'), strokeWidth: 2 })] }) }), _jsx(AnimatePresence, { children: isOpen && (_jsxs(motion.div, { initial: { opacity: 0, y: 6 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: 6 }, transition: { duration: 0.12 }, role: "listbox", "aria-label": "Preview zoom options", className: "absolute right-0 top-full z-[200] mt-1.5 w-[8.5rem] rounded-xl border border-[#e6e9ee] bg-white py-1 shadow-[0_12px_24px_rgba(15,23,42,0.08)]", children: [_jsx("div", { className: "border-b border-[#f3f4f6] px-3 py-2", children: _jsx("span", { className: "text-[11px] font-semibold uppercase tracking-wide text-[#8a94a5]", children: "Zoom" }) }), _jsx("div", { className: "py-1", children: PREVIEW_ZOOM_OPTIONS.map((option) => (_jsxs("button", { type: "button", role: "option", "aria-selected": previewZoom === option.value, onClick: () => {
|
|
121
|
-
onPreviewZoomChange(option.value);
|
|
122
|
-
setIsOpen(false);
|
|
123
|
-
}, className: cn('flex w-full items-center gap-2 px-3 py-2 text-left text-[13px] transition-colors hover:bg-[#f8fafc]', previewZoom === option.value && 'bg-[#f5f0ff] font-medium text-[#440066] hover:bg-[#ede9ff]'), children: [_jsx("span", { className: "flex-1 tabular-nums", children: option.label }), previewZoom === option.value && (_jsx(Check, { className: "h-4 w-4 shrink-0 text-[#440066]", strokeWidth: 2.5 }))] }, String(option.value)))) })] })) })] }));
|
|
124
|
-
}
|
|
125
120
|
/* ─── Component ──────────────────────────────────────────────────────────── */
|
|
126
121
|
export const EditorHeader = ({ layoutName, storeName, storeLogo, activePage, isSaving, isPublishing, onSave, onPublish, onBack, onBackToSettings, onOpenAssets, onBackToTheme, onUndo, onRedo, canUndo, canRedo, onGenerateAI, isGeneratingAI, pages, onPageSwitch, viewMode = 'desktop', onViewModeChange, previewZoom = 'fit', onPreviewZoomChange, publishButtonText = 'Publish', centerTemplateLabel, showPageSwitcher = true, showPageContextCard = true, currentPageLabel, outlinePanelOpen, onToggleOutlinePanel, listViewOpen = true, onToggleListView, interactionMode = 'edit', onInteractionModeChange, isMobileChrome = false, headerRef, headerStatusNote, mobileStatusBanner, draftSaveStatus = 'idle', }) => {
|
|
127
122
|
const navigatorOpen = outlinePanelOpen !== undefined ? outlinePanelOpen : listViewOpen;
|
|
@@ -151,14 +146,14 @@ export const EditorHeader = ({ layoutName, storeName, storeLogo, activePage, isS
|
|
|
151
146
|
? 'Unsaved changes'
|
|
152
147
|
: null;
|
|
153
148
|
const showMobileStatusRow = isMobileChrome && (headerStatusNote || mobileStatusBanner);
|
|
154
|
-
return (_jsxs("header", { ref: headerRef, className: cn('sticky top-0 z-[100] flex shrink-0 flex-col border-b border-[#e6e9ee] bg-white/95 font-sans antialiased text-[#1f2937] backdrop-blur supports-[backdrop-filter]:bg-white/88', isMobileChrome ? 'min-h-0' : 'min-h-[52px] md:min-h-[72px]'), style: { paddingTop: 'env(safe-area-inset-top, 0px)' }, children: [_jsxs("div", { className: cn('flex w-full flex-1 items-center overflow-x-auto', isMobileChrome ? 'min-h-[48px] gap-2 px-3 py-1.5' : 'min-h-[52px] gap-3 px-3 py-2 md:min-h-[72px] md:px-5'), children: [_jsxs("div", { className: cn('flex min-w-0 shrink-0 items-center', isMobileChrome ? 'gap-1' : 'gap-1.5'), children: [onBack && (_jsx(Tooltip, { text: "
|
|
149
|
+
return (_jsxs("header", { ref: headerRef, className: cn('sticky top-0 z-[100] flex shrink-0 flex-col border-b border-[#e6e9ee] bg-white/95 font-sans antialiased text-[#1f2937] backdrop-blur supports-[backdrop-filter]:bg-white/88', isMobileChrome ? 'min-h-0' : 'min-h-[52px] md:min-h-[72px]'), style: { paddingTop: 'env(safe-area-inset-top, 0px)' }, children: [_jsxs("div", { className: cn('flex w-full flex-1 items-center overflow-x-auto', isMobileChrome ? 'min-h-[48px] gap-2 px-3 py-1.5' : 'min-h-[52px] gap-3 px-3 py-2 md:min-h-[72px] md:px-5'), children: [_jsxs("div", { className: cn('flex min-w-0 shrink-0 items-center', isMobileChrome ? 'gap-1' : 'gap-1.5'), children: [onBack && (_jsx(Tooltip, { text: "Back to layout selection", children: _jsxs("button", { type: "button", onClick: onBack, "aria-label": "Back to layout selection", className: cn('flex shrink-0 items-center gap-1.5 rounded-lg text-[12px] font-semibold text-[#50575e] transition-colors hover:bg-[#f3f4f6] hover:text-[#1b0029] active:bg-[#eef1f5] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#440066]/35 focus-visible:ring-offset-2', isMobileChrome ? 'h-9 px-2' : 'h-9 px-2 min-[900px]:px-2.5'), children: [_jsx(ArrowLeft, { className: "h-4 w-4 shrink-0", strokeWidth: 2, "aria-hidden": true }), _jsx("span", { className: "hidden min-[900px]:inline", children: "Back" })] }) })), toggleNavigator && (_jsx(Tooltip, { text: navigatorOpen ? 'Hide outline panel' : 'Show outline panel', children: _jsx(IconBtn, { active: navigatorOpen, onClick: toggleNavigator, "aria-label": navigatorOpen ? 'Hide outline panel' : 'Show outline panel', children: _jsx(PanelLeft, { className: "h-4 w-4", strokeWidth: 2 }) }) })), (toggleNavigator || onUndo || onRedo) && (_jsx("span", { className: cn('inline-block w-px shrink-0 bg-[#eef1f5]', isMobileChrome ? 'mx-0.5 h-5' : 'mx-0.5 h-5'), "aria-hidden": true })), _jsx(Tooltip, { text: "Undo last change (Ctrl+Z)", children: _jsx(IconBtn, { onClick: onUndo, disabled: !canUndo, "aria-label": "Undo", children: _jsx(Undo2, { className: "h-4 w-4", strokeWidth: 2 }) }) }), _jsx(Tooltip, { text: "Redo last change (Ctrl+Y)", children: _jsx(IconBtn, { onClick: onRedo, disabled: !canRedo, "aria-label": "Redo", children: _jsx(Redo2, { className: "h-4 w-4", strokeWidth: 2 }) }) }), _jsxs("div", { className: "hidden min-w-0 items-center gap-2.5 min-[900px]:flex", children: [_jsx("span", { className: "h-7 w-px shrink-0 bg-[#e8ecf2]", "aria-hidden": true }), _jsx("div", { className: cn('flex h-9 w-9 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-[#e6e9ee] bg-white shadow-sm', storeLogo && !logoError && storeLogo.trim() !== '' ? '' : 'bg-[#f6f7f7]'), children: storeLogo && !logoError && storeLogo.trim() !== '' ? (_jsx("img", { src: storeLogo, alt: "", className: "h-full w-full object-cover", onError: () => setLogoError(true) })) : (_jsx(Layout, { className: "h-4 w-4 text-[#9ca3af]", strokeWidth: 2 })) }), _jsxs("div", { className: "min-w-0 max-w-[11rem]", children: [_jsx("p", { className: "truncate text-[13px] font-semibold leading-tight text-[#1b0029]", children: storeName || layoutName }), _jsx("p", { className: "truncate text-[11px] leading-tight text-[#7b8492]", children: layoutName })] })] })] }), _jsx("div", { className: "hidden min-w-0 flex-1 items-center justify-center px-1 md:flex md:px-4", children: showPageSwitcher ? (_jsxs("div", { className: "page-switcher-container relative", children: [_jsxs("button", { type: "button", onClick: () => setIsPageDropdownOpen((v) => !v), className: "flex max-w-[min(92vw,360px)] items-center gap-2.5 rounded-xl border border-[#e6e9ee] bg-white px-3.5 py-2.5 text-left shadow-[0_1px_2px_rgba(15,23,42,0.05)] transition-colors hover:border-[#d4dae3] hover:bg-[#fcfdff]", children: [_jsx("span", { className: "shrink-0 text-[#440066]", children: getPageIcon(activePage) }), _jsx("span", { className: "truncate text-[13px] font-semibold text-[#1f2937]", children: pages.find((p) => p.id === activePage)?.name || activePage }), _jsx(ChevronDown, { className: cn('ml-auto h-4 w-4 shrink-0 text-[#9aa3b2] transition-transform', isPageDropdownOpen && 'rotate-180'), strokeWidth: 2 })] }), _jsx(AnimatePresence, { children: isPageDropdownOpen && (_jsxs(motion.div, { initial: { opacity: 0, y: 6 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: 6 }, transition: { duration: 0.12 }, className: "absolute left-1/2 top-full z-[200] mt-1.5 w-[min(calc(100vw-24px),17rem)] -translate-x-1/2 rounded-xl border border-[#e6e9ee] bg-white py-1 shadow-[0_12px_24px_rgba(15,23,42,0.08)]", children: [_jsx("div", { className: "border-b border-[#f3f4f6] px-3.5 py-2.5", children: _jsx("span", { className: "text-[11px] font-semibold uppercase tracking-wide text-[#8a94a5]", children: "Pages" }) }), _jsx("div", { className: "max-h-[280px] overflow-y-auto py-1", children: pages.map((page) => (_jsxs("button", { type: "button", onClick: () => { onPageSwitch(page.id); setIsPageDropdownOpen(false); }, className: cn('flex w-full items-center gap-3 px-3.5 py-2.5 text-left text-[13px] transition-colors hover:bg-[#f8fafc]', activePage === page.id && 'bg-[#f5f0ff] font-medium text-[#440066] hover:bg-[#ede9ff]'), children: [_jsx("span", { className: activePage === page.id ? 'text-[#440066]' : 'text-[#9ca3af]', children: getPageIcon(page.id) }), _jsx("span", { className: "flex-1", children: page.name }), activePage === page.id && (_jsx(Check, { className: "h-4 w-4 shrink-0 text-[#440066]", strokeWidth: 2.5 }))] }, page.id))) })] })) })] })) : showPageContextCard ? (_jsxs("div", { className: "flex max-w-[min(92vw,400px)] items-center gap-2.5 rounded-lg border border-[#e8ecf2] bg-white px-3 py-1.5 shadow-[0_1px_2px_rgba(15,23,42,0.04)]", children: [_jsx("span", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-[#f7f3ff] text-[#440066]", children: getPageIcon(activePage) }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-[9px] font-semibold uppercase tracking-[0.07em] text-[#8a94a5]", children: interactionMode === 'preview' ? 'Previewing page' : 'Current page' }), _jsx("p", { className: "truncate text-[12px] font-semibold text-[#1f2937]", children: centerTemplateLabel ||
|
|
155
150
|
currentPageLabel ||
|
|
156
151
|
pages.find((p) => p.id === activePage)?.name ||
|
|
157
152
|
activePage })] })] })) : null }), _jsxs("div", { className: cn('ml-auto flex shrink-0 items-center', isMobileChrome ? 'gap-1.5' : 'gap-2'), children: [!isMobileChrome && (_jsx("div", { className: "hidden md:block", children: onInteractionModeChange && (_jsxs(Cluster, { children: [_jsx(Tooltip, { text: "Edit mode \u2014 click elements on the canvas to edit them", children: _jsxs("button", { type: "button", onClick: () => onInteractionModeChange('edit'), "aria-pressed": interactionMode === 'edit', "aria-label": "Edit mode", className: cn('flex h-8 items-center gap-1.5 rounded-lg px-3 text-[12px] font-medium transition-colors', interactionMode === 'edit'
|
|
158
153
|
? 'bg-[#440066] text-white shadow-sm'
|
|
159
154
|
: 'text-[#5b6470] hover:bg-[#f8fafc] hover:text-[#1f2937]'), children: [_jsx(Pencil, { className: cn('h-3.5 w-3.5 shrink-0', interactionMode === 'edit' && 'text-[#80FF73]'), strokeWidth: 2 }), _jsx("span", { className: "hidden min-[940px]:inline", children: "Edit" })] }) }), _jsx(Tooltip, { text: "Preview mode \u2014 browse your store as a visitor would", children: _jsxs("button", { type: "button", onClick: () => onInteractionModeChange('preview'), "aria-pressed": interactionMode === 'preview', "aria-label": "Preview mode", className: cn('flex h-8 items-center gap-1.5 rounded-lg px-3 text-[12px] font-medium transition-colors', interactionMode === 'preview'
|
|
160
155
|
? 'bg-[#440066] text-white shadow-sm'
|
|
161
|
-
: 'text-[#5b6470] hover:bg-[#f8fafc] hover:text-[#1f2937]'), children: [_jsx(Eye, { className: cn('h-3.5 w-3.5 shrink-0', interactionMode === 'preview' && 'text-[#80FF73]'), strokeWidth: 2 }), _jsx("span", { className: "hidden min-[940px]:inline", children: "Preview" })] }) })] })) })), !isMobileChrome && (_jsx("div", { className: "hidden md:block", children: _jsxs(Cluster, { children: [_jsx(Tooltip, { text: "Desktop view", children: _jsx(IconBtn, { onClick: () => onViewModeChange?.('desktop'), active: viewMode === 'desktop', "aria-pressed": viewMode === 'desktop', "aria-label": "Desktop view", children: _jsx(Monitor, { className: "h-4 w-4", strokeWidth: 2 }) }) }), _jsx(Tooltip, { text: "Tablet view", children: _jsx(IconBtn, { onClick: () => onViewModeChange?.('tablet'), active: viewMode === 'tablet', "aria-pressed": viewMode === 'tablet', "aria-label": "Tablet view", children: _jsx(Tablet, { className: "h-4 w-4", strokeWidth: 2 }) }) }), _jsx(Tooltip, { text: "Mobile view", children: _jsx(IconBtn, { onClick: () => onViewModeChange?.('mobile'), active: viewMode === 'mobile', "aria-pressed": viewMode === 'mobile', "aria-label": "Mobile view", children: _jsx(Smartphone, { className: "h-4 w-4", strokeWidth: 2 }) }) })] }) })), !isMobileChrome && (_jsx("div", { className: "hidden md:block", children:
|
|
156
|
+
: 'text-[#5b6470] hover:bg-[#f8fafc] hover:text-[#1f2937]'), children: [_jsx(Eye, { className: cn('h-3.5 w-3.5 shrink-0', interactionMode === 'preview' && 'text-[#80FF73]'), strokeWidth: 2 }), _jsx("span", { className: "hidden min-[940px]:inline", children: "Preview" })] }) })] })) })), !isMobileChrome && (_jsx("div", { className: "hidden md:block", children: _jsxs(Cluster, { children: [_jsx(Tooltip, { text: "Desktop view", children: _jsx(IconBtn, { onClick: () => onViewModeChange?.('desktop'), active: viewMode === 'desktop', "aria-pressed": viewMode === 'desktop', "aria-label": "Desktop view", children: _jsx(Monitor, { className: "h-4 w-4", strokeWidth: 2 }) }) }), _jsx(Tooltip, { text: "Tablet view", children: _jsx(IconBtn, { onClick: () => onViewModeChange?.('tablet'), active: viewMode === 'tablet', "aria-pressed": viewMode === 'tablet', "aria-label": "Tablet view", children: _jsx(Tablet, { className: "h-4 w-4", strokeWidth: 2 }) }) }), _jsx(Tooltip, { text: "Mobile view", children: _jsx(IconBtn, { onClick: () => onViewModeChange?.('mobile'), active: viewMode === 'mobile', "aria-pressed": viewMode === 'mobile', "aria-label": "Mobile view", children: _jsx(Smartphone, { className: "h-4 w-4", strokeWidth: 2 }) }) })] }) })), !isMobileChrome && (_jsx("div", { className: "hidden md:block", children: hasUtilityTools && (_jsxs(Cluster, { children: [onBackToSettings && (_jsx(Tooltip, { text: "Store settings", children: _jsx(IconBtn, { onClick: onBackToSettings, "aria-label": "Store settings", children: _jsx(Settings, { className: "h-4 w-4", strokeWidth: 2 }) }) })), onOpenAssets && (_jsx(Tooltip, { text: "Media library \u2014 browse and upload images", children: _jsx(IconBtn, { onClick: onOpenAssets, "aria-label": "Media library", children: _jsx(ImageIcon, { className: "h-4 w-4", strokeWidth: 2 }) }) })), onBackToTheme && (_jsx(Tooltip, { text: "Change template \u2014 switch to a different layout template", children: _jsx(IconBtn, { onClick: onBackToTheme, "aria-label": "Change template", children: _jsx(Palette, { className: "h-4 w-4", strokeWidth: 2 }) }) })), onGenerateAI && (onBackToSettings || onOpenAssets || onBackToTheme) && (_jsx(Divider, {})), onGenerateAI && (_jsx(Tooltip, { text: "AI assistant \u2014 generate and improve content with AI", children: _jsx(IconBtn, { id: "tour-ai-button", onClick: onGenerateAI, disabled: isGeneratingAI, "aria-label": "AI assistant", className: "text-[#440066] hover:bg-[#f5f0ff] hover:text-[#440066]", children: isGeneratingAI ? (_jsx("span", { className: "h-4 w-4 animate-spin rounded-full border-2 border-[#440066]/25 border-t-[#440066]" })) : (_jsx(Sparkles, { className: "h-4 w-4", strokeWidth: 2 })) }) }))] })) })), _jsxs("div", { className: cn('flex shrink-0 items-center', isMobileChrome ? 'gap-1.5' : 'gap-2 pl-1'), children: [_jsx(Tooltip, { text: isMobileChrome && draftStatusLabel
|
|
162
157
|
? draftStatusLabel
|
|
163
158
|
: 'Save your current changes as a draft (not yet live)', children: _jsxs("button", { type: "button", onClick: onSave, disabled: isSaving, "aria-label": draftStatusLabel ? `Save draft — ${draftStatusLabel}` : 'Save draft', className: cn('relative flex shrink-0 items-center gap-2 whitespace-nowrap rounded-xl border border-[#e6e9ee] bg-white text-[13px] font-semibold text-[#374151] shadow-[0_1px_2px_rgba(15,23,42,0.05)] transition-colors hover:border-[#d2d9e3] hover:bg-[#f8fafc] disabled:opacity-50', isMobileChrome ? 'h-9 px-2.5' : 'h-8 px-2 md:h-10 md:px-4'), children: [isMobileChrome && draftSaveStatus === 'dirty' && (_jsx("span", { className: "absolute -right-0.5 -top-0.5 h-2 w-2 rounded-full bg-amber-400 ring-2 ring-white", "aria-hidden": true })), isSaving ? (_jsx("span", { className: "h-3.5 w-3.5 animate-spin rounded-full border-2 border-[#d1d5db] border-t-[#6b7280]" })) : (_jsx(Save, { className: "h-3.5 w-3.5", strokeWidth: 2.5 })), _jsx("span", { className: isMobileChrome ? 'sr-only' : 'hidden md:inline', children: "Save draft" })] }) }), _jsx(Tooltip, { text: publishDisabled
|
|
164
159
|
? 'No pending changes to publish'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IframePreview.d.ts","sourceRoot":"","sources":["../../../src/editor/shared/IframePreview.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgF,MAAM,OAAO,CAAC;AACrG,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAIzD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AAC1F,OAAO,EAEL,KAAK,WAAW,EAEjB,MAAM,oBAAoB,CAAC;AAE5B,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC1C,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,6FAA6F;IAC7F,YAAY,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACvF,uEAAuE;IACvE,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,mEAAmE;IACnE,cAAc,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAClF,wEAAwE;IACxE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sFAAsF;IACtF,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"IframePreview.d.ts","sourceRoot":"","sources":["../../../src/editor/shared/IframePreview.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgF,MAAM,OAAO,CAAC;AACrG,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAIzD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AAC1F,OAAO,EAEL,KAAK,WAAW,EAEjB,MAAM,oBAAoB,CAAC;AAE5B,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC1C,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,6FAA6F;IAC7F,YAAY,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACvF,uEAAuE;IACvE,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,mEAAmE;IACnE,cAAc,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAClF,wEAAwE;IACxE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sFAAsF;IACtF,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAgBD,eAAO,MAAM,aAAa,qGA+UxB,CAAC"}
|
|
@@ -6,26 +6,41 @@ import { previewPageIdToRoute } from '../../preview/canvas/preview-route.js';
|
|
|
6
6
|
import { PREVIEW_MSG } from '../../preview/canvas/preview-messages.js';
|
|
7
7
|
import { DESKTOP_PREVIEW_WIDTH, resolvePreviewScale, } from './preview-viewport.js';
|
|
8
8
|
export { DESKTOP_PREVIEW_WIDTH } from './preview-viewport.js';
|
|
9
|
+
function resetPreviewSyncRefs(refs) {
|
|
10
|
+
refs.lastSentConfig.current = null;
|
|
11
|
+
refs.lastPostedRoute.current = null;
|
|
12
|
+
refs.lastPostedViewMode.current = null;
|
|
13
|
+
refs.lastPostedInteraction.current = null;
|
|
14
|
+
refs.lastPostedFocus.current = null;
|
|
15
|
+
}
|
|
9
16
|
export const IframePreview = forwardRef(function IframePreview({ layoutId, config, activePageId, viewMode, selectedSection, focusedField = null, interactionMode = 'edit', slideIndexSync = null, flushRequestId = 0, previewZoom = 'fit', desktopCanvasWidth = DESKTOP_PREVIEW_WIDTH, className = '', }, ref) {
|
|
10
17
|
const iframeRef = useRef(null);
|
|
11
18
|
const viewportContainerRef = useRef(null);
|
|
12
19
|
const [isReady, setIsReady] = useState(false);
|
|
13
20
|
const [containerWidth, setContainerWidth] = useState(0);
|
|
14
21
|
const route = useMemo(() => previewPageIdToRoute(layoutId, activePageId, config), [layoutId, activePageId, config]);
|
|
22
|
+
const lastSentConfigRef = useRef(null);
|
|
23
|
+
const lastPostedRouteRef = useRef(null);
|
|
24
|
+
const lastPostedViewModeRef = useRef(null);
|
|
25
|
+
const lastPostedInteractionRef = useRef(null);
|
|
26
|
+
const lastPostedFocusRef = useRef(null);
|
|
27
|
+
const requestRef = useRef(null);
|
|
15
28
|
useEffect(() => {
|
|
16
29
|
const handleMessage = (event) => {
|
|
17
|
-
if (event.data?.type
|
|
18
|
-
|
|
19
|
-
|
|
30
|
+
if (event.data?.type !== 'PREVIEW_READY')
|
|
31
|
+
return;
|
|
32
|
+
resetPreviewSyncRefs({
|
|
33
|
+
lastSentConfig: lastSentConfigRef,
|
|
34
|
+
lastPostedRoute: lastPostedRouteRef,
|
|
35
|
+
lastPostedViewMode: lastPostedViewModeRef,
|
|
36
|
+
lastPostedInteraction: lastPostedInteractionRef,
|
|
37
|
+
lastPostedFocus: lastPostedFocusRef,
|
|
38
|
+
});
|
|
39
|
+
setIsReady(true);
|
|
20
40
|
};
|
|
21
41
|
window.addEventListener('message', handleMessage);
|
|
22
42
|
return () => window.removeEventListener('message', handleMessage);
|
|
23
43
|
}, []);
|
|
24
|
-
const lastSentConfigRef = useRef(null);
|
|
25
|
-
const lastPostedRouteRef = useRef(null);
|
|
26
|
-
const lastPostedViewModeRef = useRef(null);
|
|
27
|
-
const lastPostedInteractionRef = useRef(null);
|
|
28
|
-
const requestRef = useRef(null);
|
|
29
44
|
useEffect(() => {
|
|
30
45
|
if (isReady && iframeRef.current?.contentWindow) {
|
|
31
46
|
if (requestRef.current) {
|
|
@@ -77,7 +92,6 @@ export const IframePreview = forwardRef(function IframePreview({ layoutId, confi
|
|
|
77
92
|
iframeRef.current.contentWindow.postMessage({ type: 'SECTION_SELECTED_SYNC', section: selectedSection }, '*');
|
|
78
93
|
}
|
|
79
94
|
}, [selectedSection, isReady]);
|
|
80
|
-
const lastPostedFocusRef = useRef(null);
|
|
81
95
|
useEffect(() => {
|
|
82
96
|
if (!isReady || !iframeRef.current?.contentWindow)
|
|
83
97
|
return;
|
|
@@ -149,11 +163,13 @@ export const IframePreview = forwardRef(function IframePreview({ layoutId, confi
|
|
|
149
163
|
}, [layoutId, config?.id, config?.slug]);
|
|
150
164
|
useEffect(() => {
|
|
151
165
|
setIsReady(false);
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
166
|
+
resetPreviewSyncRefs({
|
|
167
|
+
lastSentConfig: lastSentConfigRef,
|
|
168
|
+
lastPostedRoute: lastPostedRouteRef,
|
|
169
|
+
lastPostedViewMode: lastPostedViewModeRef,
|
|
170
|
+
lastPostedInteraction: lastPostedInteractionRef,
|
|
171
|
+
lastPostedFocus: lastPostedFocusRef,
|
|
172
|
+
});
|
|
157
173
|
}, [previewUrl]);
|
|
158
174
|
useEffect(() => {
|
|
159
175
|
if (viewMode !== 'desktop')
|
|
@@ -194,6 +210,7 @@ export const IframePreview = forwardRef(function IframePreview({ layoutId, confi
|
|
|
194
210
|
return { width: '100%', height: '100%', rounded: '', border: '' };
|
|
195
211
|
}
|
|
196
212
|
}, [viewMode]);
|
|
213
|
+
const isDesktop = viewMode === 'desktop';
|
|
197
214
|
const iframeNode = (_jsxs(_Fragment, { children: [!isReady && (_jsx("div", { className: "absolute inset-0 z-10 flex items-center justify-center rounded-[inherit] bg-white", children: _jsxs("div", { className: "flex flex-col items-center gap-3", children: [_jsx("div", { className: "h-8 w-8 animate-spin rounded-full border-[3px] border-[#F7F5F0] border-t-[#440066]" }), _jsx("p", { className: "text-[11px] font-medium text-[#1b0029]/70", children: "Loading preview\u2026" })] }) })), _jsx("iframe", { ref: iframeRef, src: previewUrl, className: "block h-full w-full rounded-[inherit] border-none", title: "Layout Preview", sandbox: "allow-scripts allow-same-origin allow-forms allow-modals allow-popups allow-popups-to-escape-sandbox", style: {
|
|
198
215
|
width: '100%',
|
|
199
216
|
height: '100%',
|
|
@@ -201,17 +218,24 @@ export const IframePreview = forwardRef(function IframePreview({ layoutId, confi
|
|
|
201
218
|
margin: 0,
|
|
202
219
|
padding: 0,
|
|
203
220
|
} })] }));
|
|
204
|
-
|
|
205
|
-
|
|
221
|
+
return (_jsx("div", { ref: viewportContainerRef, className: `relative h-full w-full ${isDesktop
|
|
222
|
+
? 'overflow-auto bg-[#e2e4e7] p-3 md:p-4'
|
|
223
|
+
: 'flex items-start justify-center bg-[#dcdcde] p-4 md:p-8'} ${className}`, style: isDesktop ? { WebkitOverflowScrolling: 'touch' } : undefined, children: _jsx("div", { className: isDesktop
|
|
224
|
+
? 'flex min-h-full w-full justify-center py-1'
|
|
225
|
+
: `flex flex-col overflow-hidden bg-white shadow-2xl transition-all duration-500 ease-in-out ${deviceDimensions.rounded} ${deviceDimensions.border} border-[#c3c4c7]`, style: isDesktop
|
|
226
|
+
? undefined
|
|
227
|
+
: {
|
|
228
|
+
width: `${deviceDimensions.width}px`,
|
|
229
|
+
height: `${deviceDimensions.height}px`,
|
|
230
|
+
}, children: _jsx("div", { className: isDesktop
|
|
231
|
+
? 'relative shrink-0 overflow-hidden rounded-lg bg-white shadow-[0_1px_2px_rgba(15,23,42,0.04),0_12px_32px_-8px_rgba(15,23,42,0.1)] transition-transform duration-200 ease-out'
|
|
232
|
+
: 'relative min-h-0 flex-1 overflow-hidden bg-white', style: isDesktop
|
|
233
|
+
? {
|
|
206
234
|
width: desktopCanvasWidth,
|
|
207
235
|
height: scaledDesktopHeight,
|
|
208
236
|
minHeight: 480,
|
|
209
237
|
transform: `scale(${desktopScale})`,
|
|
210
238
|
transformOrigin: 'top center',
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
return (_jsx("div", { className: `relative flex h-full w-full items-start justify-center bg-[#dcdcde] p-4 md:p-8 ${className}`, children: _jsx("div", { className: `flex flex-col overflow-hidden bg-white shadow-2xl transition-all duration-500 ease-in-out ${deviceDimensions.rounded} ${deviceDimensions.border} border-[#c3c4c7]`, style: {
|
|
214
|
-
width: `${deviceDimensions.width}px`,
|
|
215
|
-
height: `${deviceDimensions.height}px`,
|
|
216
|
-
}, children: _jsx("div", { className: "relative min-h-0 flex-1 overflow-hidden bg-white", children: iframeNode }) }) }));
|
|
239
|
+
}
|
|
240
|
+
: undefined, children: _jsx("div", { className: "relative h-full w-full overflow-hidden rounded-lg", children: iframeNode }) }) }) }));
|
|
217
241
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-payaza-checkout.d.ts","sourceRoot":"","sources":["../../src/hooks/use-payaza-checkout.ts"],"names":[],"mappings":"AAGA,OAAO,EAA0B,oBAAoB,EAAE,sBAAsB,EAA6B,MAAM,uBAAuB,CAAC;AAGxI,UAAU,wBAAwB;IAChC,2FAA2F;IAC3F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACvD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,SAAc,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,wBAAwB;uBAiBzE,IAAI,CAAC,oBAAoB,EAAE,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC;;;
|
|
1
|
+
{"version":3,"file":"use-payaza-checkout.d.ts","sourceRoot":"","sources":["../../src/hooks/use-payaza-checkout.ts"],"names":[],"mappings":"AAGA,OAAO,EAA0B,oBAAoB,EAAE,sBAAsB,EAA6B,MAAM,uBAAuB,CAAC;AAGxI,UAAU,wBAAwB;IAChC,2FAA2F;IAC3F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACvD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,SAAc,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,wBAAwB;uBAiBzE,IAAI,CAAC,oBAAoB,EAAE,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC;;;EAkHhG"}
|
|
@@ -42,7 +42,6 @@ export function usePayazaCheckout({ publicKey = '', onSuccess, onError, onClose
|
|
|
42
42
|
const setLoadingTimeout = () => {
|
|
43
43
|
timeoutRef.current = setTimeout(() => {
|
|
44
44
|
if (!callbackFired && mountedRef.current) {
|
|
45
|
-
console.warn('[Payaza] Timeout: checkout did not complete within 45 seconds');
|
|
46
45
|
setIsLoading(false);
|
|
47
46
|
setError('Payment popup may not have opened. Please try again.');
|
|
48
47
|
onError?.('Payment popup may not have opened. Please try again.');
|
|
@@ -60,7 +59,6 @@ export function usePayazaCheckout({ publicKey = '', onSuccess, onError, onClose
|
|
|
60
59
|
clearLoadingWithTimeout();
|
|
61
60
|
if (config.orderId) {
|
|
62
61
|
void orderService.markPaymentInitiated(config.orderId).catch((err) => {
|
|
63
|
-
console.warn('[Payaza] markPaymentInitiated failed:', err);
|
|
64
62
|
});
|
|
65
63
|
}
|
|
66
64
|
if (mountedRef.current) {
|
|
@@ -10,17 +10,33 @@ export type BookingAboutStatItem = {
|
|
|
10
10
|
label: string;
|
|
11
11
|
};
|
|
12
12
|
export declare const BOOKING_DEFAULT_ABOUT_VALUES: BookingAboutValueItem[];
|
|
13
|
+
export declare const CLOTHING_DEFAULT_ABOUT_VALUES: BookingAboutValueItem[];
|
|
14
|
+
export declare const FOOD_DEFAULT_ABOUT_VALUES: BookingAboutValueItem[];
|
|
15
|
+
export declare const CLOTHING_MINIMAL_DEFAULT_ABOUT_VALUES: BookingAboutValueItem[];
|
|
16
|
+
export declare const CLOTHING_DEFAULT_ABOUT_STATS: BookingAboutStatItem[];
|
|
13
17
|
export declare const BOOKING_DEFAULT_ABOUT_STATS: BookingAboutStatItem[];
|
|
18
|
+
export declare const FOOD_DEFAULT_ABOUT_STATS: BookingAboutStatItem[];
|
|
19
|
+
export declare const CLOTHING_MINIMAL_DEFAULT_ABOUT_STATS: BookingAboutStatItem[];
|
|
14
20
|
export declare const BOOKING_DEFAULT_STORY_IMAGE = "https://images.unsplash.com/photo-1522202176988-66273c2fd55f?q=80&w=2071&auto=format&fit=crop";
|
|
15
21
|
/** Merge saved array items with schema defaults by index / id — keeps all default slots. */
|
|
16
22
|
export declare function mergeBookingAboutArrayItems<T extends Record<string, unknown>>(defaults: T[], actual: unknown[] | undefined): T[];
|
|
17
23
|
export declare function resolveBookingAboutValues(config: {
|
|
18
24
|
items?: unknown[];
|
|
19
25
|
} | undefined, fallbackDefaults?: BookingAboutValueItem[]): BookingAboutValueItem[];
|
|
26
|
+
export declare function resolveAboutPageValueItems(layoutConfig: {
|
|
27
|
+
pages?: {
|
|
28
|
+
about?: Record<string, unknown>;
|
|
29
|
+
};
|
|
30
|
+
sections?: Record<string, unknown>;
|
|
31
|
+
} | undefined, fallbackDefaults: BookingAboutValueItem[]): BookingAboutValueItem[];
|
|
20
32
|
export declare function resolveBookingAboutStats(config: {
|
|
21
33
|
items?: unknown[];
|
|
22
34
|
} | undefined, options?: {
|
|
23
35
|
servicesCount?: number;
|
|
24
36
|
}, fallbackDefaults?: BookingAboutStatItem[]): BookingAboutStatItem[];
|
|
25
37
|
export declare function mergeBookingAboutItemsSection(actual: Record<string, unknown>, requirement: Record<string, unknown>, defaultItems: Record<string, unknown>[]): Record<string, unknown>;
|
|
38
|
+
/** Flat / layout-specific keys → grouped visit / email / hours cards for about contact sections. */
|
|
39
|
+
export declare function normalizeAboutContactInfoCards(section: Record<string, unknown> | undefined): Record<string, unknown>;
|
|
40
|
+
/** @deprecated Use normalizeAboutContactInfoCards */
|
|
41
|
+
export declare const normalizeClothingAboutContactInfo: typeof normalizeAboutContactInfoCards;
|
|
26
42
|
//# sourceMappingURL=booking-about-defaults.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"booking-about-defaults.d.ts","sourceRoot":"","sources":["../../../../src/layouts/booking/components/booking-about-defaults.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,qBAAqB,GAAG;IAClC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,4BAA4B,EAAE,qBAAqB,EAyB/D,CAAC;AAEF,eAAO,MAAM,2BAA2B,EAAE,oBAAoB,EAK7D,CAAC;AAEF,eAAO,MAAM,2BAA2B,kGACyD,CAAC;AAkBlG,4FAA4F;AAC5F,wBAAgB,2BAA2B,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3E,QAAQ,EAAE,CAAC,EAAE,EACb,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS,GAC5B,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"booking-about-defaults.d.ts","sourceRoot":"","sources":["../../../../src/layouts/booking/components/booking-about-defaults.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,qBAAqB,GAAG;IAClC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,4BAA4B,EAAE,qBAAqB,EAyB/D,CAAC;AAEF,eAAO,MAAM,6BAA6B,EAAE,qBAAqB,EAahE,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,qBAAqB,EAyB5D,CAAC;AAEF,eAAO,MAAM,qCAAqC,EAAE,qBAAqB,EAyBxE,CAAC;AAEF,eAAO,MAAM,4BAA4B,EAAE,oBAAoB,EAK9D,CAAC;AAEF,eAAO,MAAM,2BAA2B,EAAE,oBAAoB,EAK7D,CAAC;AAEF,eAAO,MAAM,wBAAwB,EAAE,oBAAoB,EAK1D,CAAC;AAEF,eAAO,MAAM,oCAAoC,EAAE,oBAAoB,EAKtE,CAAC;AAEF,eAAO,MAAM,2BAA2B,kGACyD,CAAC;AAkBlG,4FAA4F;AAC5F,wBAAgB,2BAA2B,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3E,QAAQ,EAAE,CAAC,EAAE,EACb,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS,GAC5B,CAAC,EAAE,CAmCL;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,EAAE,CAAA;CAAE,GAAG,SAAS,EACzC,gBAAgB,GAAE,qBAAqB,EAAiC,GACvE,qBAAqB,EAAE,CAEzB;AAED,wBAAgB,0BAA0B,CACxC,YAAY,EACR;IACE,KAAK,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC,GACD,SAAS,EACb,gBAAgB,EAAE,qBAAqB,EAAE,GACxC,qBAAqB,EAAE,CAgBzB;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,EAAE,CAAA;CAAE,GAAG,SAAS,EACzC,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,EACpC,gBAAgB,GAAE,oBAAoB,EAAgC,GACrE,oBAAoB,EAAE,CAYxB;AAED,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GACtC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAWzB;AAiBD,oGAAoG;AACpG,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAC3C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA6DzB;AAED,qDAAqD;AACrD,eAAO,MAAM,iCAAiC,uCAAiC,CAAC"}
|
|
@@ -24,12 +24,96 @@ export const BOOKING_DEFAULT_ABOUT_VALUES = [
|
|
|
24
24
|
description: 'We use only the best tools and products for our services.',
|
|
25
25
|
},
|
|
26
26
|
];
|
|
27
|
+
export const CLOTHING_DEFAULT_ABOUT_VALUES = [
|
|
28
|
+
{
|
|
29
|
+
id: 'about-v1',
|
|
30
|
+
icon: 'Award',
|
|
31
|
+
title: 'Quality First',
|
|
32
|
+
description: 'We never compromise on the quality of our products and services.',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 'about-v2',
|
|
36
|
+
icon: 'Users',
|
|
37
|
+
title: 'Customer Focused',
|
|
38
|
+
description: "Your satisfaction is our top priority. We're here to help.",
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
export const FOOD_DEFAULT_ABOUT_VALUES = [
|
|
42
|
+
{
|
|
43
|
+
id: 'about-v1',
|
|
44
|
+
icon: 'Award',
|
|
45
|
+
title: 'Fresh Ingredients',
|
|
46
|
+
description: 'We source the finest local ingredients for every dish we prepare.',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: 'about-v2',
|
|
50
|
+
icon: 'Users',
|
|
51
|
+
title: 'Community Driven',
|
|
52
|
+
description: "We're proud to be a local favorite and give back to our community.",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: 'about-v3',
|
|
56
|
+
icon: 'Heart',
|
|
57
|
+
title: 'Made with Love',
|
|
58
|
+
description: 'Every meal is prepared with passion and attention to detail.',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: 'about-v4',
|
|
62
|
+
icon: 'Leaf',
|
|
63
|
+
title: 'Sustainability',
|
|
64
|
+
description: 'Committed to eco-friendly packaging and responsible sourcing.',
|
|
65
|
+
},
|
|
66
|
+
];
|
|
67
|
+
export const CLOTHING_MINIMAL_DEFAULT_ABOUT_VALUES = [
|
|
68
|
+
{
|
|
69
|
+
id: 'about-v1',
|
|
70
|
+
icon: 'Award',
|
|
71
|
+
title: 'Pure Materials',
|
|
72
|
+
description: 'We use only the highest quality organic and sustainable fabrics.',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
id: 'about-v2',
|
|
76
|
+
icon: 'Users',
|
|
77
|
+
title: 'Inclusive Design',
|
|
78
|
+
description: 'Fashion designed for every body and every style.',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: 'about-v3',
|
|
82
|
+
icon: 'Heart',
|
|
83
|
+
title: 'Ethical Craft',
|
|
84
|
+
description: 'Our garments are made in ethical workshops with fair wages.',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
id: 'about-v4',
|
|
88
|
+
icon: 'Leaf',
|
|
89
|
+
title: 'Eco-Conscious',
|
|
90
|
+
description: 'Minimal waste production and plastic-free packaging.',
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
export const CLOTHING_DEFAULT_ABOUT_STATS = [
|
|
94
|
+
{ id: 'clothing-s1', value: '20k+', label: 'Style Lovers' },
|
|
95
|
+
{ id: 'clothing-s2', value: '100+', label: 'New Arrivals' },
|
|
96
|
+
{ id: 'clothing-s3', value: '50+', label: 'Global Shipping' },
|
|
97
|
+
{ id: 'clothing-s4', value: '15+', label: 'Design Experts' },
|
|
98
|
+
];
|
|
27
99
|
export const BOOKING_DEFAULT_ABOUT_STATS = [
|
|
28
100
|
{ id: 'about-s1', value: '8k+', label: 'Bookings Completed' },
|
|
29
101
|
{ id: 'about-s2', value: '15+', label: 'Expert Staff' },
|
|
30
102
|
{ id: 'about-s3', value: '20+', label: 'Services Offered' },
|
|
31
103
|
{ id: 'about-s4', value: '10+', label: 'Years Experience' },
|
|
32
104
|
];
|
|
105
|
+
export const FOOD_DEFAULT_ABOUT_STATS = [
|
|
106
|
+
{ id: 'food-s1', value: '15k+', label: 'Happy Foodies' },
|
|
107
|
+
{ id: 'food-s2', value: '40+', label: 'Menu Items' },
|
|
108
|
+
{ id: 'food-s3', value: '8+', label: 'Years of Cooking' },
|
|
109
|
+
{ id: 'food-s4', value: '12+', label: 'Expert Chefs' },
|
|
110
|
+
];
|
|
111
|
+
export const CLOTHING_MINIMAL_DEFAULT_ABOUT_STATS = [
|
|
112
|
+
{ id: 'minimal-s1', value: '12k+', label: 'Happy Shoppers' },
|
|
113
|
+
{ id: 'minimal-s2', value: '60+', label: 'Active Designs' },
|
|
114
|
+
{ id: 'minimal-s3', value: '30+', label: 'Countries Served' },
|
|
115
|
+
{ id: 'minimal-s4', value: '100%', label: 'Eco Impact' },
|
|
116
|
+
];
|
|
33
117
|
export const BOOKING_DEFAULT_STORY_IMAGE = 'https://images.unsplash.com/photo-1522202176988-66273c2fd55f?q=80&w=2071&auto=format&fit=crop';
|
|
34
118
|
function mergeRecordPreferFilled(defaults, actual) {
|
|
35
119
|
if (!defaults)
|
|
@@ -50,7 +134,11 @@ export function mergeBookingAboutArrayItems(defaults, actual) {
|
|
|
50
134
|
return defaults.map((item) => ({ ...item }));
|
|
51
135
|
}
|
|
52
136
|
const defaultsById = new Map(defaults.filter((item) => item.id).map((item) => [String(item.id), item]));
|
|
53
|
-
const
|
|
137
|
+
const slotCount = Math.max(defaults.length, actual.length);
|
|
138
|
+
const result = [];
|
|
139
|
+
for (let i = 0; i < slotCount; i++) {
|
|
140
|
+
result.push(i < defaults.length ? { ...defaults[i] } : {});
|
|
141
|
+
}
|
|
54
142
|
actual.forEach((raw, index) => {
|
|
55
143
|
if (!raw || typeof raw !== 'object')
|
|
56
144
|
return;
|
|
@@ -75,6 +163,21 @@ export function mergeBookingAboutArrayItems(defaults, actual) {
|
|
|
75
163
|
export function resolveBookingAboutValues(config, fallbackDefaults = BOOKING_DEFAULT_ABOUT_VALUES) {
|
|
76
164
|
return mergeBookingAboutArrayItems(fallbackDefaults, config?.items);
|
|
77
165
|
}
|
|
166
|
+
export function resolveAboutPageValueItems(layoutConfig, fallbackDefaults) {
|
|
167
|
+
const about = layoutConfig?.pages?.about;
|
|
168
|
+
const aboutContent = about?.aboutContent;
|
|
169
|
+
const embeddedValues = aboutContent && Array.isArray(aboutContent.values)
|
|
170
|
+
? {
|
|
171
|
+
show: aboutContent.show,
|
|
172
|
+
items: aboutContent.values,
|
|
173
|
+
}
|
|
174
|
+
: undefined;
|
|
175
|
+
const valuesSection = about?.values;
|
|
176
|
+
const valuesConfig = valuesSection ||
|
|
177
|
+
embeddedValues ||
|
|
178
|
+
layoutConfig?.sections?.values;
|
|
179
|
+
return resolveBookingAboutValues(valuesConfig, fallbackDefaults);
|
|
180
|
+
}
|
|
78
181
|
export function resolveBookingAboutStats(config, options, fallbackDefaults = BOOKING_DEFAULT_ABOUT_STATS) {
|
|
79
182
|
const defaults = fallbackDefaults.map((item) => ({ ...item }));
|
|
80
183
|
if (options?.servicesCount && options.servicesCount > 0) {
|
|
@@ -97,3 +200,70 @@ export function mergeBookingAboutItemsSection(actual, requirement, defaultItems)
|
|
|
97
200
|
items: mergeBookingAboutArrayItems((reqItems.length > 0 ? reqItems : defaultItems), actualItems),
|
|
98
201
|
};
|
|
99
202
|
}
|
|
203
|
+
const DEFAULT_CONTACT_INTRO = "Have questions? We'd love to hear from you. Reach out to our team via email, phone, or visit us at our store.";
|
|
204
|
+
function contactHoursFromLegacy(section, hours) {
|
|
205
|
+
if (typeof hours.hours === 'string' && hours.hours.trim()) {
|
|
206
|
+
return hours.hours;
|
|
207
|
+
}
|
|
208
|
+
if (typeof section.hours === 'string' && section.hours.trim()) {
|
|
209
|
+
return section.hours;
|
|
210
|
+
}
|
|
211
|
+
const line1 = section.hoursLine1;
|
|
212
|
+
const line2 = section.hoursLine2;
|
|
213
|
+
return [line1, line2].filter((line) => typeof line === 'string' && line.trim()).join('\n');
|
|
214
|
+
}
|
|
215
|
+
/** Flat / layout-specific keys → grouped visit / email / hours cards for about contact sections. */
|
|
216
|
+
export function normalizeAboutContactInfoCards(section) {
|
|
217
|
+
if (!section || typeof section !== 'object') {
|
|
218
|
+
return {};
|
|
219
|
+
}
|
|
220
|
+
const s = { ...section };
|
|
221
|
+
s.title =
|
|
222
|
+
(typeof s.title === 'string' && s.title.trim()) ||
|
|
223
|
+
(typeof s.sectionTitle === 'string' && s.sectionTitle.trim()) ||
|
|
224
|
+
'Get in Touch';
|
|
225
|
+
s.description =
|
|
226
|
+
(typeof s.description === 'string' && s.description.trim()) ||
|
|
227
|
+
(typeof s.sectionSubtitle === 'string' && s.sectionSubtitle.trim()) ||
|
|
228
|
+
DEFAULT_CONTACT_INTRO;
|
|
229
|
+
const visit = s.visitCard && typeof s.visitCard === 'object'
|
|
230
|
+
? { ...s.visitCard }
|
|
231
|
+
: {};
|
|
232
|
+
s.visitCard = {
|
|
233
|
+
title: visit.title ??
|
|
234
|
+
s.visitTitle ??
|
|
235
|
+
s.visitLabel ??
|
|
236
|
+
'Visit Us',
|
|
237
|
+
icon: visit.icon ?? s.visitIcon ?? 'MapPin',
|
|
238
|
+
address: visit.address ??
|
|
239
|
+
s.address ??
|
|
240
|
+
s.visitAddress ??
|
|
241
|
+
'',
|
|
242
|
+
};
|
|
243
|
+
const email = s.emailCard && typeof s.emailCard === 'object'
|
|
244
|
+
? { ...s.emailCard }
|
|
245
|
+
: {};
|
|
246
|
+
s.emailCard = {
|
|
247
|
+
title: email.title ?? s.emailTitle ?? s.emailLabel ?? 'Email Us',
|
|
248
|
+
icon: email.icon ?? s.emailIcon ?? 'Mail',
|
|
249
|
+
email: email.email ?? s.email ?? s.email1 ?? '',
|
|
250
|
+
emailSecondary: email.emailSecondary ?? s.emailSecondary ?? s.email2 ?? '',
|
|
251
|
+
phone: email.phone ?? s.phone ?? '',
|
|
252
|
+
ctaLabel: email.ctaLabel ??
|
|
253
|
+
s.emailCTALabel ??
|
|
254
|
+
s.ctaLabel ??
|
|
255
|
+
'Send a message',
|
|
256
|
+
ctaLink: email.ctaLink ?? s.emailLink ?? s.ctaLink ?? '/contact',
|
|
257
|
+
};
|
|
258
|
+
const hours = s.hoursCard && typeof s.hoursCard === 'object'
|
|
259
|
+
? { ...s.hoursCard }
|
|
260
|
+
: {};
|
|
261
|
+
s.hoursCard = {
|
|
262
|
+
title: hours.title ?? s.hoursTitle ?? s.hoursLabel ?? 'Opening Hours',
|
|
263
|
+
icon: hours.icon ?? s.hoursIcon ?? 'Clock',
|
|
264
|
+
hours: contactHoursFromLegacy(s, hours),
|
|
265
|
+
};
|
|
266
|
+
return s;
|
|
267
|
+
}
|
|
268
|
+
/** @deprecated Use normalizeAboutContactInfoCards */
|
|
269
|
+
export const normalizeClothingAboutContactInfo = normalizeAboutContactInfoCards;
|
|
@@ -9,9 +9,9 @@ export declare const BOOKING_DEFAULT_FOOTER_TAGLINE = "Experience the best in qu
|
|
|
9
9
|
export declare function resolveBookingFooterMainLinks(config: {
|
|
10
10
|
mainLinks?: unknown[];
|
|
11
11
|
} | undefined, storeConfig: Pick<StoreConfig, 'layout' | 'type' | 'navigation'>): BookingFooterLink[];
|
|
12
|
-
export declare function resolveBookingFooterSupportLinks(
|
|
12
|
+
export declare function resolveBookingFooterSupportLinks(_config: {
|
|
13
13
|
supportLinks?: unknown[];
|
|
14
|
-
} | undefined,
|
|
14
|
+
} | undefined, _storeConfig: Pick<StoreConfig, 'layout' | 'type' | 'pageFeatures'>): BookingFooterLink[];
|
|
15
15
|
export declare function resolveBookingFooterPrimaryColumnTitle(config: {
|
|
16
16
|
primaryColumnTitle?: string;
|
|
17
17
|
} | undefined, storeConfig: Pick<StoreConfig, 'layout' | 'type'>): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"booking-footer-defaults.d.ts","sourceRoot":"","sources":["../../../../src/layouts/booking/components/booking-footer-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,wCAAwC,CAAC;AAGhD,MAAM,MAAM,iBAAiB,GAAG,aAAa,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE,eAAO,MAAM,iCAAiC,EAAE,iBAAiB,EAKhE,CAAC;AAEF,eAAO,MAAM,oCAAoC,EAAE,iBAAiB,EAInE,CAAC;AAEF,eAAO,MAAM,8BAA8B,uHAC2E,CAAC;AAEvH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,EAAE,CAAA;CAAE,GAAG,SAAS,EAC7C,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,MAAM,GAAG,YAAY,CAAC,GAC/D,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"booking-footer-defaults.d.ts","sourceRoot":"","sources":["../../../../src/layouts/booking/components/booking-footer-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,wCAAwC,CAAC;AAGhD,MAAM,MAAM,iBAAiB,GAAG,aAAa,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE,eAAO,MAAM,iCAAiC,EAAE,iBAAiB,EAKhE,CAAC;AAEF,eAAO,MAAM,oCAAoC,EAAE,iBAAiB,EAInE,CAAC;AAEF,eAAO,MAAM,8BAA8B,uHAC2E,CAAC;AAEvH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,EAAE,CAAA;CAAE,GAAG,SAAS,EAC7C,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,MAAM,GAAG,YAAY,CAAC,GAC/D,iBAAiB,EAAE,CAuBrB;AAED,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE;IAAE,YAAY,CAAC,EAAE,OAAO,EAAE,CAAA;CAAE,GAAG,SAAS,EACjD,YAAY,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,MAAM,GAAG,cAAc,CAAC,GAClE,iBAAiB,EAAE,CAErB;AAED,wBAAgB,sCAAsC,CACpD,MAAM,EAAE;IAAE,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EACnD,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,MAAM,CAAC,GAChD,MAAM,CAER;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAkBzB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getDefaultFooterMainLinks,
|
|
1
|
+
import { getDefaultFooterMainLinks, getFooterPrimaryColumnTitle, withoutContactPageNavLinks, } from '../../../lib/utils/footer-nav-defaults.js';
|
|
2
2
|
import { mergeBookingAboutArrayItems } from './booking-about-defaults.js';
|
|
3
3
|
export const BOOKING_DEFAULT_FOOTER_MAIN_LINKS = [
|
|
4
4
|
{ id: 'f-m1', label: 'Services', href: '/services' },
|
|
@@ -26,14 +26,11 @@ export function resolveBookingFooterMainLinks(config, storeConfig) {
|
|
|
26
26
|
const defaults = Array.isArray(config?.mainLinks) && config.mainLinks.length > 0
|
|
27
27
|
? config.mainLinks
|
|
28
28
|
: navLinks;
|
|
29
|
-
|
|
29
|
+
const merged = mergeBookingAboutArrayItems(defaults.length > 0 ? defaults : BOOKING_DEFAULT_FOOTER_MAIN_LINKS, config?.mainLinks);
|
|
30
|
+
return withoutContactPageNavLinks(merged);
|
|
30
31
|
}
|
|
31
|
-
export function resolveBookingFooterSupportLinks(
|
|
32
|
-
|
|
33
|
-
id: `def-s-${index}`,
|
|
34
|
-
...link,
|
|
35
|
-
}));
|
|
36
|
-
return mergeBookingAboutArrayItems(defaults.length > 0 ? defaults : BOOKING_DEFAULT_FOOTER_SUPPORT_LINKS, config?.supportLinks);
|
|
32
|
+
export function resolveBookingFooterSupportLinks(_config, _storeConfig) {
|
|
33
|
+
return [];
|
|
37
34
|
}
|
|
38
35
|
export function resolveBookingFooterPrimaryColumnTitle(config, storeConfig) {
|
|
39
36
|
return config?.primaryColumnTitle?.trim() || getFooterPrimaryColumnTitle(storeConfig);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AboutPage.d.ts","sourceRoot":"","sources":["../../../../src/layouts/booking/pages/AboutPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AboutPage.d.ts","sourceRoot":"","sources":["../../../../src/layouts/booking/pages/AboutPage.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AA0BhD,UAAU,cAAc;IACtB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,wBAAgB,SAAS,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE,cAAc,+BAwSvE"}
|