@deneb-ui/ui 2.0.68 → 2.0.69

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.
@@ -102,9 +102,9 @@ function EditableCategoryPills({ categories, fieldPath = 'categories', selectedC
102
102
  whiteSpace: 'nowrap',
103
103
  cursor: 'pointer',
104
104
  transition: 'all 0.2s ease',
105
- border: isSelected ? '1px solid var(--color-primary, #0f172a)' : '1px solid #e2e8f0',
106
- backgroundColor: isSelected ? 'var(--color-primary, #0f172a)' : '#ffffff',
107
- color: isSelected ? '#ffffff' : '#475569',
105
+ border: isSelected ? '1px solid var(--brand-color, var(--color-primary, #0f172a))' : '1px solid var(--color-border, #e2e8f0)',
106
+ backgroundColor: isSelected ? 'var(--brand-color, var(--color-primary, #0f172a))' : 'var(--card-bg, var(--color-surface, #ffffff))',
107
+ color: isSelected ? '#ffffff' : 'var(--color-text-muted, var(--muted-text, #475569))',
108
108
  boxShadow: isSelected ? '0 1px 3px rgba(0,0,0,0.1)' : 'none',
109
109
  }, "data-preview-field-path": `${fieldPath}.${idx}`, "aria-pressed": isSelected, children: cat }, `${cat}-${idx}`));
110
110
  }) }));
@@ -98,10 +98,11 @@ function EditableContactForm({ endpoint = 'https://api.fivora.com/site-contact',
98
98
  width: '100%',
99
99
  padding: '0.75rem 1rem',
100
100
  borderRadius: '10px',
101
- border: '1px solid #cbd5e1',
101
+ border: '1px solid var(--input-border, #cbd5e1)',
102
102
  fontSize: '0.95rem',
103
103
  outline: 'none',
104
- backgroundColor: '#ffffff',
104
+ backgroundColor: 'var(--input-bg, #ffffff)',
105
+ color: 'var(--input-color, var(--page-text, inherit))',
105
106
  boxSizing: 'border-box',
106
107
  } })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "contact-email", "data-preview-field-path": emailLabelPath, style: {
107
108
  display: 'block',
@@ -113,10 +114,11 @@ function EditableContactForm({ endpoint = 'https://api.fivora.com/site-contact',
113
114
  width: '100%',
114
115
  padding: '0.75rem 1rem',
115
116
  borderRadius: '10px',
116
- border: '1px solid #cbd5e1',
117
+ border: '1px solid var(--input-border, #cbd5e1)',
117
118
  fontSize: '0.95rem',
118
119
  outline: 'none',
119
- backgroundColor: '#ffffff',
120
+ backgroundColor: 'var(--input-bg, #ffffff)',
121
+ color: 'var(--input-color, var(--page-text, inherit))',
120
122
  boxSizing: 'border-box',
121
123
  } })] }), showPhone && ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "contact-phone", "data-preview-field-path": phoneLabelPath, style: {
122
124
  display: 'block',
@@ -143,10 +145,11 @@ function EditableContactForm({ endpoint = 'https://api.fivora.com/site-contact',
143
145
  width: '100%',
144
146
  padding: '0.75rem 1rem',
145
147
  borderRadius: '10px',
146
- border: '1px solid #cbd5e1',
148
+ border: '1px solid var(--input-border, #cbd5e1)',
147
149
  fontSize: '0.95rem',
148
150
  outline: 'none',
149
- backgroundColor: '#ffffff',
151
+ backgroundColor: 'var(--input-bg, #ffffff)',
152
+ color: 'var(--input-color, var(--page-text, inherit))',
150
153
  boxSizing: 'border-box',
151
154
  fontFamily: 'inherit',
152
155
  } })] }), (0, jsx_runtime_1.jsx)("button", { type: "submit", disabled: status === 'submitting', style: {
@@ -66,7 +66,9 @@ function EditableDialog({ open = false, onClose, title, description, titleFieldP
66
66
  position: 'relative',
67
67
  width: '100%',
68
68
  maxWidth,
69
- backgroundColor: '#ffffff',
69
+ backgroundColor: 'var(--card-bg, var(--color-surface, #ffffff))',
70
+ color: 'var(--page-text, inherit)',
71
+ border: '1px solid var(--color-border, rgba(0, 0, 0, 0.05))',
70
72
  borderRadius: '20px',
71
73
  boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25), 0 0 0 1px rgba(0, 0, 0, 0.05)',
72
74
  padding: '2rem',
@@ -62,10 +62,10 @@ function EditableNavbar({ defaultLinks = DEFAULT_PAGES, sticky = true, activeRou
62
62
  top: 0,
63
63
  zIndex: 50,
64
64
  width: '100%',
65
- backgroundColor: 'rgba(255, 255, 255, 0.82)',
65
+ backgroundColor: 'var(--header-bg, rgba(255, 255, 255, 0.82))',
66
66
  backdropFilter: 'blur(16px)',
67
67
  WebkitBackdropFilter: 'blur(16px)',
68
- borderBottom: '1px solid rgba(226, 232, 240, 0.8)',
68
+ borderBottom: '1px solid var(--color-border, rgba(226, 232, 240, 0.8))',
69
69
  transition: 'all 0.2s ease',
70
70
  ...style,
71
71
  }, className: `deneb-navbar sticky top-0 z-50 w-full border-b border-slate-200/80 bg-white/80 backdrop-blur-md dark:border-slate-800/80 dark:bg-slate-950/80 ${className}`.trim(), ...props, children: [(0, jsx_runtime_1.jsxs)("div", { style: {
@@ -144,7 +144,7 @@ function EditableNavbar({ defaultLinks = DEFAULT_PAGES, sticky = true, activeRou
144
144
  cursor: 'pointer',
145
145
  }, className: "deneb-mobile-toggle md:hidden flex items-center justify-center w-10 h-10 rounded-lg border border-slate-200 text-slate-700 hover:bg-slate-100 dark:border-slate-800 dark:text-slate-300 dark:hover:bg-slate-800 transition-colors", children: (0, jsx_runtime_1.jsx)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: mobileMenuOpen ? ((0, jsx_runtime_1.jsx)("path", { d: "M18 6L6 18M6 6l12 12" })) : ((0, jsx_runtime_1.jsx)("path", { d: "M4 6h16M4 12h16M4 18h16" })) }) })] })] }), mobileMenuOpen && ((0, jsx_runtime_1.jsxs)("div", { style: {
146
146
  borderTop: '1px solid var(--color-border, #e2e8f0)',
147
- backgroundColor: 'rgba(255, 255, 255, 0.98)',
147
+ backgroundColor: 'var(--card-bg, var(--page-background, rgba(255, 255, 255, 0.98)))',
148
148
  padding: '1.25rem 1.5rem',
149
149
  display: 'flex',
150
150
  flexDirection: 'column',
@@ -170,7 +170,7 @@ function EditableNavbar({ defaultLinks = DEFAULT_PAGES, sticky = true, activeRou
170
170
  }, 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
171
171
  ? 'bg-slate-100 text-slate-900 font-semibold dark:bg-slate-800 dark:text-white'
172
172
  : '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 }) }) }, `mobile-${link.id}`));
173
- }), hasContact ? ((0, jsx_runtime_1.jsx)("span", { "data-target-page": "contact", style: { marginTop: '0.5rem', paddingTop: '0.75rem', borderTop: '1px solid rgba(226,232,240,0.8)' }, children: (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => {
173
+ }), hasContact ? ((0, jsx_runtime_1.jsx)("span", { "data-target-page": "contact", style: { marginTop: '0.5rem', paddingTop: '0.75rem', borderTop: '1px solid var(--color-border, rgba(226, 232, 240, 0.8))' }, children: (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => {
174
174
  setMobileMenuOpen(false);
175
175
  navigate('/contact');
176
176
  }, style: {
@@ -20,8 +20,8 @@ function EditablePricingCard({ itemPath, item, as: Component = 'div', isPopular
20
20
  const popular = item?.isPopular || isPopular;
21
21
  const cardStyle = {
22
22
  position: 'relative',
23
- backgroundColor: popular ? '#ffffff' : 'rgba(255, 255, 255, 0.85)',
24
- border: popular ? '2px solid var(--brand-color, #2563eb)' : '1px solid #e2e8f0',
23
+ backgroundColor: 'var(--card-bg, var(--color-surface, #ffffff))',
24
+ border: popular ? '2px solid var(--brand-color, #2563eb)' : '1px solid var(--card-border, var(--color-border, #e2e8f0))',
25
25
  borderRadius: '20px',
26
26
  padding: '2.5rem 2rem',
27
27
  boxShadow: popular
@@ -67,10 +67,10 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
67
67
  };
68
68
  const variantStyles = {
69
69
  'modern-glass': {
70
- backgroundColor: 'var(--product-card-bg, #0F1424)',
70
+ backgroundColor: 'var(--product-card-bg, var(--card-bg, var(--color-surface, rgba(255, 255, 255, 0.85))))',
71
71
  backdropFilter: 'blur(16px)',
72
72
  WebkitBackdropFilter: 'blur(16px)',
73
- border: '1px solid var(--product-card-border, #1E2638)',
73
+ border: '1px solid var(--product-card-border, var(--card-border, var(--color-border, rgba(226, 232, 240, 0.8))))',
74
74
  borderRadius: '16px',
75
75
  boxShadow: '0 10px 25px -5px rgba(0, 0, 0, 0.4)',
76
76
  overflow: 'hidden',
@@ -79,8 +79,8 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
79
79
  flexDirection: 'column',
80
80
  },
81
81
  classic: {
82
- backgroundColor: '#ffffff',
83
- border: '1px solid #e2e8f0',
82
+ backgroundColor: 'var(--card-bg, var(--color-surface, #ffffff))',
83
+ border: '1px solid var(--card-border, var(--color-border, #e2e8f0))',
84
84
  borderRadius: '14px',
85
85
  boxShadow: '0 1px 3px 0 rgba(0, 0, 0, 0.05)',
86
86
  overflow: 'hidden',
@@ -96,8 +96,8 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
96
96
  flexDirection: 'column',
97
97
  },
98
98
  horizontal: {
99
- backgroundColor: '#ffffff',
100
- border: '1px solid #e2e8f0',
99
+ backgroundColor: 'var(--card-bg, var(--color-surface, #ffffff))',
100
+ border: '1px solid var(--card-border, var(--color-border, #e2e8f0))',
101
101
  borderRadius: '16px',
102
102
  overflow: 'hidden',
103
103
  display: 'flex',
@@ -131,8 +131,8 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
131
131
  fontWeight: 700,
132
132
  letterSpacing: '0.08em',
133
133
  textTransform: 'uppercase',
134
- color: '#94a3b8',
135
- backgroundColor: 'rgba(30, 41, 59, 0.8)',
134
+ color: 'var(--tag-color, var(--muted-text, var(--color-muted, #64748b)))',
135
+ backgroundColor: 'var(--tag-bg, var(--color-secondary, rgba(241, 245, 249, 0.9)))',
136
136
  padding: '2px 8px',
137
137
  borderRadius: '6px',
138
138
  } })) : null] }), (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "h3", id: `${itemPath}.name`, "data-preview-field-path": `${itemPath}.name`, defaultValue: name, style: {
@@ -153,7 +153,7 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
153
153
  } })) : null] }), (0, jsx_runtime_1.jsxs)("div", { style: {
154
154
  marginTop: '0.75rem',
155
155
  paddingTop: '0.75rem',
156
- borderTop: cardVariant === 'minimal' ? 'none' : '1px solid rgba(51, 65, 85, 0.6)',
156
+ borderTop: cardVariant === 'minimal' ? 'none' : '1px solid var(--card-border, var(--color-border, rgba(226, 232, 240, 0.7)))',
157
157
  display: 'flex',
158
158
  flexDirection: 'column',
159
159
  gap: '0.75rem',
@@ -191,8 +191,8 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
191
191
  transition: 'all 0.2s ease',
192
192
  boxShadow: '0 2px 8px rgba(37, 211, 102, 0.25)',
193
193
  }, className: "hover:brightness-105 active:scale-95", children: [(0, jsx_runtime_1.jsx)(WhatsAppIcon, {}), (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.whatsappButtonText`, "data-preview-field-path": `${itemPath}.whatsappButtonText`, defaultValue: resolvedWhatsAppText, style: { color: '#ffffff', fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' } })] })), showAddToCartButton && ((0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: handleAddToCartClick, title: "Add this product to shopping cart", style: {
194
- backgroundColor: 'var(--brand-color, #2563eb)',
195
- color: '#ffffff',
194
+ backgroundColor: 'var(--button-bg, var(--brand-color, #2563eb))',
195
+ color: 'var(--button-text, #ffffff)',
196
196
  border: 'none',
197
197
  padding: '0.55rem 0.75rem',
198
198
  borderRadius: '10px',
@@ -205,5 +205,5 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
205
205
  gap: '0.375rem',
206
206
  transition: 'all 0.2s ease',
207
207
  boxShadow: '0 2px 8px rgba(37, 99, 235, 0.25)',
208
- }, className: "hover:brightness-105 active:scale-95", children: [(0, jsx_runtime_1.jsx)(CartIcon, {}), (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.addToCartButtonText`, "data-preview-field-path": `${itemPath}.addToCartButtonText`, defaultValue: resolvedAddToCartText, style: { color: '#ffffff', fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' } })] }))] }))] })] })] }));
208
+ }, className: "hover:brightness-105 active:scale-95", children: [(0, jsx_runtime_1.jsx)(CartIcon, {}), (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.addToCartButtonText`, "data-preview-field-path": `${itemPath}.addToCartButtonText`, defaultValue: resolvedAddToCartText, style: { color: 'var(--button-text, #ffffff)', fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' } })] }))] }))] })] })] }));
209
209
  }
@@ -11,8 +11,8 @@ function EditableTestimonialCard({ itemPath, item, as: Component = 'div', classN
11
11
  const avatar = String(item?.avatar || '');
12
12
  const rating = Number(item?.rating || 5);
13
13
  const cardStyle = {
14
- backgroundColor: 'var(--color-surface, #ffffff)',
15
- border: '1px solid var(--color-border, #f1f5f9)',
14
+ backgroundColor: 'var(--card-bg, var(--color-surface, #ffffff))',
15
+ border: '1px solid var(--card-border, var(--color-border, #f1f5f9))',
16
16
  borderRadius: '16px',
17
17
  padding: '2rem',
18
18
  boxShadow: 'var(--card-shadow, 0 4px 20px -2px rgba(0, 0, 0, 0.04))',
@@ -251,37 +251,37 @@ function EditableButton({ id, 'data-preview-field-path': previewFieldPath, defau
251
251
  };
252
252
  const variantStyles = {
253
253
  primary: {
254
- backgroundColor: 'var(--brand-color, #2563eb)',
255
- color: '#ffffff',
254
+ backgroundColor: 'var(--button-bg, var(--brand-color, #2563eb))',
255
+ color: 'var(--button-text, #ffffff)',
256
256
  border: 'none',
257
257
  boxShadow: '0 4px 14px 0 rgba(37, 99, 235, 0.35)',
258
258
  },
259
259
  secondary: {
260
- backgroundColor: 'var(--brand-secondary, #0f172a)',
261
- color: '#ffffff',
262
- border: 'none',
260
+ backgroundColor: 'var(--button-secondary-bg, var(--color-secondary, var(--brand-secondary, #0f172a)))',
261
+ color: 'var(--button-secondary-text, var(--color-text, #ffffff))',
262
+ border: '1px solid var(--button-secondary-border, var(--color-border, transparent))',
263
263
  },
264
264
  accent: {
265
265
  backgroundColor: 'var(--brand-accent, #14b8a6)',
266
- color: '#ffffff',
266
+ color: 'var(--button-accent-text, #ffffff)',
267
267
  border: 'none',
268
268
  },
269
269
  outline: {
270
270
  backgroundColor: 'transparent',
271
- color: 'var(--page-text, #0f172a)',
272
- border: '1.5px solid currentColor',
271
+ color: 'var(--button-outline-text, var(--color-text, var(--page-text, #0f172a)))',
272
+ border: '1.5px solid var(--button-outline-border, var(--color-border, currentColor))',
273
273
  },
274
274
  ghost: {
275
275
  backgroundColor: 'transparent',
276
- color: 'var(--page-text, #0f172a)',
276
+ color: 'var(--button-ghost-text, var(--color-text, var(--page-text, #0f172a)))',
277
277
  border: 'none',
278
278
  },
279
279
  glass: {
280
- backgroundColor: 'rgba(255, 255, 255, 0.25)',
280
+ backgroundColor: 'var(--glass-bg, rgba(255, 255, 255, 0.15))',
281
281
  backdropFilter: 'blur(12px)',
282
282
  WebkitBackdropFilter: 'blur(12px)',
283
- color: 'var(--page-text, #0f172a)',
284
- border: '1px solid rgba(255, 255, 255, 0.4)',
283
+ color: 'var(--color-text, var(--page-text, #0f172a))',
284
+ border: '1px solid var(--card-border, rgba(255, 255, 255, 0.2))',
285
285
  },
286
286
  };
287
287
  const baseStyle = {
@@ -59,6 +59,8 @@ export type SiteData = {
59
59
  };
60
60
  export declare const SiteDataContext: React.Context<SiteData>;
61
61
  export declare function isRecord(value: unknown): value is GenericRecord;
62
+ export declare function isDarkColor(color?: unknown): boolean;
63
+ export declare function syncThemeToDocument(theme: unknown): void;
62
64
  export declare function mergeSiteData(current: unknown, incoming: unknown, depth?: number, seen?: WeakSet<object>): unknown;
63
65
  export declare function normalizeOrigin(value?: string | null, baseOrigin?: string | null): string | null;
64
66
  /**
@@ -3,6 +3,8 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.DenebDataContext = exports.useDenebData = exports.DenebDataProvider = exports.SiteDataContext = exports.DENEB_STYLE_PATCH_MESSAGE = exports.STYLE_PATCH_MESSAGE = exports.PREVIEW_FIELD_ATTRIBUTE = exports.LEGACY_PREVIEW_FOCUS_MESSAGE = exports.PREVIEW_FOCUS_MESSAGE = exports.DENEB_PREVIEW_FOCUS_MESSAGE = exports.LEGACY_PREVIEW_READY_MESSAGE = exports.PREVIEW_READY_MESSAGE = exports.DENEB_PREVIEW_READY_MESSAGE = exports.LEGACY_PREVIEW_DATA_MESSAGE = exports.PREVIEW_DATA_MESSAGE = exports.DENEB_PREVIEW_DATA_MESSAGE = void 0;
5
5
  exports.isRecord = isRecord;
6
+ exports.isDarkColor = isDarkColor;
7
+ exports.syncThemeToDocument = syncThemeToDocument;
6
8
  exports.mergeSiteData = mergeSiteData;
7
9
  exports.normalizeOrigin = normalizeOrigin;
8
10
  exports.resolveParentOrigin = resolveParentOrigin;
@@ -52,6 +54,54 @@ exports.SiteDataContext = (0, react_1.createContext)({});
52
54
  function isRecord(value) {
53
55
  return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
54
56
  }
57
+ function isDarkColor(color) {
58
+ if (typeof color !== "string" || !color)
59
+ return false;
60
+ const hex = color.trim().toLowerCase();
61
+ if (!/^#[0-9a-f]{3,6}$/.test(hex))
62
+ return false;
63
+ const fullHex = hex.length === 4
64
+ ? "#" + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3]
65
+ : hex;
66
+ const r = Number.parseInt(fullHex.slice(1, 3), 16);
67
+ const g = Number.parseInt(fullHex.slice(3, 5), 16);
68
+ const b = Number.parseInt(fullHex.slice(5, 7), 16);
69
+ return (r * 299 + g * 587 + b * 114) / 1000 < 130;
70
+ }
71
+ function syncThemeToDocument(theme) {
72
+ if (typeof document === "undefined" || !isRecord(theme))
73
+ return;
74
+ const rootStyle = document.documentElement.style;
75
+ if (typeof theme.primaryColor === "string") {
76
+ rootStyle.setProperty("--brand-primary", theme.primaryColor);
77
+ rootStyle.setProperty("--brand-color", theme.primaryColor);
78
+ rootStyle.setProperty("--color-primary", theme.primaryColor);
79
+ const isPrimaryDark = isDarkColor(theme.primaryColor);
80
+ const autoBtnText = isPrimaryDark ? "#ffffff" : "#0f172a";
81
+ rootStyle.setProperty("--button-bg", String(theme.buttonBackgroundColor || theme.primaryColor));
82
+ rootStyle.setProperty("--button-text", String(theme.buttonTextColor || autoBtnText));
83
+ }
84
+ if (typeof theme.secondaryColor === "string") {
85
+ rootStyle.setProperty("--brand-secondary", theme.secondaryColor);
86
+ }
87
+ if (typeof theme.accentColor === "string") {
88
+ rootStyle.setProperty("--brand-accent", theme.accentColor);
89
+ rootStyle.setProperty("--color-accent", theme.accentColor);
90
+ }
91
+ if (typeof theme.backgroundColor === "string") {
92
+ const isDark = isDarkColor(theme.backgroundColor);
93
+ document.documentElement.classList.toggle("dark", isDark);
94
+ document.documentElement.setAttribute("data-theme", isDark ? "dark" : "light");
95
+ rootStyle.colorScheme = isDark ? "dark" : "light";
96
+ rootStyle.setProperty("--page-background", theme.backgroundColor);
97
+ rootStyle.setProperty("--card-bg", isDark ? "#111a2e" : "#ffffff");
98
+ rootStyle.setProperty("--product-card-bg", isDark ? "#111a2e" : "#ffffff");
99
+ rootStyle.setProperty("--color-surface", isDark ? "rgba(255,255,255,0.05)" : "#ffffff");
100
+ rootStyle.setProperty("--color-secondary", isDark ? "rgba(255,255,255,0.08)" : "#f1f5f9");
101
+ rootStyle.setProperty("--button-secondary-bg", isDark ? "rgba(255,255,255,0.08)" : "#f1f5f9");
102
+ rootStyle.setProperty("--button-secondary-text", isDark ? "#f8fafc" : "#0f172a");
103
+ }
104
+ }
55
105
  function mergeSiteData(current, incoming, depth = 0, seen = new WeakSet()) {
56
106
  if (depth > 50)
57
107
  return incoming;
@@ -237,16 +287,7 @@ function SiteDataProvider({ children, initialSiteData, fallbackSiteData, liveCat
237
287
  });
238
288
  // Dynamic theme variable injection for instant color updates
239
289
  if (isRecord(live.theme)) {
240
- const rootStyle = document.documentElement.style;
241
- if (typeof live.theme.primaryColor === "string") {
242
- rootStyle.setProperty("--brand-primary", live.theme.primaryColor);
243
- }
244
- if (typeof live.theme.secondaryColor === "string") {
245
- rootStyle.setProperty("--brand-secondary", live.theme.secondaryColor);
246
- }
247
- if (typeof live.theme.accentColor === "string") {
248
- rootStyle.setProperty("--brand-accent", live.theme.accentColor);
249
- }
290
+ syncThemeToDocument(live.theme);
250
291
  }
251
292
  };
252
293
  const loadLiveCatalog = async (attempt = 0) => {
@@ -312,6 +353,17 @@ function SiteDataProvider({ children, initialSiteData, fallbackSiteData, liveCat
312
353
  if (!isRecord(incoming))
313
354
  return;
314
355
  setSiteData((current) => mergeSiteData(current, incoming));
356
+ try {
357
+ const inc = incoming;
358
+ const theme = (isRecord(inc.template) && isRecord(inc.template.structure))
359
+ ? inc.template.structure?.theme
360
+ : inc.theme;
361
+ if (theme)
362
+ syncThemeToDocument(theme);
363
+ }
364
+ catch {
365
+ // Best-effort
366
+ }
315
367
  try {
316
368
  window[SITE_DATA_GLOBAL_KEY] =
317
369
  incoming;
@@ -71,10 +71,10 @@ function StickyMobileBar({ fieldPath, actions, showOnDesktop = false, className
71
71
  }
72
72
  };
73
73
  return ((0, jsx_runtime_1.jsx)("aside", { className: `deneb-sticky-mobile-bar fixed bottom-0 left-0 right-0 z-50 p-2 sm:p-3 transition-transform duration-300 ${showOnDesktop ? 'block' : 'lg:hidden'} ${className}`, "data-preview-field-path": fieldPath, style: {
74
- backgroundColor: 'rgba(255, 255, 255, 0.92)',
74
+ backgroundColor: 'var(--header-bg, var(--card-bg, rgba(255, 255, 255, 0.92)))',
75
75
  backdropFilter: 'blur(12px)',
76
76
  WebkitBackdropFilter: 'blur(12px)',
77
- borderTop: '1px solid rgba(226, 232, 240, 0.8)',
77
+ borderTop: '1px solid var(--color-border, rgba(226, 232, 240, 0.8))',
78
78
  boxShadow: '0 -4px 20px rgba(0, 0, 0, 0.08)',
79
79
  ...style,
80
80
  }, children: (0, jsx_runtime_1.jsx)("div", { className: "max-w-md mx-auto flex items-center justify-between gap-2", children: resolvedActions.map((action) => {
@@ -15,6 +15,8 @@ export interface TemplateTheme {
15
15
  bodyFont?: string;
16
16
  borderRadius?: string;
17
17
  align?: 'left' | 'center' | 'right';
18
+ buttonBackgroundColor?: string;
19
+ buttonTextColor?: string;
18
20
  [key: string]: unknown;
19
21
  }
20
22
  /**
@@ -5,6 +5,7 @@ exports.getCategoryTheme = getCategoryTheme;
5
5
  exports.getThemeCssProperties = getThemeCssProperties;
6
6
  exports.ThemeStyles = ThemeStyles;
7
7
  const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const core_1 = require("@deneb-ui/core");
8
9
  const ResponsiveBaseStyles_1 = require("./ResponsiveBaseStyles");
9
10
  /**
10
11
  * Pre-configured, high-converting theme presets tailored for different business categories.
@@ -144,15 +145,30 @@ function getThemeCssProperties(theme) {
144
145
  }
145
146
  }
146
147
  }
148
+ const isDark = (0, core_1.isDarkColor)(theme?.backgroundColor);
149
+ const bgColor = theme?.backgroundColor || (isDark ? '#0f172a' : '#ffffff');
150
+ const textColor = theme?.textColor || (isDark ? '#f8fafc' : '#0f172a');
151
+ const mutedColor = theme?.mutedTextColor || (isDark ? 'rgba(248, 250, 252, 0.7)' : '#64748b');
152
+ const borderColor = isDark ? 'rgba(255, 255, 255, 0.1)' : '#e2e8f0';
153
+ const cardBg = isDark ? '#111a2e' : '#ffffff';
154
+ const cardBorder = isDark ? 'rgba(255, 255, 255, 0.09)' : '#e2e8f0';
155
+ const primaryColor = theme?.primaryColor || '#2563eb';
156
+ const buttonBg = String(theme?.buttonBackgroundColor || primaryColor || '#2563eb');
157
+ const autoButtonText = (0, core_1.getAutoContrastTextColor)(buttonBg);
158
+ const buttonText = String(theme?.buttonTextColor || autoButtonText);
159
+ const buttonSecondaryBg = isDark
160
+ ? 'rgba(255, 255, 255, 0.08)'
161
+ : (theme?.secondaryColor && !(0, core_1.isDarkColor)(theme.secondaryColor) ? theme.secondaryColor : '#f1f5f9');
162
+ const buttonSecondaryText = isDark ? '#f8fafc' : '#0f172a';
147
163
  return {
148
- '--brand-color': theme?.primaryColor || '#2563eb',
149
- '--brand-secondary': theme?.secondaryColor || '#0f172a',
164
+ '--brand-color': primaryColor,
165
+ '--brand-secondary': theme?.secondaryColor || (isDark ? '#1e293b' : '#0f172a'),
150
166
  '--brand-accent': theme?.accentColor || '#14b8a6',
151
- '--page-background': theme?.backgroundColor || '#ffffff',
152
- '--page-text': theme?.textColor || '#0f172a',
153
- '--heading-color': theme?.headingColor || theme?.secondaryColor || '#0f172a',
154
- '--muted-text': theme?.mutedTextColor || '#64748b',
155
- '--link-color': theme?.linkColor || theme?.primaryColor || '#2563eb',
167
+ '--page-background': bgColor,
168
+ '--page-text': textColor,
169
+ '--heading-color': theme?.headingColor || (isDark ? '#ffffff' : theme?.secondaryColor || '#0f172a'),
170
+ '--muted-text': mutedColor,
171
+ '--link-color': theme?.linkColor || primaryColor,
156
172
  '--hero-min-height': theme?.heroMinHeight || '72vh',
157
173
  '--section-padding': theme?.sectionPadding || '5rem',
158
174
  '--base-size': theme?.baseSize || '16px',
@@ -160,6 +176,35 @@ function getThemeCssProperties(theme) {
160
176
  '--body-font': theme?.bodyFont || 'Inter, sans-serif',
161
177
  '--border-radius': theme?.borderRadius || '8px',
162
178
  '--content-align': theme?.align || 'left',
179
+ // Canonical color system tokens for light & dark mode harmony
180
+ '--color-primary': primaryColor,
181
+ '--color-secondary': buttonSecondaryBg,
182
+ '--color-accent': theme?.accentColor || '#14b8a6',
183
+ '--color-text': textColor,
184
+ '--color-text-muted': mutedColor,
185
+ '--color-border': borderColor,
186
+ '--color-surface': isDark ? 'rgba(255,255,255,0.05)' : '#ffffff',
187
+ '--card-bg': cardBg,
188
+ '--card-border': cardBorder,
189
+ '--product-card-bg': cardBg,
190
+ '--product-card-border': cardBorder,
191
+ '--tag-bg': isDark ? 'rgba(255, 255, 255, 0.08)' : 'rgba(241, 245, 249, 0.9)',
192
+ '--tag-color': mutedColor,
193
+ '--card-shadow': isDark ? '0 10px 25px -5px rgba(0, 0, 0, 0.4)' : '0 10px 25px -5px rgba(0, 0, 0, 0.05)',
194
+ '--header-bg': isDark ? 'rgba(15, 23, 42, 0.85)' : 'rgba(255, 255, 255, 0.82)',
195
+ '--input-bg': isDark ? '#1e293b' : '#ffffff',
196
+ '--input-border': isDark ? 'rgba(255, 255, 255, 0.15)' : '#cbd5e1',
197
+ '--input-color': textColor,
198
+ // Dedicated Button Design Tokens
199
+ '--button-bg': buttonBg,
200
+ '--button-text': buttonText,
201
+ '--button-primary-bg': buttonBg,
202
+ '--button-primary-text': buttonText,
203
+ '--button-secondary-bg': buttonSecondaryBg,
204
+ '--button-secondary-text': buttonSecondaryText,
205
+ '--button-outline-border': isDark ? 'rgba(255, 255, 255, 0.22)' : 'currentColor',
206
+ '--button-outline-text': isDark ? '#f8fafc' : textColor,
207
+ '--button-ghost-text': isDark ? '#f8fafc' : textColor,
163
208
  fontFamily: theme?.bodyFont || 'Inter, sans-serif',
164
209
  ...customVars,
165
210
  };
@@ -58,22 +58,23 @@ function ContactButton({ type = 'whatsapp', value, href, label, children, fieldP
58
58
  };
59
59
  const variantStyles = {
60
60
  primary: {
61
- backgroundColor: 'var(--color-primary, #0f172a)',
62
- color: '#ffffff',
61
+ backgroundColor: 'var(--button-bg, var(--color-primary, #0f172a))',
62
+ color: 'var(--button-text, #ffffff)',
63
63
  boxShadow: '0 1px 2px rgba(0,0,0,0.05)',
64
64
  },
65
65
  secondary: {
66
- backgroundColor: 'var(--color-secondary, #f1f5f9)',
67
- color: 'var(--color-text, #0f172a)',
66
+ backgroundColor: 'var(--button-secondary-bg, var(--color-secondary, #f1f5f9))',
67
+ color: 'var(--button-secondary-text, var(--color-text, #0f172a))',
68
+ border: '1px solid var(--button-secondary-border, var(--color-border, transparent))',
68
69
  },
69
70
  outline: {
70
71
  backgroundColor: 'transparent',
71
- border: '1px solid var(--color-border, #e2e8f0)',
72
- color: 'var(--color-text, #0f172a)',
72
+ border: '1px solid var(--button-outline-border, var(--color-border, #e2e8f0))',
73
+ color: 'var(--button-outline-text, var(--color-text, #0f172a))',
73
74
  },
74
75
  ghost: {
75
76
  backgroundColor: 'transparent',
76
- color: 'var(--color-text, #0f172a)',
77
+ color: 'var(--button-ghost-text, var(--color-text, #0f172a))',
77
78
  },
78
79
  whatsapp: {
79
80
  backgroundColor: '#25D366',
@@ -58,10 +58,11 @@ function FloatingContactWidget({ fieldPath = 'contact', defaultPhone, defaultWha
58
58
  [isRight ? 'right' : 'left']: '0',
59
59
  width: 'min(18rem, calc(100vw - 2rem))',
60
60
  maxWidth: 'calc(100vw - 2rem)',
61
- backgroundColor: '#ffffff',
61
+ backgroundColor: 'var(--card-bg, var(--color-surface, #ffffff))',
62
+ color: 'var(--page-text, inherit)',
62
63
  borderRadius: '1rem',
63
64
  boxShadow: '0 20px 25px -5px rgba(0, 0, 0, 0.15), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
64
- border: '1px solid rgba(226, 232, 240, 0.8)',
65
+ border: '1px solid var(--color-border, rgba(226, 232, 240, 0.8))',
65
66
  overflow: 'hidden',
66
67
  animation: 'deneb-pop 0.2s cubic-bezier(0.16, 1, 0.3, 1)',
67
68
  };
package/dist/index.d.ts CHANGED
@@ -94,3 +94,5 @@ export { PlatformAdditionalPages, AdditionalPagesNav } from './PlatformAdditiona
94
94
  export declare const DENEB_FRAMEWORK_NAME = "DENEB UI";
95
95
  export declare const DENEB_FRAMEWORK_VERSION = "2.0.0";
96
96
  export declare const DENEB_AUTHOR = "Chamika Gayashan & Induranga Kawishwara";
97
+ export { THEME_PALETTES, GLOBAL_FONT_OPTIONS, FONT_PAIRINGS, isDarkColor, getAutoContrastTextColor, toHexColor, normalizeHexColor, parseVisualCustomization, customizationToTheme, mergeVisualCustomizationIntoTheme, generateThemeVariables, } from '@deneb-ui/core';
98
+ export type { ThemePalette, FontPairing, GlobalFontOption, VisualCustomization, VisualCustomizationColors, VisualCustomizationTypography, VisualCustomizationSpacing, VisualCustomizationLayout, VisualCustomizationComponents, VisualCustomizationSectionOverride, VisualCustomizationElementStyle, TemplateThemeShape, } from '@deneb-ui/core';
package/dist/index.js CHANGED
@@ -19,7 +19,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
21
  exports.FAQ = exports.Accordion = exports.Testimonials = exports.TestimonialSection = exports.TestimonialCard = exports.PricingCard = exports.ServiceCard = exports.GoogleFeedback = exports.CustomerReviews = exports.ProductDetail = exports.ProductShowcase = exports.ProductGrid = exports.ProductCard = exports.List = exports.Box = exports.Section = exports.Grid = exports.Map = exports.Image = exports.Quote = exports.Badge = exports.Paragraph = exports.Heading = exports.Text = exports.Dialog = exports.Card = exports.Button = exports.collectStyleTargetsFromHtml = exports.validateStyleTree = exports.styleToCssVariables = exports.patchStyleByPath = exports.patchElementStyle = exports.STYLE_TYPE_ATTRIBUTE = exports.STYLE_TARGET_ATTRIBUTE = exports.DENEB_STYLE_PATCH_MESSAGE = exports.STYLE_PATCH_MESSAGE = exports.formatResponsiveFontSize = exports.resolveInstallableFont = exports.normalizeFontId = exports.lookupFontDefinition = exports.listFontsByCategory = exports.collectFontIdsFromSiteData = exports.buildGoogleFontsStylesheetUrl = exports.DENEB_GOOGLE_FONT_COUNT = exports.DENEB_FONT_REGISTRY = exports.useDenebFonts = exports.DENEB_FONTS_LINK_ID = exports.FontLoader = exports.DenebComponentStyles = exports.ResponsiveBaseStyles = void 0;
22
- exports.DENEB_AUTHOR = exports.DENEB_FRAMEWORK_VERSION = exports.DENEB_FRAMEWORK_NAME = exports.AdditionalPagesNav = exports.PlatformAdditionalPages = exports.FilterSidebar = exports.CartDrawer = exports.CategoryPills = exports.AnnouncementBar = exports.HeroSplit = exports.Hero = exports.Footer = exports.Header = exports.Navbar = exports.ContactForm = void 0;
22
+ exports.generateThemeVariables = exports.mergeVisualCustomizationIntoTheme = exports.customizationToTheme = exports.parseVisualCustomization = exports.normalizeHexColor = exports.toHexColor = exports.getAutoContrastTextColor = exports.isDarkColor = exports.FONT_PAIRINGS = exports.GLOBAL_FONT_OPTIONS = exports.THEME_PALETTES = exports.DENEB_AUTHOR = exports.DENEB_FRAMEWORK_VERSION = exports.DENEB_FRAMEWORK_NAME = exports.AdditionalPagesNav = exports.PlatformAdditionalPages = exports.FilterSidebar = exports.CartDrawer = exports.CategoryPills = exports.AnnouncementBar = exports.HeroSplit = exports.Hero = exports.Footer = exports.Header = exports.Navbar = exports.ContactForm = void 0;
23
23
  __exportStar(require("./PreviewField"), exports);
24
24
  __exportStar(require("./EditableText"), exports);
25
25
  __exportStar(require("./EditableImage"), exports);
@@ -176,3 +176,15 @@ Object.defineProperty(exports, "AdditionalPagesNav", { enumerable: true, get: fu
176
176
  exports.DENEB_FRAMEWORK_NAME = 'DENEB UI';
177
177
  exports.DENEB_FRAMEWORK_VERSION = '2.0.0';
178
178
  exports.DENEB_AUTHOR = 'Chamika Gayashan & Induranga Kawishwara';
179
+ var core_3 = require("@deneb-ui/core");
180
+ Object.defineProperty(exports, "THEME_PALETTES", { enumerable: true, get: function () { return core_3.THEME_PALETTES; } });
181
+ Object.defineProperty(exports, "GLOBAL_FONT_OPTIONS", { enumerable: true, get: function () { return core_3.GLOBAL_FONT_OPTIONS; } });
182
+ Object.defineProperty(exports, "FONT_PAIRINGS", { enumerable: true, get: function () { return core_3.FONT_PAIRINGS; } });
183
+ Object.defineProperty(exports, "isDarkColor", { enumerable: true, get: function () { return core_3.isDarkColor; } });
184
+ Object.defineProperty(exports, "getAutoContrastTextColor", { enumerable: true, get: function () { return core_3.getAutoContrastTextColor; } });
185
+ Object.defineProperty(exports, "toHexColor", { enumerable: true, get: function () { return core_3.toHexColor; } });
186
+ Object.defineProperty(exports, "normalizeHexColor", { enumerable: true, get: function () { return core_3.normalizeHexColor; } });
187
+ Object.defineProperty(exports, "parseVisualCustomization", { enumerable: true, get: function () { return core_3.parseVisualCustomization; } });
188
+ Object.defineProperty(exports, "customizationToTheme", { enumerable: true, get: function () { return core_3.customizationToTheme; } });
189
+ Object.defineProperty(exports, "mergeVisualCustomizationIntoTheme", { enumerable: true, get: function () { return core_3.mergeVisualCustomizationIntoTheme; } });
190
+ Object.defineProperty(exports, "generateThemeVariables", { enumerable: true, get: function () { return core_3.generateThemeVariables; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deneb-ui/ui",
3
- "version": "2.0.68",
3
+ "version": "2.0.69",
4
4
  "description": "Visual-first React component library for editable commerce storefronts. Built for Next.js and Fivora.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -50,7 +50,7 @@
50
50
  ],
51
51
  "license": "MIT",
52
52
  "dependencies": {
53
- "@deneb-ui/core": "^2.0.68"
53
+ "@deneb-ui/core": "^2.0.69"
54
54
  },
55
55
  "peerDependencies": {
56
56
  "react": "^18.0.0 || ^19.0.0",
@@ -68,6 +68,10 @@
68
68
  "require": "./dist/index.js",
69
69
  "default": "./dist/index.js"
70
70
  },
71
- "./platform-contract": "./platform-contract.json"
71
+ "./platform-contract": "./platform-contract.json",
72
+ "./theme": {
73
+ "types": "./dist/index.d.ts",
74
+ "default": "./dist/index.js"
75
+ }
72
76
  }
73
77
  }