@deneb-ui/ui 2.0.5 → 2.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/EditableAnnouncementBar.js +1 -2
- package/dist/EditableContactForm.d.ts +9 -1
- package/dist/EditableContactForm.js +17 -9
- package/dist/EditableDialog.js +4 -14
- package/dist/EditableFooter.d.ts +3 -0
- package/dist/EditableFooter.js +82 -46
- package/dist/EditableNavbar.js +1 -1
- package/dist/EditableProductCard.d.ts +9 -1
- package/dist/EditableProductCard.js +3 -3
- package/dist/EditableText.d.ts +6 -1
- package/dist/EditableText.js +13 -3
- package/dist/business/BusinessHours.js +1 -1
- package/dist/location/LocationCard.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
> **DENEB UI — Build beautiful interfaces, effortlessly.**
|
|
6
6
|
> The premier visual-first React component ecosystem.
|
|
7
|
-
>
|
|
7
|
+
> Proudly presented by **DENEB-UI Collaborate with FIVORA**.
|
|
8
8
|
|
|
9
9
|
[](https://github.com/chamikathereal)
|
|
10
10
|
[](https://opensource.org/licenses/MIT)
|
|
@@ -85,8 +85,7 @@ function EditableAnnouncementBar({ fieldPath = 'site.announcement', defaultText
|
|
|
85
85
|
borderRadius: '0.25rem',
|
|
86
86
|
transition: 'color 0.15s ease',
|
|
87
87
|
};
|
|
88
|
-
|
|
89
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: `deneb-announcement-bar relative z-40 bg-slate-900 text-white text-xs md:text-sm font-medium px-4 py-2 flex items-center justify-center text-center ${className}`, style: containerStyle, children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-center flex-wrap gap-1.5 max-w-7xl mx-auto pr-6", children: [badge && ((0, jsx_runtime_1.jsx)("span", { className: "deneb-announcement-badge bg-white/20 text-white px-2 py-0.5 rounded-full text-[10px] font-bold tracking-wider uppercase inline-flex items-center", style: badgeStyle, ...(hasDynamicField ? { 'data-preview-field-path': `${fieldPath}.badge` } : { 'data-preview-static': 'announcement-badge' }), children: badge })), (0, jsx_runtime_1.jsx)("span", { className: "deneb-announcement-text", ...(hasDynamicField ? { 'data-preview-field-path': `${fieldPath}.text` } : { 'data-preview-static': 'announcement-text' }), children: text }), linkText && linkUrl && ((0, jsx_runtime_1.jsxs)("a", { href: linkUrl, className: "deneb-announcement-link underline font-semibold text-white hover:opacity-90 transition-opacity ml-1 inline-flex items-center gap-1", style: linkStyle, ...(hasDynamicField ? { 'data-preview-field-path': `${fieldPath}.linkText` } : { 'data-preview-static': 'announcement-link' }), children: [linkText, " \u2192"] }))] }), dismissible && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setIsDismissed(true), style: closeButtonStyle, "aria-label": "Dismiss announcement", className: "hover:text-white transition-colors", "data-preview-static": "announcement-dismiss", children: (0, jsx_runtime_1.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [(0, jsx_runtime_1.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), (0, jsx_runtime_1.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) }))] }));
|
|
88
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: `deneb-announcement-bar relative z-40 bg-slate-900 text-white text-xs md:text-sm font-medium px-4 py-2 flex items-center justify-center text-center ${className}`, style: containerStyle, children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-center flex-wrap gap-1.5 max-w-7xl mx-auto pr-6", children: [badge && ((0, jsx_runtime_1.jsx)("span", { className: "deneb-announcement-badge bg-white/20 text-white px-2 py-0.5 rounded-full text-[10px] font-bold tracking-wider uppercase inline-flex items-center", style: badgeStyle, "data-preview-field-path": fieldPath ? `${fieldPath}.badge` : undefined, children: badge })), (0, jsx_runtime_1.jsx)("span", { className: "deneb-announcement-text", "data-preview-field-path": fieldPath ? `${fieldPath}.text` : undefined, children: text }), linkText && linkUrl && ((0, jsx_runtime_1.jsxs)("a", { href: linkUrl, className: "deneb-announcement-link underline font-semibold text-white hover:opacity-90 transition-opacity ml-1 inline-flex items-center gap-1", style: linkStyle, "data-preview-field-path": fieldPath ? `${fieldPath}.linkText` : undefined, children: [linkText, " \u2192"] }))] }), dismissible && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setIsDismissed(true), style: closeButtonStyle, "aria-label": "Dismiss announcement", className: "hover:text-white transition-colors", "data-preview-static": "announcement-dismiss", children: (0, jsx_runtime_1.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [(0, jsx_runtime_1.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), (0, jsx_runtime_1.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) }))] }));
|
|
90
89
|
}
|
|
91
90
|
// Canonical alias
|
|
92
91
|
exports.AnnouncementBar = EditableAnnouncementBar;
|
|
@@ -5,7 +5,15 @@ export interface EditableContactFormProps extends React.FormHTMLAttributes<HTMLF
|
|
|
5
5
|
formTitlePath?: string;
|
|
6
6
|
submitButtonText?: string;
|
|
7
7
|
submitLabelPath?: string;
|
|
8
|
+
nameLabelPath?: string;
|
|
9
|
+
namePlaceholderPath?: string;
|
|
10
|
+
emailLabelPath?: string;
|
|
11
|
+
emailPlaceholderPath?: string;
|
|
12
|
+
phoneLabelPath?: string;
|
|
13
|
+
phonePlaceholderPath?: string;
|
|
14
|
+
messageLabelPath?: string;
|
|
15
|
+
messagePlaceholderPath?: string;
|
|
8
16
|
successMessage?: string;
|
|
9
17
|
showPhone?: boolean;
|
|
10
18
|
}
|
|
11
|
-
export declare function EditableContactForm({ endpoint, formTitle, formTitlePath, submitButtonText, submitLabelPath, successMessage, showPhone, className, style, ...props }: EditableContactFormProps): React.JSX.Element;
|
|
19
|
+
export declare function EditableContactForm({ endpoint, formTitle, formTitlePath, submitButtonText, submitLabelPath, nameLabelPath, namePlaceholderPath, emailLabelPath, emailPlaceholderPath, phoneLabelPath, phonePlaceholderPath, messageLabelPath, messagePlaceholderPath, successMessage, showPhone, className, style, ...props }: EditableContactFormProps): React.JSX.Element;
|
|
@@ -4,13 +4,21 @@ exports.EditableContactForm = EditableContactForm;
|
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const SiteDataProvider_1 = require("./SiteDataProvider");
|
|
7
|
-
function EditableContactForm({ endpoint = 'https://api.fivora.com/site-contact', formTitle, formTitlePath, submitButtonText = 'Send Message', submitLabelPath = 'contact.submitLabel', successMessage = 'Thank you! Your message has been sent successfully.', showPhone = false, className = '', style, ...props }) {
|
|
7
|
+
function EditableContactForm({ endpoint = 'https://api.fivora.com/site-contact', formTitle, formTitlePath, submitButtonText = 'Send Message', submitLabelPath = 'contact.submitLabel', nameLabelPath = 'contact.nameLabel', namePlaceholderPath = 'contact.namePlaceholder', emailLabelPath = 'contact.emailLabel', emailPlaceholderPath = 'contact.emailPlaceholder', phoneLabelPath = 'contact.phoneLabel', phonePlaceholderPath = 'contact.phonePlaceholder', messageLabelPath = 'contact.messageLabel', messagePlaceholderPath = 'contact.messagePlaceholder', successMessage = 'Thank you! Your message has been sent successfully.', showPhone = false, className = '', style, ...props }) {
|
|
8
8
|
const siteData = (0, SiteDataProvider_1.useSiteData)();
|
|
9
9
|
const [status, setStatus] = (0, react_1.useState)('idle');
|
|
10
10
|
const [errorMessage, setErrorMessage] = (0, react_1.useState)('');
|
|
11
11
|
const contactContent = siteData?.content?.contact;
|
|
12
12
|
const resolvedSubmitText = String(contactContent?.submitLabel || submitButtonText);
|
|
13
13
|
const resolvedFormTitle = formTitle || contactContent?.formTitle;
|
|
14
|
+
const resolvedNameLabel = String(contactContent?.nameLabel || 'Your Name');
|
|
15
|
+
const resolvedNamePlaceholder = String(contactContent?.namePlaceholder || 'John Doe');
|
|
16
|
+
const resolvedEmailLabel = String(contactContent?.emailLabel || 'Email Address');
|
|
17
|
+
const resolvedEmailPlaceholder = String(contactContent?.emailPlaceholder || 'john@example.com');
|
|
18
|
+
const resolvedPhoneLabel = String(contactContent?.phoneLabel || 'Phone Number');
|
|
19
|
+
const resolvedPhonePlaceholder = String(contactContent?.phonePlaceholder || '+1 (555) 000-0000');
|
|
20
|
+
const resolvedMessageLabel = String(contactContent?.messageLabel || 'Message');
|
|
21
|
+
const resolvedMessagePlaceholder = String(contactContent?.messagePlaceholder || 'Tell us how we can help...');
|
|
14
22
|
const handleSubmit = async (e) => {
|
|
15
23
|
e.preventDefault();
|
|
16
24
|
setStatus('submitting');
|
|
@@ -51,13 +59,13 @@ function EditableContactForm({ endpoint = 'https://api.fivora.com/site-contact',
|
|
|
51
59
|
fontWeight: 700,
|
|
52
60
|
color: 'var(--heading-color, #0f172a)',
|
|
53
61
|
margin: '0 0 0.5rem 0',
|
|
54
|
-
}, children: resolvedFormTitle })), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "contact-name", "data-preview-
|
|
62
|
+
}, children: resolvedFormTitle })), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "contact-name", "data-preview-field-path": nameLabelPath, style: {
|
|
55
63
|
display: 'block',
|
|
56
64
|
fontSize: '0.875rem',
|
|
57
65
|
fontWeight: 600,
|
|
58
66
|
marginBottom: '0.375rem',
|
|
59
67
|
color: 'var(--heading-color, #0f172a)',
|
|
60
|
-
}, children:
|
|
68
|
+
}, children: resolvedNameLabel }), (0, jsx_runtime_1.jsx)("input", { id: "contact-name", name: "name", type: "text", required: true, placeholder: resolvedNamePlaceholder, "data-preview-field-path": namePlaceholderPath, style: {
|
|
61
69
|
width: '100%',
|
|
62
70
|
padding: '0.75rem 1rem',
|
|
63
71
|
borderRadius: '10px',
|
|
@@ -66,13 +74,13 @@ function EditableContactForm({ endpoint = 'https://api.fivora.com/site-contact',
|
|
|
66
74
|
outline: 'none',
|
|
67
75
|
backgroundColor: '#ffffff',
|
|
68
76
|
boxSizing: 'border-box',
|
|
69
|
-
} })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "contact-email", "data-preview-
|
|
77
|
+
} })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "contact-email", "data-preview-field-path": emailLabelPath, style: {
|
|
70
78
|
display: 'block',
|
|
71
79
|
fontSize: '0.875rem',
|
|
72
80
|
fontWeight: 600,
|
|
73
81
|
marginBottom: '0.375rem',
|
|
74
82
|
color: 'var(--heading-color, #0f172a)',
|
|
75
|
-
}, children:
|
|
83
|
+
}, children: resolvedEmailLabel }), (0, jsx_runtime_1.jsx)("input", { id: "contact-email", name: "email", type: "email", required: true, placeholder: resolvedEmailPlaceholder, "data-preview-field-path": emailPlaceholderPath, style: {
|
|
76
84
|
width: '100%',
|
|
77
85
|
padding: '0.75rem 1rem',
|
|
78
86
|
borderRadius: '10px',
|
|
@@ -81,13 +89,13 @@ function EditableContactForm({ endpoint = 'https://api.fivora.com/site-contact',
|
|
|
81
89
|
outline: 'none',
|
|
82
90
|
backgroundColor: '#ffffff',
|
|
83
91
|
boxSizing: 'border-box',
|
|
84
|
-
} })] }), showPhone && ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "contact-phone", "data-preview-
|
|
92
|
+
} })] }), showPhone && ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "contact-phone", "data-preview-field-path": phoneLabelPath, style: {
|
|
85
93
|
display: 'block',
|
|
86
94
|
fontSize: '0.875rem',
|
|
87
95
|
fontWeight: 600,
|
|
88
96
|
marginBottom: '0.375rem',
|
|
89
97
|
color: 'var(--heading-color, #0f172a)',
|
|
90
|
-
}, children:
|
|
98
|
+
}, children: resolvedPhoneLabel }), (0, jsx_runtime_1.jsx)("input", { id: "contact-phone", name: "phone", type: "tel", placeholder: resolvedPhonePlaceholder, "data-preview-field-path": phonePlaceholderPath, style: {
|
|
91
99
|
width: '100%',
|
|
92
100
|
padding: '0.75rem 1rem',
|
|
93
101
|
borderRadius: '10px',
|
|
@@ -96,13 +104,13 @@ function EditableContactForm({ endpoint = 'https://api.fivora.com/site-contact',
|
|
|
96
104
|
outline: 'none',
|
|
97
105
|
backgroundColor: '#ffffff',
|
|
98
106
|
boxSizing: 'border-box',
|
|
99
|
-
} })] })), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "contact-message", "data-preview-
|
|
107
|
+
} })] })), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "contact-message", "data-preview-field-path": messageLabelPath, style: {
|
|
100
108
|
display: 'block',
|
|
101
109
|
fontSize: '0.875rem',
|
|
102
110
|
fontWeight: 600,
|
|
103
111
|
marginBottom: '0.375rem',
|
|
104
112
|
color: 'var(--heading-color, #0f172a)',
|
|
105
|
-
}, children:
|
|
113
|
+
}, children: resolvedMessageLabel }), (0, jsx_runtime_1.jsx)("textarea", { id: "contact-message", name: "message", rows: 5, required: true, placeholder: resolvedMessagePlaceholder, "data-preview-field-path": messagePlaceholderPath, style: {
|
|
106
114
|
width: '100%',
|
|
107
115
|
padding: '0.75rem 1rem',
|
|
108
116
|
borderRadius: '10px',
|
package/dist/EditableDialog.js
CHANGED
|
@@ -82,17 +82,12 @@ function EditableDialog({ open = false, onClose, title, description, titleFieldP
|
|
|
82
82
|
alignItems: 'flex-start',
|
|
83
83
|
justifyContent: 'space-between',
|
|
84
84
|
marginBottom: description || descriptionFieldPath ? '0.5rem' : '1.25rem',
|
|
85
|
-
}, children: [
|
|
85
|
+
}, children: [title ? ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "h2", id: titleFieldPath || 'common.dialogTitle', defaultValue: title, style: {
|
|
86
86
|
fontSize: '1.35rem',
|
|
87
87
|
fontWeight: 700,
|
|
88
88
|
color: 'var(--heading-color, #0f172a)',
|
|
89
89
|
margin: 0,
|
|
90
|
-
} })) :
|
|
91
|
-
fontSize: '1.35rem',
|
|
92
|
-
fontWeight: 700,
|
|
93
|
-
color: 'var(--heading-color, #0f172a)',
|
|
94
|
-
margin: 0,
|
|
95
|
-
}, children: title })) : ((0, jsx_runtime_1.jsx)("div", {})), showCloseButton && onClose && ((0, jsx_runtime_1.jsx)("button", { type: "button", "data-preview-static": "dialog-close-btn", onClick: onClose, "aria-label": "Close dialog", style: {
|
|
90
|
+
} })) : ((0, jsx_runtime_1.jsx)("div", {})), showCloseButton && onClose && ((0, jsx_runtime_1.jsx)("button", { type: "button", "data-preview-static": "dialog-close-btn", onClick: onClose, "aria-label": "Close dialog", style: {
|
|
96
91
|
background: 'none',
|
|
97
92
|
border: 'none',
|
|
98
93
|
padding: '0.375rem',
|
|
@@ -109,18 +104,13 @@ function EditableDialog({ open = false, onClose, title, description, titleFieldP
|
|
|
109
104
|
}, onMouseLeave: (e) => {
|
|
110
105
|
e.currentTarget.style.backgroundColor = 'transparent';
|
|
111
106
|
e.currentTarget.style.color = '#94a3b8';
|
|
112
|
-
}, children: (0, jsx_runtime_1.jsx)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] })),
|
|
113
|
-
fontSize: '0.925rem',
|
|
114
|
-
color: 'var(--muted-text, #64748b)',
|
|
115
|
-
marginBottom: '1.5rem',
|
|
116
|
-
lineHeight: 1.5,
|
|
117
|
-
} })) : description ? ((0, jsx_runtime_1.jsx)("p", { "data-preview-static": "dialog-description", style: {
|
|
107
|
+
}, children: (0, jsx_runtime_1.jsx)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] })), description ? ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "p", id: descriptionFieldPath || 'common.dialogDescription', defaultValue: description, style: {
|
|
118
108
|
fontSize: '0.925rem',
|
|
119
109
|
color: 'var(--muted-text, #64748b)',
|
|
120
110
|
marginBottom: '1.5rem',
|
|
121
111
|
lineHeight: 1.5,
|
|
122
112
|
margin: '0 0 1.5rem 0',
|
|
123
|
-
}
|
|
113
|
+
} })) : null, (0, jsx_runtime_1.jsx)("div", { style: { flex: 1, overflowY: 'auto' }, children: children }), footerSlot && ((0, jsx_runtime_1.jsx)("div", { style: {
|
|
124
114
|
marginTop: '1.75rem',
|
|
125
115
|
paddingTop: '1rem',
|
|
126
116
|
borderTop: '1px solid #f1f5f9',
|
package/dist/EditableFooter.d.ts
CHANGED
|
@@ -9,6 +9,9 @@ export interface EditableFooterProps extends React.HTMLAttributes<HTMLElement> {
|
|
|
9
9
|
links?: FooterLink[];
|
|
10
10
|
basePath?: string;
|
|
11
11
|
showNewsletter?: boolean;
|
|
12
|
+
socialMedia?: Record<string, string>;
|
|
13
|
+
whatsappUrl?: string;
|
|
14
|
+
directMessageText?: string;
|
|
12
15
|
}
|
|
13
16
|
/**
|
|
14
17
|
* Next-Level DENEB UI Footer
|
package/dist/EditableFooter.js
CHANGED
|
@@ -6,12 +6,47 @@ exports.EditableFooter = EditableFooter;
|
|
|
6
6
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
7
|
const react_1 = require("react");
|
|
8
8
|
const SiteDataProvider_1 = require("./SiteDataProvider");
|
|
9
|
+
const EditableText_1 = require("./EditableText");
|
|
9
10
|
const DEFAULT_FOOTER_PAGES = [
|
|
10
11
|
{ id: 'home', label: 'Home', route: '/' },
|
|
11
12
|
{ id: 'about_us', label: 'About', route: '/about_us' },
|
|
12
13
|
{ id: 'services', label: 'Services', route: '/services' },
|
|
13
14
|
{ id: 'contact', label: 'Contact', route: '/contact' },
|
|
14
15
|
];
|
|
16
|
+
const SOCIAL_ICONS = {
|
|
17
|
+
twitter: {
|
|
18
|
+
label: 'X (Twitter)',
|
|
19
|
+
icon: ((0, jsx_runtime_1.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", children: (0, jsx_runtime_1.jsx)("path", { d: "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" }) })),
|
|
20
|
+
},
|
|
21
|
+
x: {
|
|
22
|
+
label: 'X (Twitter)',
|
|
23
|
+
icon: ((0, jsx_runtime_1.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", children: (0, jsx_runtime_1.jsx)("path", { d: "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" }) })),
|
|
24
|
+
},
|
|
25
|
+
github: {
|
|
26
|
+
label: 'GitHub',
|
|
27
|
+
icon: ((0, jsx_runtime_1.jsx)("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "currentColor", children: (0, jsx_runtime_1.jsx)("path", { d: "M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" }) })),
|
|
28
|
+
},
|
|
29
|
+
linkedin: {
|
|
30
|
+
label: 'LinkedIn',
|
|
31
|
+
icon: ((0, jsx_runtime_1.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", children: (0, jsx_runtime_1.jsx)("path", { d: "M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" }) })),
|
|
32
|
+
},
|
|
33
|
+
instagram: {
|
|
34
|
+
label: 'Instagram',
|
|
35
|
+
icon: ((0, jsx_runtime_1.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [(0, jsx_runtime_1.jsx)("rect", { width: "20", height: "20", x: "2", y: "2", rx: "5", ry: "5" }), (0, jsx_runtime_1.jsx)("path", { d: "M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z" }), (0, jsx_runtime_1.jsx)("line", { x1: "17.5", x2: "17.51", y1: "6.5", y2: "6.5" })] })),
|
|
36
|
+
},
|
|
37
|
+
facebook: {
|
|
38
|
+
label: 'Facebook',
|
|
39
|
+
icon: ((0, jsx_runtime_1.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", children: (0, jsx_runtime_1.jsx)("path", { d: "M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z" }) })),
|
|
40
|
+
},
|
|
41
|
+
youtube: {
|
|
42
|
+
label: 'YouTube',
|
|
43
|
+
icon: ((0, jsx_runtime_1.jsx)("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "currentColor", children: (0, jsx_runtime_1.jsx)("path", { d: "M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z" }) })),
|
|
44
|
+
},
|
|
45
|
+
whatsapp: {
|
|
46
|
+
label: 'WhatsApp',
|
|
47
|
+
icon: ((0, jsx_runtime_1.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", children: [(0, jsx_runtime_1.jsx)("path", { d: "M12.031 6.172c-3.181 0-5.767 2.586-5.768 5.766-.001 1.298.38 2.27 1.019 3.287l-.582 2.128 2.182-.573c.978.58 1.911.928 3.145.929 3.178 0 5.767-2.587 5.768-5.766.001-3.187-2.575-5.77-5.764-5.771zm3.392 8.244c-.144.405-.837.774-1.17.824-.312.045-.634.072-1.849-.434-1.464-.61-2.41-2.096-2.484-2.195-.072-.099-.6-0.798-.6-1.523 0-.726.379-1.084.514-1.231.135-.148.297-.185.396-.185.099 0 .198.002.284.006.091.004.213-.035.333.253.123.297.42 1.024.457 1.099.037.074.062.16.012.259-.049.099-.074.16-.148.247-.074.086-.156.193-.223.259-.074.074-.152.155-.065.304.086.148.384.633.824 1.024.567.505 1.045.661 1.194.735.148.074.235.062.321-.037.086-.099.37-.432.469-.58.099-.148.198-.123.333-.074.135.049.864.407 1.012.481.148.074.247.111.284.173.037.062.037.358-.107.763z" }), (0, jsx_runtime_1.jsx)("path", { d: "M12 2C6.48 2 2 6.48 2 12c0 1.82.49 3.53 1.34 5L2 22l5.16-1.32c1.42.8 3.06 1.32 4.84 1.32 5.52 0 10-4.48 10-10S17.52 2 12 2zm0 18.2c-1.59 0-3.07-.46-4.32-1.26l-.31-.2-3.06.78.82-2.98-.22-.33C4.05 14.93 3.6 13.51 3.6 12c0-4.63 3.77-8.4 8.4-8.4s8.4 3.77 8.4 8.4-3.77 8.4-8.4 8.4z" })] })),
|
|
48
|
+
},
|
|
49
|
+
};
|
|
15
50
|
/**
|
|
16
51
|
* Next-Level DENEB UI Footer
|
|
17
52
|
*
|
|
@@ -35,6 +70,7 @@ function EditableFooter({ defaultLinks = DEFAULT_FOOTER_PAGES, links, basePath =
|
|
|
35
70
|
const [subscribed, setSubscribed] = (0, react_1.useState)(false);
|
|
36
71
|
const content = (siteData?.content || {});
|
|
37
72
|
const common = (content?.common || {});
|
|
73
|
+
const contact = (content?.contact || {});
|
|
38
74
|
const business = (common?.business || {});
|
|
39
75
|
// Auto-synchronized with Header
|
|
40
76
|
const siteName = String(common?.websiteTitle || common?.siteName || 'Storefront');
|
|
@@ -45,9 +81,23 @@ function EditableFooter({ defaultLinks = DEFAULT_FOOTER_PAGES, links, basePath =
|
|
|
45
81
|
const footerHeading = String(common?.footerHeading || 'Stay Connected');
|
|
46
82
|
const copyright = String(common?.copyright || `© ${new Date().getFullYear()} ${siteName}. All rights reserved.`);
|
|
47
83
|
// Contact / business values
|
|
48
|
-
const phone = String(business?.phone || common?.phone || '');
|
|
49
|
-
const emailContact = String(business?.email || common?.email || '');
|
|
50
|
-
const address = String(business?.location?.address || common?.address || '');
|
|
84
|
+
const phone = String(business?.phone || common?.phone || contact?.phone || '');
|
|
85
|
+
const emailContact = String(business?.email || common?.email || contact?.email || '');
|
|
86
|
+
const address = String(business?.location?.address || common?.address || contact?.address || '');
|
|
87
|
+
// Social media mapping with live editable URL bindings
|
|
88
|
+
const rawSocial = (common?.socialMedia || content?.socialMedia || props.socialMedia || {});
|
|
89
|
+
const socialPlatforms = Object.keys(rawSocial).length > 0
|
|
90
|
+
? Object.keys(rawSocial)
|
|
91
|
+
: ['twitter', 'github', 'linkedin', 'instagram'];
|
|
92
|
+
// Direct message / WhatsApp action
|
|
93
|
+
const directMessageLabel = String(contact?.directMessageText || common?.directMessageText || props.directMessageText || 'Send us a direct message');
|
|
94
|
+
const rawWhatsapp = String(contact?.whatsapp || contact?.whatsappUrl || common?.whatsapp || business?.whatsapp || props.whatsappUrl || phone || '');
|
|
95
|
+
const cleanDigits = rawWhatsapp.replace(/[^\d]/g, '');
|
|
96
|
+
const whatsappHref = rawWhatsapp.startsWith('http')
|
|
97
|
+
? rawWhatsapp
|
|
98
|
+
: cleanDigits
|
|
99
|
+
? `https://wa.me/${cleanDigits}`
|
|
100
|
+
: 'https://wa.me/';
|
|
51
101
|
// Route filtering
|
|
52
102
|
const navigationItems = links || defaultLinks;
|
|
53
103
|
const requiredPages = Array.isArray(siteData?.requirements?.requiredPages)
|
|
@@ -118,14 +168,14 @@ function EditableFooter({ defaultLinks = DEFAULT_FOOTER_PAGES, links, basePath =
|
|
|
118
168
|
padding: 0,
|
|
119
169
|
cursor: 'pointer',
|
|
120
170
|
textAlign: 'left',
|
|
121
|
-
}, className: "inline-flex items-center gap-3 group border-0 bg-transparent p-0 cursor-pointer", children: [(0, jsx_runtime_1.jsx)("img", { src: withBase(logoUrl || '/placeholder.svg'), alt: siteName, "data-preview-
|
|
171
|
+
}, className: "inline-flex items-center gap-3 group border-0 bg-transparent p-0 cursor-pointer", children: [(0, jsx_runtime_1.jsx)("img", { src: withBase(logoUrl || '/placeholder.svg'), alt: siteName, "data-preview-field-path": "common.logoUrl", style: {
|
|
122
172
|
height: '32px',
|
|
123
173
|
width: 'auto',
|
|
124
174
|
maxWidth: '120px',
|
|
125
175
|
objectFit: 'contain',
|
|
126
176
|
borderRadius: '6px',
|
|
127
177
|
filter: 'brightness(1.1)',
|
|
128
|
-
}, className: "h-8 w-auto max-w-[120px] object-contain rounded-md group-hover:scale-105 transition-transform" }), (0, jsx_runtime_1.jsx)("span", { "data-preview-
|
|
178
|
+
}, className: "h-8 w-auto max-w-[120px] object-contain rounded-md group-hover:scale-105 transition-transform" }), (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": "common.websiteTitle", style: {
|
|
129
179
|
fontSize: '1.25rem',
|
|
130
180
|
fontWeight: 700,
|
|
131
181
|
letterSpacing: '-0.025em',
|
|
@@ -136,12 +186,20 @@ function EditableFooter({ defaultLinks = DEFAULT_FOOTER_PAGES, links, basePath =
|
|
|
136
186
|
color: '#94a3b8', // slate-400
|
|
137
187
|
margin: 0,
|
|
138
188
|
maxWidth: '320px',
|
|
139
|
-
}, className: "text-sm text-slate-400 leading-relaxed max-w-sm mt-1", children: shortDescription }), (0, jsx_runtime_1.
|
|
189
|
+
}, className: "text-sm text-slate-400 leading-relaxed max-w-sm mt-1", children: shortDescription }), (0, jsx_runtime_1.jsx)("div", { style: {
|
|
140
190
|
display: 'flex',
|
|
141
191
|
alignItems: 'center',
|
|
192
|
+
flexWrap: 'wrap',
|
|
142
193
|
gap: '0.625rem',
|
|
143
194
|
marginTop: '0.75rem',
|
|
144
|
-
}, className: "flex items-center gap-2.5 mt-3", children:
|
|
195
|
+
}, className: "flex items-center flex-wrap gap-2.5 mt-3", children: socialPlatforms.map((platformKey) => {
|
|
196
|
+
const key = platformKey.toLowerCase();
|
|
197
|
+
const iconConfig = SOCIAL_ICONS[key] || {
|
|
198
|
+
label: platformKey,
|
|
199
|
+
icon: ((0, jsx_runtime_1.jsx)("span", { style: { fontSize: '10px', fontWeight: 700, textTransform: 'uppercase' }, children: platformKey.slice(0, 2) })),
|
|
200
|
+
};
|
|
201
|
+
const url = rawSocial[platformKey] || rawSocial[key] || `https://${key}.com`;
|
|
202
|
+
return ((0, jsx_runtime_1.jsx)("a", { href: url, target: "_blank", rel: "noopener noreferrer", "data-preview-field-path": `common.socialMedia.${key}`, "aria-label": iconConfig.label, title: `Edit ${iconConfig.label} URL in Fivora`, style: {
|
|
145
203
|
width: '34px',
|
|
146
204
|
height: '34px',
|
|
147
205
|
borderRadius: '8px',
|
|
@@ -153,31 +211,8 @@ function EditableFooter({ defaultLinks = DEFAULT_FOOTER_PAGES, links, basePath =
|
|
|
153
211
|
color: '#94a3b8',
|
|
154
212
|
textDecoration: 'none',
|
|
155
213
|
transition: 'all 0.15s ease',
|
|
156
|
-
}, className: "w-8 h-8 rounded-lg bg-slate-900 border border-slate-800 flex items-center justify-center text-slate-400 hover:text-white hover:border-slate-700 hover:bg-slate-800 transition-all", children:
|
|
157
|
-
|
|
158
|
-
height: '34px',
|
|
159
|
-
borderRadius: '8px',
|
|
160
|
-
backgroundColor: 'rgba(255, 255, 255, 0.05)',
|
|
161
|
-
border: '1px solid rgba(255, 255, 255, 0.1)',
|
|
162
|
-
display: 'flex',
|
|
163
|
-
alignItems: 'center',
|
|
164
|
-
justifyContent: 'center',
|
|
165
|
-
color: '#94a3b8',
|
|
166
|
-
textDecoration: 'none',
|
|
167
|
-
transition: 'all 0.15s ease',
|
|
168
|
-
}, className: "w-8 h-8 rounded-lg bg-slate-900 border border-slate-800 flex items-center justify-center text-slate-400 hover:text-white hover:border-slate-700 hover:bg-slate-800 transition-all", children: (0, jsx_runtime_1.jsx)("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "currentColor", children: (0, jsx_runtime_1.jsx)("path", { d: "M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" }) }) }), (0, jsx_runtime_1.jsx)("a", { href: "https://linkedin.com", target: "_blank", rel: "noreferrer", "data-preview-static": "social-linkedin", "aria-label": "LinkedIn", style: {
|
|
169
|
-
width: '34px',
|
|
170
|
-
height: '34px',
|
|
171
|
-
borderRadius: '8px',
|
|
172
|
-
backgroundColor: 'rgba(255, 255, 255, 0.05)',
|
|
173
|
-
border: '1px solid rgba(255, 255, 255, 0.1)',
|
|
174
|
-
display: 'flex',
|
|
175
|
-
alignItems: 'center',
|
|
176
|
-
justifyContent: 'center',
|
|
177
|
-
color: '#94a3b8',
|
|
178
|
-
textDecoration: 'none',
|
|
179
|
-
transition: 'all 0.15s ease',
|
|
180
|
-
}, className: "w-8 h-8 rounded-lg bg-slate-900 border border-slate-800 flex items-center justify-center text-slate-400 hover:text-white hover:border-slate-700 hover:bg-slate-800 transition-all", children: (0, jsx_runtime_1.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", children: (0, jsx_runtime_1.jsx)("path", { d: "M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" }) }) })] })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h4", { "data-preview-static": "footer-explore-heading", style: {
|
|
214
|
+
}, className: "w-8 h-8 rounded-lg bg-slate-900 border border-slate-800 flex items-center justify-center text-slate-400 hover:text-white hover:border-slate-700 hover:bg-slate-800 transition-all", children: iconConfig.icon }, platformKey));
|
|
215
|
+
}) })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h4", { "data-preview-static": "footer-explore-heading", style: {
|
|
181
216
|
fontSize: '0.8125rem',
|
|
182
217
|
fontWeight: 700,
|
|
183
218
|
textTransform: 'uppercase',
|
|
@@ -229,19 +264,20 @@ function EditableFooter({ defaultLinks = DEFAULT_FOOTER_PAGES, links, basePath =
|
|
|
229
264
|
gap: '0.875rem',
|
|
230
265
|
fontSize: '0.875rem',
|
|
231
266
|
color: '#94a3b8',
|
|
232
|
-
}, className: "flex flex-col gap-3.5 text-sm text-slate-400", children: [emailContact && ((0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'center', gap: '0.5rem' }, children: [(0, jsx_runtime_1.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "text-slate-500", children: [(0, jsx_runtime_1.jsx)("rect", { width: "20", height: "16", x: "2", y: "4", rx: "2" }), (0, jsx_runtime_1.jsx)("path", { d: "m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" })] }), (0, jsx_runtime_1.jsx)("a", { href: `mailto:${emailContact}`, "data-preview-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
267
|
+
}, className: "flex flex-col gap-3.5 text-sm text-slate-400", children: [emailContact && ((0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'center', gap: '0.5rem' }, children: [(0, jsx_runtime_1.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "text-slate-500", children: [(0, jsx_runtime_1.jsx)("rect", { width: "20", height: "16", x: "2", y: "4", rx: "2" }), (0, jsx_runtime_1.jsx)("path", { d: "m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" })] }), (0, jsx_runtime_1.jsx)("a", { href: `mailto:${emailContact}`, "data-preview-field-path": "contact.email", className: "hover:text-white transition-colors", style: { color: 'inherit', textDecoration: 'none' }, children: emailContact })] })), phone && ((0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'center', gap: '0.5rem' }, children: [(0, jsx_runtime_1.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "text-slate-500", children: (0, jsx_runtime_1.jsx)("path", { d: "M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z" }) }), (0, jsx_runtime_1.jsx)("a", { href: `tel:${phone}`, "data-preview-field-path": "contact.phone", className: "hover:text-white transition-colors", style: { color: 'inherit', textDecoration: 'none' }, children: phone })] })), address && ((0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'flex-start', gap: '0.5rem' }, children: [(0, jsx_runtime_1.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "text-slate-500 mt-0.5", children: [(0, jsx_runtime_1.jsx)("path", { d: "M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" }), (0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "10", r: "3" })] }), (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": "contact.address", children: address })] })), hasContact && ((0, jsx_runtime_1.jsx)("div", { style: { marginTop: '0.5rem' }, children: (0, jsx_runtime_1.jsxs)("a", { href: whatsappHref, target: "_blank", rel: "noopener noreferrer", "data-preview-field-path": "contact.whatsapp", "aria-label": "Direct message on WhatsApp", style: {
|
|
268
|
+
display: 'inline-flex',
|
|
269
|
+
alignItems: 'center',
|
|
270
|
+
gap: '0.375rem',
|
|
271
|
+
fontSize: '0.8125rem',
|
|
272
|
+
fontWeight: 600,
|
|
273
|
+
color: '#34d399', // emerald-400
|
|
274
|
+
background: 'transparent',
|
|
275
|
+
border: 0,
|
|
276
|
+
padding: 0,
|
|
277
|
+
cursor: 'pointer',
|
|
278
|
+
textDecoration: 'none',
|
|
279
|
+
transition: 'color 0.15s ease',
|
|
280
|
+
}, className: "inline-flex items-center gap-1.5 text-xs font-semibold text-emerald-400 hover:text-emerald-300 transition-colors border-0 bg-transparent p-0 cursor-pointer", children: [(0, jsx_runtime_1.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", style: { flexShrink: 0 }, children: [(0, jsx_runtime_1.jsx)("path", { d: "M12.031 6.172c-3.181 0-5.767 2.586-5.768 5.766-.001 1.298.38 2.27 1.019 3.287l-.582 2.128 2.182-.573c.978.58 1.911.928 3.145.929 3.178 0 5.767-2.587 5.768-5.766.001-3.187-2.575-5.77-5.764-5.771zm3.392 8.244c-.144.405-.837.774-1.17.824-.312.045-.634.072-1.849-.434-1.464-.61-2.41-2.096-2.484-2.195-.072-.099-.6-0.798-.6-1.523 0-.726.379-1.084.514-1.231.135-.148.297-.185.396-.185.099 0 .198.002.284.006.091.004.213-.035.333.253.123.297.42 1.024.457 1.099.037.074.062.16.012.259-.049.099-.074.16-.148.247-.074.086-.156.193-.223.259-.074.074-.152.155-.065.304.086.148.384.633.824 1.024.567.505 1.045.661 1.194.735.148.074.235.062.321-.037.086-.099.37-.432.469-.58.099-.148.198-.123.333-.074.135.049.864.407 1.012.481.148.074.247.111.284.173.037.062.037.358-.107.763z" }), (0, jsx_runtime_1.jsx)("path", { d: "M12 2C6.48 2 2 6.48 2 12c0 1.82.49 3.53 1.34 5L2 22l5.16-1.32c1.42.8 3.06 1.32 4.84 1.32 5.52 0 10-4.48 10-10S17.52 2 12 2zm0 18.2c-1.59 0-3.07-.46-4.32-1.26l-.31-.2-3.06.78.82-2.98-.22-.33C4.05 14.93 3.6 13.51 3.6 12c0-4.63 3.77-8.4 8.4-8.4s8.4 3.77 8.4 8.4-3.77 8.4-8.4 8.4z" })] }), (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: "contact.directMessageText", defaultValue: directMessageLabel, style: { color: 'inherit', fontWeight: 600 } }), (0, jsx_runtime_1.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: (0, jsx_runtime_1.jsx)("path", { d: "M5 12h14M12 5l7 7-7 7" }) })] }) }))] })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h4", { "data-preview-field-path": "common.footerHeading", style: {
|
|
245
281
|
fontSize: '0.8125rem',
|
|
246
282
|
fontWeight: 700,
|
|
247
283
|
textTransform: 'uppercase',
|
|
@@ -313,7 +349,7 @@ function EditableFooter({ defaultLinks = DEFAULT_FOOTER_PAGES, links, basePath =
|
|
|
313
349
|
padding: '0.15rem 0.5rem',
|
|
314
350
|
borderRadius: '6px',
|
|
315
351
|
letterSpacing: '0.025em',
|
|
316
|
-
}, className: "inline-flex items-center gap-1 font-semibold text-slate-200 bg-slate-900 border border-slate-800 px-2 py-0.5 rounded-md text-xs shadow-inner", children: [(0, jsx_runtime_1.jsx)("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "currentColor", className: "text-
|
|
352
|
+
}, className: "inline-flex items-center gap-1 font-semibold text-slate-200 bg-slate-900 border border-slate-800 px-2 py-0.5 rounded-md text-xs shadow-inner", children: [(0, jsx_runtime_1.jsx)("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "currentColor", className: "text-cyan-400", children: (0, jsx_runtime_1.jsx)("polygon", { points: "12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" }) }), "Fivora"] })] }), (0, jsx_runtime_1.jsx)("button", { type: "button", "data-preview-static": "back-to-top", onClick: scrollToTop, "aria-label": "Back to top", style: {
|
|
317
353
|
display: 'inline-flex',
|
|
318
354
|
alignItems: 'center',
|
|
319
355
|
justifyContent: 'center',
|
package/dist/EditableNavbar.js
CHANGED
|
@@ -171,7 +171,7 @@ function EditableNavbar({ defaultLinks = DEFAULT_PAGES, sticky = true, activeRou
|
|
|
171
171
|
cursor: 'pointer',
|
|
172
172
|
}, className: `block w-full text-left px-3.5 py-2.5 rounded-lg text-base font-medium transition-colors border-0 cursor-pointer ${isActive
|
|
173
173
|
? 'bg-slate-100 text-slate-900 font-semibold dark:bg-slate-800 dark:text-white'
|
|
174
|
-
: 'bg-transparent text-slate-700 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-800'}`, children: (0, jsx_runtime_1.jsx)("span", { "data-preview-
|
|
174
|
+
: 'bg-transparent text-slate-700 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-800'}`, children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `common.navLabels.${link.id}`, children: label }) }) }, link.id));
|
|
175
175
|
}) }))] }));
|
|
176
176
|
}
|
|
177
177
|
exports.Navbar = EditableNavbar;
|
|
@@ -51,10 +51,18 @@ export interface EditableProductCardProps extends React.HTMLAttributes<HTMLEleme
|
|
|
51
51
|
* Optional custom action slot (e.g. Add to Cart button).
|
|
52
52
|
*/
|
|
53
53
|
actionSlot?: React.ReactNode;
|
|
54
|
+
/**
|
|
55
|
+
* Label for the action button (default: 'Buy Now' or product.buttonText).
|
|
56
|
+
*/
|
|
57
|
+
actionLabel?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Custom field path for the action button label.
|
|
60
|
+
*/
|
|
61
|
+
actionLabelPath?: string;
|
|
54
62
|
}
|
|
55
63
|
/**
|
|
56
64
|
* EditableProductCard is an elite, auto-balancing commerce card supporting
|
|
57
65
|
* four visual variants (modern-glass, classic, minimal, horizontal) and
|
|
58
66
|
* strict Fivora visual editing synchronization.
|
|
59
67
|
*/
|
|
60
|
-
export declare function EditableProductCard({ itemPath, product, cardVariant, imageFallback, as: Component, showPrice, showDescription, showCategory, actionSlot, className, style, ...props }: EditableProductCardProps): React.JSX.Element;
|
|
68
|
+
export declare function EditableProductCard({ itemPath, product, cardVariant, imageFallback, as: Component, showPrice, showDescription, showCategory, actionSlot, actionLabel, actionLabelPath, className, style, ...props }: EditableProductCardProps): React.JSX.Element;
|
|
@@ -10,7 +10,7 @@ const EditableText_2 = require("./EditableText");
|
|
|
10
10
|
* four visual variants (modern-glass, classic, minimal, horizontal) and
|
|
11
11
|
* strict Fivora visual editing synchronization.
|
|
12
12
|
*/
|
|
13
|
-
function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass', imageFallback, as: Component = 'article', showPrice = true, showDescription = true, showCategory = true, actionSlot, className = '', style, ...props }) {
|
|
13
|
+
function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass', imageFallback, as: Component = 'article', showPrice = true, showDescription = true, showCategory = true, actionSlot, actionLabel, actionLabelPath, className = '', style, ...props }) {
|
|
14
14
|
const name = String(product?.name || product?.title || '');
|
|
15
15
|
const price = product?.price !== undefined ? String(product.price) : '';
|
|
16
16
|
const originalPrice = product?.originalPrice !== undefined ? String(product.originalPrice) : '';
|
|
@@ -102,7 +102,7 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
|
|
|
102
102
|
fontSize: '0.875rem',
|
|
103
103
|
textDecoration: 'line-through',
|
|
104
104
|
color: 'var(--muted-text, #94a3b8)',
|
|
105
|
-
} })) : null] })), actionSlot ? ((0, jsx_runtime_1.jsx)("div", { children: actionSlot })) : ((0, jsx_runtime_1.jsx)("button", { type: "button",
|
|
105
|
+
} })) : null] })), actionSlot ? ((0, jsx_runtime_1.jsx)("div", { children: actionSlot })) : ((0, jsx_runtime_1.jsx)("button", { type: "button", style: {
|
|
106
106
|
backgroundColor: 'var(--brand-color, #2563eb)',
|
|
107
107
|
color: '#ffffff',
|
|
108
108
|
border: 'none',
|
|
@@ -112,5 +112,5 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
|
|
|
112
112
|
fontWeight: 600,
|
|
113
113
|
cursor: 'pointer',
|
|
114
114
|
transition: 'opacity 0.2s ease',
|
|
115
|
-
}, children: "Buy Now
|
|
115
|
+
}, children: (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: actionLabelPath || `${itemPath}.buttonText`, defaultValue: actionLabel || product?.buttonText || 'Buy Now', style: { color: '#ffffff', fontWeight: 600 } }) }))] })] })] }));
|
|
116
116
|
}
|
package/dist/EditableText.d.ts
CHANGED
|
@@ -32,6 +32,11 @@ export interface EditableTextProps extends React.HTMLAttributes<HTMLElement> {
|
|
|
32
32
|
*/
|
|
33
33
|
'data-preview-field-path'?: string;
|
|
34
34
|
defaultValue?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Placeholder text displayed when defaultValue or children is empty.
|
|
37
|
+
* Remains 100% interactive and editable inside the Fivora live editor.
|
|
38
|
+
*/
|
|
39
|
+
placeholder?: string;
|
|
35
40
|
as?: React.ElementType;
|
|
36
41
|
/**
|
|
37
42
|
* Semantic typography variant providing instant preset styles (h1-h6, p, lead, eyebrow, caption, badge).
|
|
@@ -76,7 +81,7 @@ export interface EditableTextProps extends React.HTMLAttributes<HTMLElement> {
|
|
|
76
81
|
* EditableText provides full typography controls (color, size, weight, line-height, alignment, transform, variants)
|
|
77
82
|
* alongside strict Fivora visual editing bindings.
|
|
78
83
|
*/
|
|
79
|
-
export declare function EditableText({ id, 'data-preview-field-path': previewFieldPath, defaultValue, children, as: ComponentOverride, variant, color, size, weight, lineHeight, align, transform, letterSpacing, fontFamily, style, ...props }: EditableTextProps): React.JSX.Element;
|
|
84
|
+
export declare function EditableText({ id, 'data-preview-field-path': previewFieldPath, defaultValue, placeholder, children, as: ComponentOverride, variant, color, size, weight, lineHeight, align, transform, letterSpacing, fontFamily, style, ...props }: EditableTextProps): React.JSX.Element;
|
|
80
85
|
export interface EditableHeadingProps extends Omit<EditableTextProps, 'variant'> {
|
|
81
86
|
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
82
87
|
}
|
package/dist/EditableText.js
CHANGED
|
@@ -106,9 +106,14 @@ function toCssUnit(value) {
|
|
|
106
106
|
* EditableText provides full typography controls (color, size, weight, line-height, alignment, transform, variants)
|
|
107
107
|
* alongside strict Fivora visual editing bindings.
|
|
108
108
|
*/
|
|
109
|
-
function EditableText({ id, 'data-preview-field-path': previewFieldPath, defaultValue, children, as: ComponentOverride, variant, color, size, weight, lineHeight, align, transform, letterSpacing, fontFamily, style, ...props }) {
|
|
109
|
+
function EditableText({ id, 'data-preview-field-path': previewFieldPath, defaultValue, placeholder, children, as: ComponentOverride, variant, color, size, weight, lineHeight, align, transform, letterSpacing, fontFamily, style, ...props }) {
|
|
110
110
|
const path = previewFieldPath || id;
|
|
111
|
-
const
|
|
111
|
+
const rawContent = children !== undefined ? children : defaultValue;
|
|
112
|
+
const isContentEmpty = rawContent === undefined ||
|
|
113
|
+
rawContent === null ||
|
|
114
|
+
(typeof rawContent === 'string' && rawContent.trim() === '');
|
|
115
|
+
const isPlaceholderActive = isContentEmpty && Boolean(placeholder);
|
|
116
|
+
const displayContent = isPlaceholderActive ? placeholder : rawContent;
|
|
112
117
|
const dynamicStyle = (0, SiteDataProvider_1.useFieldStyle)(path);
|
|
113
118
|
const variantDefaults = variant ? exports.VARIANT_DEFAULTS[variant] : undefined;
|
|
114
119
|
const Component = ComponentOverride || variantDefaults?.as || 'span';
|
|
@@ -148,6 +153,11 @@ function EditableText({ id, 'data-preview-field-path': previewFieldPath, default
|
|
|
148
153
|
const dynamicMarginLeft = toCssUnit(dynamicStyle?.spacingLeft);
|
|
149
154
|
const dynamicMarginRight = toCssUnit(dynamicStyle?.spacingRight);
|
|
150
155
|
const typographyStyle = {
|
|
156
|
+
// Minimum dimensions ensure empty/placeholder elements never collapse to 0x0 and remain 100% clickable in Fivora
|
|
157
|
+
minHeight: '1.2em',
|
|
158
|
+
minWidth: '1.5ch',
|
|
159
|
+
...(Component === 'span' || ComponentOverride === 'span' ? { display: 'inline-block' } : {}),
|
|
160
|
+
...(isPlaceholderActive ? { opacity: 0.55, fontStyle: 'italic' } : {}),
|
|
151
161
|
...(resolvedColor ? { color: resolvedColor } : {}),
|
|
152
162
|
...(resolvedSize ? { fontSize: resolvedSize } : {}),
|
|
153
163
|
...(resolvedWeight ? { fontWeight: resolvedWeight } : {}),
|
|
@@ -168,7 +178,7 @@ function EditableText({ id, 'data-preview-field-path': previewFieldPath, default
|
|
|
168
178
|
...(dynamicMarginLeft !== undefined ? { marginLeft: dynamicMarginLeft } : {}),
|
|
169
179
|
...(dynamicMarginRight !== undefined ? { marginRight: dynamicMarginRight } : {}),
|
|
170
180
|
};
|
|
171
|
-
return ((0, jsx_runtime_1.jsx)(Component, { "data-preview-field-path": path, style: typographyStyle, ...props, children:
|
|
181
|
+
return ((0, jsx_runtime_1.jsx)(Component, { "data-preview-field-path": path, "data-preview-placeholder": isPlaceholderActive ? 'true' : undefined, style: typographyStyle, ...props, children: displayContent }));
|
|
172
182
|
}
|
|
173
183
|
function EditableHeading({ level = 2, as, ...props }) {
|
|
174
184
|
const variant = `h${level}`;
|
|
@@ -67,7 +67,7 @@ function BusinessHours({ hours, title = 'Business Hours', fieldPath = 'common.bu
|
|
|
67
67
|
backgroundColor: 'var(--color-surface, #ffffff)',
|
|
68
68
|
...style,
|
|
69
69
|
};
|
|
70
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: `deneb-business-hours ${className}`.trim(), style: containerStyles, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '1rem' }, children: [(0, jsx_runtime_1.jsx)("h4", { style: { margin: 0, fontSize: '1.1rem', fontWeight: 600, color: 'var(--color-text, #0f172a)' }, children: (0, jsx_runtime_1.jsx)("span", { "data-preview-
|
|
70
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: `deneb-business-hours ${className}`.trim(), style: containerStyles, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '1rem' }, children: [(0, jsx_runtime_1.jsx)("h4", { style: { margin: 0, fontSize: '1.1rem', fontWeight: 600, color: 'var(--color-text, #0f172a)' }, children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": fieldPath ? `${fieldPath}.title` : 'contact.businessHoursTitle', children: title }) }), showStatusBadge && currentStatus && ((0, jsx_runtime_1.jsxs)("span", { "data-preview-static": "business-hours-status", style: {
|
|
71
71
|
display: 'inline-flex',
|
|
72
72
|
alignItems: 'center',
|
|
73
73
|
gap: '0.35rem',
|
|
@@ -37,5 +37,5 @@ function LocationCard({ title = 'Our Location', titleFieldPath, address, city, c
|
|
|
37
37
|
alignItems: 'center',
|
|
38
38
|
justifyContent: 'center',
|
|
39
39
|
};
|
|
40
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: `deneb-location-card ${className}`.trim(), style: cardStyles, children: [(0, jsx_runtime_1.jsx)("div", { style: iconCircleStyles, children: (0, jsx_runtime_1.jsxs)("svg", { "data-preview-static": "location-card-icon", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [(0, jsx_runtime_1.jsx)("path", { d: "M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" }), (0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "10", r: "3" })] }) }),
|
|
40
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: `deneb-location-card ${className}`.trim(), style: cardStyles, children: [(0, jsx_runtime_1.jsx)("div", { style: iconCircleStyles, children: (0, jsx_runtime_1.jsxs)("svg", { "data-preview-static": "location-card-icon", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [(0, jsx_runtime_1.jsx)("path", { d: "M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" }), (0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "10", r: "3" })] }) }), (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "h3", id: titleFieldPath || (fieldPath ? `${fieldPath}.title` : 'contact.locationTitle'), defaultValue: title, style: { margin: 0, fontSize: '1.25rem', fontWeight: 600, color: 'var(--color-text, #0f172a)' } }), (0, jsx_runtime_1.jsx)(Address_1.Address, { address: address, city: city, country: country, postalCode: postalCode, fieldPath: fieldPath, addressFieldPath: addressFieldPath }), (0, jsx_runtime_1.jsx)("div", { style: { marginTop: '0.5rem', width: '100%' }, children: (0, jsx_runtime_1.jsx)(MapLink_1.MapLink, { mapUrl: mapUrl, address: address, city: city, country: country, label: directionsLabel, fieldPath: mapUrlFieldPath, variant: "primary", size: "md", style: { width: '100%' } }) })] }));
|
|
41
41
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deneb-ui/ui",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.7",
|
|
4
4
|
"description": "DENEB UI - The premier visual-first React component framework for the modern web. Created by Chamika Gayashan & Induranga Kawishwara.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|