@deneb-ui/ui 2.0.22 → 2.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,182 +1,104 @@
1
- # DENEB
2
-
3
- ### A modern UI system for the web.
4
-
5
- > **DENEB UI — Build beautiful interfaces, effortlessly.**
6
- > The premier visual-first React component ecosystem.
7
- > Proudly presented by **DENEB-UI Collaborate with FIVORA**.
8
-
9
- [![Framework: DENEB UI](https://img.shields.io/badge/Framework-DENEB_UI_v2.0-blue.svg)](https://github.com/deneb-ui/ui)
10
- [![License: MIT](https://img.shields.io/badge/License-MIT-orange.svg)](https://opensource.org/licenses/MIT)
1
+ <p align="center">
2
+ <a href="https://deneb.fivora.site">
3
+ <img src="https://img.shields.io/badge/DENEB_UI-Visual--First_React_Components-6366F1?style=for-the-badge&labelColor=0f172a" alt="DENEB UI" />
4
+ </a>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/@deneb-ui/ui"><img src="https://img.shields.io/npm/v/@deneb-ui/ui.svg?style=flat-square&color=6366F1" alt="npm version" /></a>
9
+ <a href="https://www.npmjs.com/package/@deneb-ui/ui"><img src="https://img.shields.io/npm/dm/@deneb-ui/ui.svg?style=flat-square&color=6366F1" alt="npm downloads" /></a>
10
+ <img src="https://img.shields.io/badge/React-18%20%7C%2019-61DAFB?style=flat-square&logo=react&logoColor=white" alt="React" />
11
+ <img src="https://img.shields.io/badge/TypeScript-Ready-3178C6?style=flat-square&logo=typescript&logoColor=white" alt="TypeScript" />
12
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-emerald?style=flat-square" alt="MIT License" /></a>
13
+ </p>
14
+
15
+ <p align="center">
16
+ <strong>Build beautiful, editable storefronts — on mobile, tablet, and desktop.</strong><br />
17
+ The visual-first React component library for Next.js commerce and Fivora live editing.
18
+ </p>
19
+
20
+ <p align="center">
21
+ <a href="https://deneb.fivora.site/docs/introduction"><strong>Documentation</strong></a> ·
22
+ <a href="https://deneb.fivora.site/docs/components/button"><strong>Components</strong></a> ·
23
+ <a href="https://deneb.fivora.site/docs/responsive-design"><strong>Responsive Design</strong></a> ·
24
+ <a href="https://github.com/deneb-ui/core"><strong>GitHub</strong></a>
25
+ </p>
11
26
 
12
27
  ---
13
28
 
14
- ## Quick Installation
29
+ ## Getting Started
30
+
31
+ ### Install
15
32
 
16
33
  ```bash
17
34
  npm install @deneb-ui/ui
18
- # Or with yarn / pnpm
19
- pnpm add @deneb-ui/ui
35
+ # pnpm add @deneb-ui/ui
36
+ # yarn add @deneb-ui/ui
20
37
  ```
21
38
 
22
- ```tsx
23
- import {
24
- Button,
25
- Card,
26
- Dialog,
27
- ContactActions,
28
- WhatsAppButton,
29
- LocationCard,
30
- SocialLinks,
31
- BusinessHours,
32
- } from "@deneb-ui/ui";
33
- ```
39
+ ### Minimal example
34
40
 
35
- ---
36
-
37
- ## What is DENEB UI?
38
-
39
- **DENEB UI** is a modern, modular design system and component framework engineered specifically for live visual editing, dynamic theming, and high-converting commerce storefronts.
40
-
41
- Every component in DENEB UI:
42
- - **Zero-Breakage Visual Editing**: Automatically connects to the bidirectional live editor protocol (`DENEB_PREVIEW_SITE_DATA` / `FIVORA_PREVIEW_SITE_DATA`, `DENEB_PREVIEW_READY`, `DENEB_PREVIEW_FOCUS_PAGE`).
43
- - **Auto-Balancing Layouts**: Columns and card heights automatically adapt across desktop, tablet, and mobile regardless of content length.
44
- - **Smart Contact & Location Actions**: One-click WhatsApp, call, email, and Google Maps generation from raw phone numbers and addresses.
45
- - **Dynamic Tokenized Theming**: Fully integrated with tokenized custom properties (`--color-primary`, `--color-secondary`, fonts, spacing) and AI-assisted restyling.
46
- - **Selected-Page Route Guard**: Automatically respects `requirements.requiredPages`, ensuring zero dead links or validation warnings.
41
+ ```tsx
42
+ import { SiteDataProvider, Navbar, Hero, Footer, Grid, ProductCard } from "@deneb-ui/ui";
43
+ import siteData from "@/data/site-data.json";
47
44
 
48
- ---
45
+ export default function Page() {
46
+ return (
47
+ <SiteDataProvider initialSiteData={siteData}>
48
+ <Navbar />
49
+ <Hero />
50
+ <Grid columns={{ mobile: 1, tablet: 2, desktop: 3 }} gap="lg">
51
+ {/* ProductCard items */}
52
+ </Grid>
53
+ <Footer />
54
+ </SiteDataProvider>
55
+ );
56
+ }
57
+ ```
49
58
 
50
- ## Component Catalog
51
-
52
- ### 1. Smart Template & Action Components
53
- - `<ContactActions />` — Auto-detects and renders active communication channels (`phone`, `whatsapp`, `email`). When a merchant adds a phone number in `site-data.json`, the button appears automatically with zero template changes.
54
- - `<WhatsAppButton />` — One-click WhatsApp click-to-chat button with built-in SVG icon and automatic `https://wa.me/...` URL generation from raw phone numbers.
55
- - `<PhoneButton />` — One-click calling button with `tel:` handler and raw number editing bindings.
56
- - `<EmailButton />` — One-click email button with `mailto:` handler and optional subject lines.
57
- - `<ContactButton />` — Base unified action button supporting WhatsApp, phone, email, and forms.
58
- - `<LocationCard />` — High-converting location card with pin icon, formatted address, and Google Maps directions button.
59
- - `<LocationLink />` — Semantic address display paired with a "Get Directions" action.
60
- - `<MapLink />` — Direct link button to open Google Maps directions or search queries.
61
- - `<MapEmbed />` — Responsive map embed iframe with safe graceful fallback to `MapLink` when embed URLs are unconfigured.
62
- - `<Address />` — Structured `<address>` component with individual street, locality, and country field markers.
63
- - `<SocialLinks />` — Smart social media container that filters out unconfigured platforms automatically.
64
- - `<SocialButton />` — Brand-colored social button with built-in SVGs (Instagram, Facebook, TikTok, YouTube, LinkedIn, X, Twitter, Pinterest, GitHub).
65
- - `<BusinessHours />` — Weekly operating schedule renderer with a dynamic live **Open Now** / **Closed** status badge.
66
- - `<DenebAction />` (or `<ActionLink />`) — Universal action primitive connecting action types, URL generation, and visual editing markers.
67
-
68
- ### 2. Interactive Primitives
69
- - `<Button />` (or `<EditableButton />`) — Modern button with `primary`, `secondary`, `accent`, `glass`, `ghost` styles and `targetPage` guard.
70
- - `<Dialog />` (or `<EditableDialog />`) — Accessible popup modal with backdrop blur, smooth entrance, keyboard ESC exit, title, description, and footer actions.
71
- - `<Card />` (or `<EditableCard />`) — Flexible surface card with auto-balancing content layout.
72
- - `<Text />`, `<Heading />`, `<Paragraph />` — Typography components with responsive sizing and live editor binding.
73
- - `<Badge />` — Status indicators, tags, and promotional pills (`primary`, `secondary`, `accent`, `glass`, `glow`).
74
- - `<Link />` — Route link that automatically validates against `requirements.requiredPages`.
75
- - `<Quote />` — Editorial pull quotes and callouts.
76
-
77
- ### 3. Sections & Commerce
78
- - `<ProductCard />` — 4 visual variants (`modern-glass`, `classic`, `minimal`, `horizontal`) with discount tags and pricing.
79
- - `<PricingCard />` — Subscription/pricing tiers with feature checklist.
80
- - `<TestimonialCard />` — Customer reviews with 1–5 stars and author avatar.
81
- - `<ContactForm />` — Direct submission form connected to shared API endpoint.
82
- - `<Navbar />` — Sticky header with logo, mobile drawer, and filtered navigation.
83
- - `<Footer />` — Responsive footer with copyright and route filtering.
84
- - `<Hero />` & `<HeroSplit />` — High-impact hero sections with eyebrow badges and dual CTAs.
85
- - `<Grid />` — Auto-balancing CSS grid with equal height.
86
- - `<Accordion />` / `<FAQ />` — Collapsible Q&A list.
87
- - `<Image />` — Aspect ratio locked image with SVG fallback placeholder.
59
+ `SiteDataProvider` automatically injects **ResponsiveBaseStyles** — every component adapts across phone, tablet, and desktop without extra setup.
88
60
 
89
61
  ---
90
62
 
91
- ## URL Utility Layer
63
+ ## Features
92
64
 
93
- DENEB UI exports a dedicated utility suite for URL formatting and generation:
94
-
95
- ```tsx
96
- import {
97
- createWhatsAppUrl,
98
- createPhoneUrl,
99
- createEmailUrl,
100
- createMapUrl,
101
- isSafeExternalLink,
102
- } from "@deneb-ui/ui";
103
-
104
- // Generates: https://wa.me/94771234567?text=Hello%20Store
105
- const waUrl = createWhatsAppUrl("+94 77 123 4567", "Hello Store");
106
-
107
- // Generates: tel:+94112345678
108
- const telUrl = createPhoneUrl("+94 11 234 5678");
109
-
110
- // Generates: mailto:hello@store.com?subject=Enquiry
111
- const mailUrl = createEmailUrl("hello@store.com", "Enquiry");
112
-
113
- // Generates Google Maps directions search URL
114
- const mapUrl = createMapUrl({ address: "123 Main Street", city: "Colombo", country: "Sri Lanka" });
115
- ```
65
+ | Capability | Description |
66
+ | :--- | :--- |
67
+ | **Visual editing native** | Built-in `data-preview-field-path` bindings for Fivora and DENEB preview protocol |
68
+ | **Responsive by default** | Mobile drawer nav, collapsible filters, fluid grids, `clamp()` section spacing |
69
+ | **Smart commerce actions** | WhatsApp, phone, email, maps — auto-hide when merchant data is missing |
70
+ | **Zero styling lock-in** | Inline CSS + optional Tailwind; works in any React 18/19 app |
71
+ | **40+ components** | Navbar, Hero, ProductGrid, CartDrawer, ContactForm, BusinessHours, and more |
116
72
 
117
73
  ---
118
74
 
119
- ## Example Usage
120
-
121
- ```tsx
122
- import {
123
- SiteDataProvider,
124
- Navbar,
125
- Hero,
126
- ProductCard,
127
- ContactActions,
128
- LocationCard,
129
- BusinessHours,
130
- SocialLinks,
131
- Footer,
132
- useSiteData,
133
- } from '@deneb-ui/ui';
134
-
135
- import siteData from '@/data/site-data.json';
136
-
137
- export default function HomePage() {
138
- const data = useSiteData();
139
- const business = data.content?.common?.business || {};
140
-
141
- return (
142
- <SiteDataProvider initialSiteData={siteData}>
143
- <Navbar />
75
+ ## Documentation
144
76
 
145
- <main data-preview-page-key="home">
146
- <Hero />
77
+ | Guide | Link |
78
+ | :--- | :--- |
79
+ | Introduction | [deneb.fivora.site/docs/introduction](https://deneb.fivora.site/docs/introduction) |
80
+ | Installation & CLI init | [deneb.fivora.site/docs/installation](https://deneb.fivora.site/docs/installation) |
81
+ | Responsive design | [deneb.fivora.site/docs/responsive-design](https://deneb.fivora.site/docs/responsive-design) |
82
+ | Theming & tokens | [deneb.fivora.site/docs/theming](https://deneb.fivora.site/docs/theming) |
83
+ | Component catalog | [deneb.fivora.site/docs/components/button](https://deneb.fivora.site/docs/components/button) |
147
84
 
148
- {/* Smart Contact & Actions */}
149
- <section className="py-12 max-w-5xl mx-auto px-6 flex flex-col items-center gap-6">
150
- <ContactActions
151
- phone={business.phone}
152
- whatsapp={business.whatsapp}
153
- email={business.email}
154
- />
85
+ ---
155
86
 
156
- <div className="grid grid-cols-1 md:grid-cols-2 gap-8 w-full mt-6">
157
- <LocationCard
158
- address={business.location?.address}
159
- city={business.location?.city}
160
- country={business.location?.country}
161
- mapUrl={business.location?.mapUrl}
162
- />
87
+ ## Related packages
163
88
 
164
- <BusinessHours hours={business.hours} />
165
- </div>
89
+ | Package | Purpose |
90
+ | :--- | :--- |
91
+ | [`@deneb-ui/cli`](https://www.npmjs.com/package/@deneb-ui/cli) | Convert, validate, and package storefront templates |
92
+ | [`@deneb-ui/create-template`](https://www.npmjs.com/package/@deneb-ui/create-template) | Scaffold a new DENEB storefront in one command |
166
93
 
167
- <SocialLinks social={business.social} />
168
- </section>
169
- </main>
94
+ ---
170
95
 
171
- <Footer />
172
- </SiteDataProvider>
173
- );
174
- }
175
- ```
96
+ ## Authors
176
97
 
177
- ---
98
+ Created and maintained by **[Chamika Gayashan](https://github.com/chamikathereal)** and **[Induranga Kawishwara](https://github.com/Induranga-kawishwara)**.
178
99
 
179
- ## Author & Credits
100
+ Part of the **DENEB UI** ecosystem · Collaborate with **[Fivora](https://fivora.site)**.
180
101
 
181
- Created and architected by **Chamika Gayashan & Induranga Kawishwara**.
182
- Built for the global React and storefront developer ecosystem.
102
+ <p align="center">
103
+ <sub>MIT © DENEB UI</sub>
104
+ </p>
@@ -54,7 +54,7 @@ function EditableContactForm({ endpoint = 'https://api.fivora.com/site-contact',
54
54
  flexDirection: 'column',
55
55
  gap: '1.25rem',
56
56
  ...style,
57
- }, className: `editable-contact-form ${className}`.trim(), ...props, children: [(resolvedFormTitle || formTitlePath) && ((0, jsx_runtime_1.jsx)("h2", { "data-preview-field-path": formTitlePath || 'contact.formTitle', style: {
57
+ }, className: `editable-contact-form ${className}`.trim(), ...props, children: [(resolvedFormTitle || formTitlePath) && ((0, jsx_runtime_1.jsx)("h2", { className: "deneb-contact-form-title", "data-preview-field-path": formTitlePath || 'contact.formTitle', style: {
58
58
  fontSize: '1.5rem',
59
59
  fontWeight: 700,
60
60
  color: 'var(--heading-color, #0f172a)',
@@ -12,6 +12,7 @@ function EditableFilterSidebar({ basePath = 'filters', categories = ['All', 'Run
12
12
  const [currentPrice, setCurrentPrice] = (0, react_1.useState)(initialFilters?.priceRange ? initialFilters.priceRange[1] : maxPrice);
13
13
  const [selectedSizes, setSelectedSizes] = (0, react_1.useState)(initialFilters?.selectedSizes || []);
14
14
  const [inStockOnly, setInStockOnly] = (0, react_1.useState)(initialFilters?.inStockOnly || false);
15
+ const [mobileOpen, setMobileOpen] = (0, react_1.useState)(false);
15
16
  const getContent = (key, fallback) => {
16
17
  const section = siteData?.content?.[basePath];
17
18
  return section?.[key] || fallback;
@@ -69,16 +70,16 @@ function EditableFilterSidebar({ basePath = 'filters', categories = ['All', 'Run
69
70
  const availabilityTitle = getContent('availabilityTitle', 'Availability');
70
71
  const inStockLabel = getContent('inStockLabel', 'In Stock Only');
71
72
  const clearAllText = getContent('clearAllText', 'Clear All');
72
- return ((0, jsx_runtime_1.jsxs)("aside", { className: `deneb-filter-sidebar w-full rounded-2xl border border-neutral-800 bg-neutral-900/80 backdrop-blur-md p-6 text-white shadow-xl ${className}`, "aria-label": "Product Filters", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between border-b border-neutral-800 pb-4 mb-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("h3", { className: "text-lg font-bold tracking-tight text-white", "data-preview-field-path": fieldPath('title'), children: title }), activeFiltersCount > 0 && ((0, jsx_runtime_1.jsx)("span", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-emerald-500 text-xs font-bold text-black", "data-preview-static": "filter-active-count", children: activeFiltersCount }))] }), activeFiltersCount > 0 && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: handleClearAll, className: "text-xs font-medium text-neutral-400 hover:text-white transition-colors", "data-preview-static": "filter-clear-all", children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": fieldPath('clearAllText'), children: clearAllText }) }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-6", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-xs font-semibold uppercase tracking-wider text-neutral-400 mb-3", "data-preview-field-path": fieldPath('categoryTitle'), children: categoryTitle }), (0, jsx_runtime_1.jsx)("div", { className: "flex flex-wrap gap-2", children: categories.map((cat) => {
73
- const isSelected = selectedCategories.includes(cat);
74
- return ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => toggleCategory(cat), "data-preview-static": "filter-cat-btn", className: `rounded-lg px-3 py-1.5 text-xs font-medium transition-all ${isSelected
75
- ? 'bg-white text-black shadow-md'
76
- : 'bg-neutral-800 text-neutral-300 hover:bg-neutral-700 hover:text-white'}`, children: cat }, cat));
77
- }) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "border-t border-neutral-800/80 pt-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center mb-2", children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-xs font-semibold uppercase tracking-wider text-neutral-400", "data-preview-field-path": fieldPath('priceTitle'), children: priceTitle }), (0, jsx_runtime_1.jsxs)("span", { className: "text-sm font-semibold text-emerald-400", "data-preview-static": "filter-price-display", children: ["Up to ", currency, currentPrice] })] }), (0, jsx_runtime_1.jsx)("input", { type: "range", min: minPrice, max: maxPrice, step: 5, value: currentPrice, onChange: handlePriceChange, "data-preview-static": "filter-price-slider", className: "w-full accent-emerald-500 bg-neutral-800 h-1.5 rounded-lg cursor-pointer" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between text-xs text-neutral-500 mt-1", children: [(0, jsx_runtime_1.jsxs)("span", { children: [currency, minPrice] }), (0, jsx_runtime_1.jsxs)("span", { children: [currency, maxPrice] })] })] }), sizes.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "border-t border-neutral-800/80 pt-6", children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-xs font-semibold uppercase tracking-wider text-neutral-400 mb-3", "data-preview-field-path": fieldPath('sizeTitle'), children: sizeTitle }), (0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-3 gap-2", children: sizes.map((size) => {
78
- const isSelected = selectedSizes.includes(size);
79
- return ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => toggleSize(size), "data-preview-static": "filter-size-btn", className: `rounded-lg py-2 text-xs font-semibold transition-all border ${isSelected
80
- ? 'border-white bg-white text-black'
81
- : 'border-neutral-800 bg-neutral-800/50 text-neutral-300 hover:border-neutral-700'}`, children: size }, size));
82
- }) })] })), (0, jsx_runtime_1.jsx)("div", { className: "border-t border-neutral-800/80 pt-6", children: (0, jsx_runtime_1.jsxs)("label", { className: "flex items-center justify-between cursor-pointer group", "data-preview-static": "filter-instock-toggle", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-xs font-medium text-neutral-300 group-hover:text-white transition-colors", "data-preview-field-path": fieldPath('inStockLabel'), children: inStockLabel }), (0, jsx_runtime_1.jsx)("input", { type: "checkbox", checked: inStockOnly, onChange: toggleInStock, className: "h-4 w-4 rounded border-neutral-700 bg-neutral-800 text-emerald-500 accent-emerald-500 cursor-pointer" })] }) })] })] }));
73
+ return ((0, jsx_runtime_1.jsxs)("div", { className: `deneb-filter-sidebar-wrap w-full ${className}`, children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: "deneb-filter-mobile-toggle mb-3 rounded-xl border border-neutral-800 bg-neutral-900/90 px-4 py-3 text-sm font-semibold text-white", onClick: () => setMobileOpen((open) => !open), "aria-expanded": mobileOpen, "aria-controls": "deneb-filter-panel", "data-preview-static": "filter-mobile-toggle", children: [(0, jsx_runtime_1.jsx)("span", { children: title }), (0, jsx_runtime_1.jsxs)("span", { className: "flex items-center gap-2 text-neutral-400", children: [activeFiltersCount > 0 ? ((0, jsx_runtime_1.jsx)("span", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-emerald-500 text-xs font-bold text-black", children: activeFiltersCount })) : null, mobileOpen ? '−' : '+'] })] }), (0, jsx_runtime_1.jsxs)("aside", { id: "deneb-filter-panel", className: `deneb-filter-sidebar deneb-filter-sidebar-panel w-full rounded-2xl border border-neutral-800 bg-neutral-900/80 backdrop-blur-md p-6 text-white shadow-xl ${mobileOpen ? 'is-open' : ''}`, "aria-label": "Product Filters", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between border-b border-neutral-800 pb-4 mb-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("h3", { className: "text-lg font-bold tracking-tight text-white", "data-preview-field-path": fieldPath('title'), children: title }), activeFiltersCount > 0 && ((0, jsx_runtime_1.jsx)("span", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-emerald-500 text-xs font-bold text-black", "data-preview-static": "filter-active-count", children: activeFiltersCount }))] }), activeFiltersCount > 0 && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: handleClearAll, className: "text-xs font-medium text-neutral-400 hover:text-white transition-colors", "data-preview-static": "filter-clear-all", children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": fieldPath('clearAllText'), children: clearAllText }) }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-6", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-xs font-semibold uppercase tracking-wider text-neutral-400 mb-3", "data-preview-field-path": fieldPath('categoryTitle'), children: categoryTitle }), (0, jsx_runtime_1.jsx)("div", { className: "flex flex-wrap gap-2", children: categories.map((cat) => {
74
+ const isSelected = selectedCategories.includes(cat);
75
+ return ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => toggleCategory(cat), "data-preview-static": "filter-cat-btn", className: `rounded-lg px-3 py-1.5 text-xs font-medium transition-all ${isSelected
76
+ ? 'bg-white text-black shadow-md'
77
+ : 'bg-neutral-800 text-neutral-300 hover:bg-neutral-700 hover:text-white'}`, children: cat }, cat));
78
+ }) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "border-t border-neutral-800/80 pt-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center mb-2", children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-xs font-semibold uppercase tracking-wider text-neutral-400", "data-preview-field-path": fieldPath('priceTitle'), children: priceTitle }), (0, jsx_runtime_1.jsxs)("span", { className: "text-sm font-semibold text-emerald-400", "data-preview-static": "filter-price-display", children: ["Up to ", currency, currentPrice] })] }), (0, jsx_runtime_1.jsx)("input", { type: "range", min: minPrice, max: maxPrice, step: 5, value: currentPrice, onChange: handlePriceChange, "data-preview-static": "filter-price-slider", className: "w-full accent-emerald-500 bg-neutral-800 h-1.5 rounded-lg cursor-pointer" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between text-xs text-neutral-500 mt-1", children: [(0, jsx_runtime_1.jsxs)("span", { children: [currency, minPrice] }), (0, jsx_runtime_1.jsxs)("span", { children: [currency, maxPrice] })] })] }), sizes.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "border-t border-neutral-800/80 pt-6", children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-xs font-semibold uppercase tracking-wider text-neutral-400 mb-3", "data-preview-field-path": fieldPath('sizeTitle'), children: sizeTitle }), (0, jsx_runtime_1.jsx)("div", { className: "deneb-filter-size-grid grid grid-cols-3 gap-2", children: sizes.map((size) => {
79
+ const isSelected = selectedSizes.includes(size);
80
+ return ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => toggleSize(size), "data-preview-static": "filter-size-btn", className: `rounded-lg py-2 text-xs font-semibold transition-all border ${isSelected
81
+ ? 'border-white bg-white text-black'
82
+ : 'border-neutral-800 bg-neutral-800/50 text-neutral-300 hover:border-neutral-700'}`, children: size }, size));
83
+ }) })] })), (0, jsx_runtime_1.jsx)("div", { className: "border-t border-neutral-800/80 pt-6", children: (0, jsx_runtime_1.jsxs)("label", { className: "flex items-center justify-between cursor-pointer group", "data-preview-static": "filter-instock-toggle", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-xs font-medium text-neutral-300 group-hover:text-white transition-colors", "data-preview-field-path": fieldPath('inStockLabel'), children: inStockLabel }), (0, jsx_runtime_1.jsx)("input", { type: "checkbox", checked: inStockOnly, onChange: toggleInStock, className: "h-4 w-4 rounded border-neutral-700 bg-neutral-800 text-emerald-500 accent-emerald-500 cursor-pointer" })] }) })] })] })] }));
83
84
  }
84
85
  exports.FilterSidebar = EditableFilterSidebar;
@@ -159,7 +159,7 @@ function EditableFooter({ defaultLinks = DEFAULT_FOOTER_PAGES, links, basePath =
159
159
  gridTemplateColumns: 'repeat(auto-fit, minmax(240px, 1fr))',
160
160
  gap: '3rem',
161
161
  marginBottom: '4rem',
162
- }, className: "grid grid-cols-1 gap-10 md:grid-cols-2 lg:grid-cols-4 lg:gap-8 mb-16", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-4", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", "data-preview-static": "footer-brand-link", onClick: () => navigate('/'), style: {
162
+ }, className: "deneb-footer-grid grid grid-cols-1 gap-10 md:grid-cols-2 lg:grid-cols-4 lg:gap-8 mb-16", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-4", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", "data-preview-static": "footer-brand-link", onClick: () => navigate('/'), style: {
163
163
  display: 'inline-flex',
164
164
  alignItems: 'center',
165
165
  gap: '0.75rem',
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EditableGrid = EditableGrid;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const responsive_1 = require("./utils/responsive");
5
6
  const SPACING_MAP = {
6
7
  none: '0',
7
8
  xs: '0.5rem',
@@ -17,23 +18,20 @@ const SPACING_MAP = {
17
18
  */
18
19
  function EditableGrid({ as: Component = 'div', id, 'data-preview-list-path': previewListPath, 'data-preview-static': previewStatic, minCardWidth = '280px', columns, gap = 'md', equalHeight = true, align = 'stretch', style, className = '', children, ...props }) {
19
20
  const resolvedGap = gap !== undefined ? (SPACING_MAP[String(gap)] || String(gap)) : '1.25rem';
20
- let templateCols;
21
- if (typeof columns === 'number') {
22
- templateCols = `repeat(${columns}, minmax(0, 1fr))`;
23
- }
24
- else if (columns && typeof columns === 'object') {
25
- templateCols = `repeat(auto-fit, minmax(${minCardWidth}, 1fr))`;
26
- }
27
- else {
28
- // Default auto-balancing formula
29
- templateCols = `repeat(auto-fit, minmax(${minCardWidth}, 1fr))`;
30
- }
21
+ const { template: templateCols, dataAttrs } = (0, responsive_1.resolveResponsiveColumns)(columns, minCardWidth);
31
22
  const gridStyle = {
32
23
  display: 'grid',
33
24
  gridTemplateColumns: templateCols,
34
25
  gap: resolvedGap,
35
26
  alignItems: equalHeight ? 'stretch' : align,
27
+ ...(dataAttrs
28
+ ? {
29
+ '--deneb-cols': dataAttrs['data-cols-mobile'],
30
+ '--deneb-cols-tablet': dataAttrs['data-cols-tablet'],
31
+ '--deneb-cols-desktop': dataAttrs['data-cols-desktop'],
32
+ }
33
+ : {}),
36
34
  ...style,
37
35
  };
38
- return ((0, jsx_runtime_1.jsx)(Component, { "data-preview-list-path": previewListPath || id, className: `editable-grid ${className}`.trim(), style: gridStyle, ...props, children: children }));
36
+ return ((0, jsx_runtime_1.jsx)(Component, { "data-preview-list-path": previewListPath || id, className: `editable-grid ${className}`.trim(), style: gridStyle, ...(dataAttrs || {}), ...props, children: children }));
39
37
  }
@@ -98,7 +98,6 @@ function EditableNavbar({ defaultLinks = DEFAULT_PAGES, sticky = true, activeRou
98
98
  letterSpacing: '-0.025em',
99
99
  color: 'var(--color-text, #0f172a)',
100
100
  }, className: "deneb-site-title text-xl font-bold tracking-tight text-slate-900 dark:text-white", children: siteName })] }), (0, jsx_runtime_1.jsx)("nav", { style: {
101
- display: 'flex',
102
101
  alignItems: 'center',
103
102
  gap: '0.375rem',
104
103
  }, className: "deneb-desktop-nav flex items-center gap-1.5", children: activeLinks.map((link) => {
@@ -133,8 +132,7 @@ function EditableNavbar({ defaultLinks = DEFAULT_PAGES, sticky = true, activeRou
133
132
  cursor: 'pointer',
134
133
  boxShadow: '0 2px 8px rgba(0, 0, 0, 0.08)',
135
134
  transition: 'all 0.2s cubic-bezier(0.4, 0, 0.2, 1)',
136
- }, className: "deneb-header-cta inline-flex items-center justify-center px-4 py-2 rounded-full text-sm font-semibold bg-slate-900 text-white shadow-sm hover:bg-slate-800 hover:shadow-md transition-all border-0 cursor-pointer dark:bg-white dark:text-slate-900 dark:hover:bg-slate-100", children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": "common.headerCtaLabel", children: headerCtaLabel }) }) })) : ((0, jsx_runtime_1.jsx)("span", { "data-target-page": "contact", className: "deneb-header-cta unavailable", "data-preview-field-path": "common.headerCtaLabel", children: headerCtaLabel })), (0, jsx_runtime_1.jsx)("button", { type: "button", "data-preview-static": "mobile-menu-toggle", onClick: () => setMobileMenuOpen(!mobileMenuOpen), "aria-label": "Toggle Navigation Menu", style: {
137
- display: 'flex',
135
+ }, className: "deneb-header-cta inline-flex items-center justify-center px-4 py-2 rounded-full text-sm font-semibold bg-slate-900 text-white shadow-sm hover:bg-slate-800 hover:shadow-md transition-all border-0 cursor-pointer dark:bg-white dark:text-slate-900 dark:hover:bg-slate-100", children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": "common.headerCtaLabel", children: headerCtaLabel }) }) })) : ((0, jsx_runtime_1.jsx)("span", { "data-target-page": "contact", className: "deneb-header-cta unavailable", "data-preview-field-path": "common.headerCtaLabel", children: headerCtaLabel })), (0, jsx_runtime_1.jsx)("button", { type: "button", "data-preview-static": "mobile-menu-toggle", onClick: () => setMobileMenuOpen(!mobileMenuOpen), "aria-label": "Toggle Navigation Menu", "aria-expanded": mobileMenuOpen, style: {
138
136
  alignItems: 'center',
139
137
  justifyContent: 'center',
140
138
  width: '40px',
@@ -144,35 +142,50 @@ function EditableNavbar({ defaultLinks = DEFAULT_PAGES, sticky = true, activeRou
144
142
  backgroundColor: 'transparent',
145
143
  color: 'var(--color-text, #0f172a)',
146
144
  cursor: 'pointer',
147
- }, 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.jsx)("div", { style: {
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: {
148
146
  borderTop: '1px solid var(--color-border, #e2e8f0)',
149
147
  backgroundColor: 'rgba(255, 255, 255, 0.98)',
150
148
  padding: '1.25rem 1.5rem',
151
149
  display: 'flex',
152
150
  flexDirection: 'column',
153
151
  gap: '0.625rem',
154
- }, className: "deneb-mobile-drawer md:hidden border-t border-slate-200 bg-white/95 backdrop-blur-lg px-4 py-5 flex flex-col gap-2.5 dark:border-slate-800 dark:bg-slate-950/95", children: activeLinks.map((link) => {
155
- const label = navLabels[link.id] || link.label;
156
- const isActive = activeRoute === link.route;
157
- return ((0, jsx_runtime_1.jsx)("span", { "data-target-page": link.id, children: (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => {
152
+ }, className: "deneb-mobile-drawer md:hidden border-t border-slate-200 bg-white/95 backdrop-blur-lg px-4 py-5 flex flex-col gap-2.5 dark:border-slate-800 dark:bg-slate-950/95", children: [activeLinks.map((link) => {
153
+ const label = navLabels[link.id] || link.label;
154
+ const isActive = activeRoute === link.route;
155
+ return ((0, jsx_runtime_1.jsx)("span", { "data-target-page": link.id, children: (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => {
156
+ setMobileMenuOpen(false);
157
+ navigate(link.route);
158
+ }, style: {
159
+ display: 'block',
160
+ width: '100%',
161
+ textAlign: 'left',
162
+ padding: '0.625rem 0.875rem',
163
+ borderRadius: '8px',
164
+ fontSize: '0.95rem',
165
+ fontWeight: isActive ? 600 : 500,
166
+ color: isActive ? 'var(--color-primary, #0f172a)' : 'var(--color-text, #0f172a)',
167
+ backgroundColor: isActive ? 'var(--color-secondary, #f1f5f9)' : 'transparent',
168
+ border: 0,
169
+ cursor: 'pointer',
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
+ ? 'bg-slate-100 text-slate-900 font-semibold dark:bg-slate-800 dark:text-white'
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: () => {
158
174
  setMobileMenuOpen(false);
159
- navigate(link.route);
175
+ navigate('/contact');
160
176
  }, style: {
161
177
  display: 'block',
162
178
  width: '100%',
163
- textAlign: 'left',
164
- padding: '0.625rem 0.875rem',
165
- borderRadius: '8px',
179
+ textAlign: 'center',
180
+ backgroundColor: 'var(--color-primary, #0f172a)',
181
+ color: '#ffffff',
182
+ padding: '0.75rem 1rem',
183
+ borderRadius: '9999px',
166
184
  fontSize: '0.95rem',
167
- fontWeight: isActive ? 600 : 500,
168
- color: isActive ? 'var(--color-primary, #0f172a)' : 'var(--color-text, #0f172a)',
169
- backgroundColor: isActive ? 'var(--color-secondary, #f1f5f9)' : 'transparent',
185
+ fontWeight: 600,
170
186
  border: 0,
171
187
  cursor: 'pointer',
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
- ? '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-field-path": `common.navLabels.${link.id}`, children: label }) }) }, link.id));
175
- }) }))] }));
188
+ }, className: "deneb-mobile-drawer-cta w-full text-center px-4 py-3 rounded-full text-base font-semibold bg-slate-900 text-white border-0 cursor-pointer", children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": "common.headerCtaLabel", children: headerCtaLabel }) }) })) : null] }))] }));
176
189
  }
177
190
  exports.Navbar = EditableNavbar;
178
191
  exports.Header = EditableNavbar;
@@ -43,7 +43,7 @@ function EditablePricingCard({ itemPath, item, as: Component = 'div', isPopular
43
43
  color: 'var(--muted-text, #64748b)',
44
44
  marginBottom: '1.5rem',
45
45
  lineHeight: 1.5,
46
- } }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'baseline', gap: '0.25rem', marginBottom: '1.5rem' }, children: [(0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.price`, defaultValue: price, style: {
46
+ } }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'baseline', gap: '0.25rem', marginBottom: '1.5rem' }, children: [(0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.price`, defaultValue: price, className: "deneb-pricing-amount", style: {
47
47
  fontSize: '2.75rem',
48
48
  fontWeight: 800,
49
49
  letterSpacing: '-0.03em',
@@ -49,17 +49,17 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
49
49
  borderRadius: '14px',
50
50
  overflow: 'hidden',
51
51
  display: 'flex',
52
- flexDirection: 'row',
53
- alignItems: 'center',
52
+ flexDirection: 'column',
53
+ alignItems: 'stretch',
54
54
  },
55
55
  };
56
56
  return ((0, jsx_runtime_1.jsxs)(Component, { "data-preview-item-path": itemPath, style: {
57
57
  ...variantStyles[cardVariant],
58
58
  ...style,
59
- }, className: `editable-product-card group ${className}`.trim(), ...props, children: [(0, jsx_runtime_1.jsxs)("div", { style: {
59
+ }, className: `editable-product-card group ${isHorizontal ? 'is-horizontal' : ''} ${className}`.trim(), ...props, children: [(0, jsx_runtime_1.jsxs)("div", { className: "deneb-product-card-media", style: {
60
60
  position: 'relative',
61
61
  overflow: 'hidden',
62
- width: isHorizontal ? '38%' : '100%',
62
+ width: isHorizontal ? '100%' : '100%',
63
63
  flexShrink: 0,
64
64
  }, children: [(0, jsx_runtime_1.jsx)(EditableImage_1.EditableImage, { id: `${itemPath}.imageUrl`, src: imageUrl, fallbackSrc: imageFallback, alt: name, aspectRatio: isHorizontal ? 'square' : '4/3', fit: "cover", hoverZoom: true, style: { width: '100%', height: '100%', display: 'block' } }), badge && ((0, jsx_runtime_1.jsx)("div", { style: { position: 'absolute', top: '10px', left: '10px', zIndex: 10 }, children: (0, jsx_runtime_1.jsx)(EditableText_2.EditableBadge, { id: `${itemPath}.badge`, defaultValue: badge, badgeVariant: "primary" }) }))] }), (0, jsx_runtime_1.jsxs)("div", { style: {
65
65
  padding: '1.25rem',
@@ -42,11 +42,11 @@ function EditableProductDetail({ sectionPath = 'product', product, sizes = ['40'
42
42
  const resolvedWhatsappUrl = whatsappUrl || (product.whatsappNumber
43
43
  ? (0, urls_1.createWhatsAppUrl)(product.whatsappNumber, product.whatsappMessage || `Hi, I would like to order ${name} (${selectedSize}, ${selectedColor}) - ${price}`)
44
44
  : '');
45
- return ((0, jsx_runtime_1.jsx)("section", { "data-preview-page-key": sectionPath, className: `editable-product-detail max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12 ${className}`.trim(), style: style, ...props, children: (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-1 lg:grid-cols-12 gap-12 lg:gap-16 items-start", children: [(0, jsx_runtime_1.jsxs)("div", { className: "lg:col-span-7 flex flex-col-reverse md:flex-row gap-4", children: [images.length > 1 && ((0, jsx_runtime_1.jsx)("div", { className: "flex md:flex-col gap-3 overflow-x-auto md:overflow-y-auto max-h-[580px] pb-2 md:pb-0 scrollbar-none", children: images.map((img, idx) => ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveImage(img), className: `w-20 h-20 sm:w-24 sm:h-24 rounded-2xl overflow-hidden border-2 transition-all duration-200 flex-shrink-0 bg-slate-900/40 p-2 ${activeImage === img
45
+ return ((0, jsx_runtime_1.jsx)("section", { "data-preview-page-key": sectionPath, className: `editable-product-detail max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12 ${className}`.trim(), style: style, ...props, children: (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-1 lg:grid-cols-12 gap-12 lg:gap-16 items-start", children: [(0, jsx_runtime_1.jsxs)("div", { className: "lg:col-span-7 flex flex-col-reverse md:flex-row gap-4", children: [images.length > 1 && ((0, jsx_runtime_1.jsx)("div", { className: "deneb-product-detail-gallery flex md:flex-col gap-3 overflow-x-auto md:overflow-y-auto max-h-[580px] pb-2 md:pb-0 scrollbar-none", children: images.map((img, idx) => ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveImage(img), className: `w-20 h-20 sm:w-24 sm:h-24 rounded-2xl overflow-hidden border-2 transition-all duration-200 flex-shrink-0 bg-slate-900/40 p-2 ${activeImage === img
46
46
  ? 'border-brand-primary scale-98 shadow-md'
47
47
  : 'border-slate-800/80 opacity-60 hover:opacity-100 hover:border-slate-700'}`, children: (0, jsx_runtime_1.jsx)("img", { src: (0, utils_1.withBasePath)(img), alt: "", className: "w-full h-full object-contain" }) }, idx))) })), (0, jsx_runtime_1.jsxs)("div", { className: "relative flex-1 aspect-square rounded-3xl bg-gradient-to-b from-slate-900/50 to-slate-950/80 border border-slate-800/80 p-8 flex items-center justify-center overflow-hidden group", children: [badge && ((0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.badge`, className: "absolute top-6 left-6 z-10 px-3.5 py-1 text-xs font-black tracking-wider uppercase rounded-full bg-lime-400 text-slate-950 shadow-lg", children: badge })), (0, jsx_runtime_1.jsx)("img", { "data-preview-field-path": `${sectionPath}.featuredImage`, src: (0, utils_1.withBasePath)(activeImage), alt: name, className: "w-full h-full object-contain transition-transform duration-500 group-hover:scale-105" })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "lg:col-span-5 flex flex-col justify-between", children: (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h1", { "data-preview-field-path": `${sectionPath}.name`, className: "text-3xl sm:text-4xl font-extrabold tracking-tight text-white leading-tight", children: name }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-4 flex items-baseline gap-3", children: [(0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.price`, className: "text-3xl font-black text-lime-400 tracking-tight", children: price }), product.originalPrice ? ((0, jsx_runtime_1.jsx)("span", { className: "text-lg font-medium text-slate-500 line-through", children: String(product.originalPrice) })) : null] }), description && ((0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `${sectionPath}.description`, className: "mt-6 text-base text-slate-300 leading-relaxed", children: description })), colors.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-8", children: [(0, jsx_runtime_1.jsxs)("span", { className: "block text-xs font-bold uppercase tracking-wider text-slate-400 mb-3", children: ["Color \u2014 ", (0, jsx_runtime_1.jsx)("span", { className: "text-white", children: selectedColor })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex gap-3", children: colors.map((c) => ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setSelectedColor(c.name), className: `w-9 h-9 rounded-full border-2 transition-all p-0.5 ${selectedColor === c.name
48
48
  ? 'border-lime-400 ring-2 ring-lime-400/30 scale-105'
49
- : 'border-slate-700 hover:border-slate-500'}`, style: { backgroundColor: c.hex }, title: c.name, "aria-label": c.name }, c.name))) })] })), sizes.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-8", children: [(0, jsx_runtime_1.jsx)("span", { className: "block text-xs font-bold uppercase tracking-wider text-slate-400 mb-3", children: "Select Size" }), (0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-4 sm:grid-cols-7 gap-2", children: sizes.map((s) => ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setSelectedSize(s), className: `py-2.5 rounded-xl font-bold text-sm transition-all duration-150 ${selectedSize === s
49
+ : 'border-slate-700 hover:border-slate-500'}`, style: { backgroundColor: c.hex }, title: c.name, "aria-label": c.name }, c.name))) })] })), sizes.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-8", children: [(0, jsx_runtime_1.jsx)("span", { className: "block text-xs font-bold uppercase tracking-wider text-slate-400 mb-3", children: "Select Size" }), (0, jsx_runtime_1.jsx)("div", { className: "deneb-product-detail-sizes grid grid-cols-4 sm:grid-cols-7 gap-2", children: sizes.map((s) => ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setSelectedSize(s), className: `py-2.5 rounded-xl font-bold text-sm transition-all duration-150 ${selectedSize === s
50
50
  ? 'bg-white text-slate-950 shadow-md font-extrabold scale-102'
51
51
  : 'bg-slate-900/60 text-slate-300 border border-slate-800 hover:bg-slate-800 hover:text-white'}`, children: s }, s))) })] })), (0, jsx_runtime_1.jsxs)("div", { className: "mt-8 flex flex-col gap-3", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => onAddToSelection?.(product, selectedSize, selectedColor), className: "w-full py-4 px-6 rounded-2xl font-black text-sm uppercase tracking-wider bg-lime-400 text-slate-950 hover:bg-lime-300 active:scale-98 transition-all duration-150 shadow-lg shadow-lime-400/20 flex items-center justify-center gap-2", children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.addToSelectionLabel`, children: addToSelectionLabel }) }), resolvedWhatsappUrl && ((0, jsx_runtime_1.jsxs)("a", { href: resolvedWhatsappUrl, target: "_blank", rel: "noopener noreferrer", className: "w-full py-3.5 px-6 rounded-2xl font-bold text-sm bg-emerald-600/20 text-emerald-400 hover:bg-emerald-600/30 border border-emerald-500/30 transition-all duration-150 flex items-center justify-center gap-2", children: [(0, jsx_runtime_1.jsx)("svg", { className: "w-5 h-5 fill-current", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { d: "M17.472 14.382c-.301-.15-1.78-.879-2.056-.98-.276-.1-.477-.15-.678.15-.201.3-.78 0.98-.956 1.18-.175.2-.351.226-.652.075-.301-.15-1.272-.469-2.423-1.496-.896-.799-1.501-1.787-1.677-2.088-.175-.301-.019-.464.132-.614.136-.135.301-.351.452-.527.15-.176.201-.301.301-.502.1-.2.05-.376-.025-.527-.075-.15-.678-1.635-.93-2.242-.244-.592-.493-.512-.678-.521-.175-.009-.376-.009-.577-.009-.201 0-.527.075-.803.376-.276.301-1.054 1.03-1.054 2.512 0 1.482 1.079 2.912 1.23 3.113.15.201 2.124 3.243 5.145 4.548.718.311 1.279.497 1.716.636.722.23 1.378.197 1.898.12.579-.087 1.78-.728 2.03-1.431.251-.703.251-1.305.176-1.431-.075-.126-.276-.201-.577-.351zM12.004 2C6.48 2 2 6.48 2 12c0 1.82.49 3.52 1.34 4.99L2 22l5.14-1.35c1.42.78 3.04 1.22 4.86 1.22 5.52 0 10-4.48 10-10S17.524 2 12.004 2z" }) }), (0, jsx_runtime_1.jsx)("span", { children: "Order Directly via WhatsApp" })] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-10 border-t border-slate-800/80 pt-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex gap-6 border-b border-slate-800 pb-3 mb-4", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveTab('specs'), className: `text-sm font-bold tracking-wide transition-colors ${activeTab === 'specs' ? 'text-lime-400' : 'text-slate-400 hover:text-slate-200'}`, children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.specsTitle`, children: specsTitle }) }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveTab('shipping'), className: `text-sm font-bold tracking-wide transition-colors ${activeTab === 'shipping' ? 'text-lime-400' : 'text-slate-400 hover:text-slate-200'}`, children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.shippingTitle`, children: shippingTitle }) })] }), activeTab === 'specs' ? ((0, jsx_runtime_1.jsx)("div", { className: "space-y-3", children: product.specs && product.specs.length > 0 ? (product.specs.map((spec, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between text-xs py-1 border-b border-slate-900", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-slate-400 font-medium", children: spec.label }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: spec.value })] }, i)))) : ((0, jsx_runtime_1.jsxs)("div", { className: "text-xs text-slate-400 space-y-2", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between py-1 border-b border-slate-800/50", children: [(0, jsx_runtime_1.jsx)("span", { children: "Upper Material" }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: "Engineered breathable mesh" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between py-1 border-b border-slate-800/50", children: [(0, jsx_runtime_1.jsx)("span", { children: "Midsole Technology" }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: "Dual-density responsive foam" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between py-1 border-b border-slate-800/50", children: [(0, jsx_runtime_1.jsx)("span", { children: "Outsole Grip" }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: "High-abrasion tactical rubber" })] })] })) })) : ((0, jsx_runtime_1.jsxs)("div", { className: "text-xs text-slate-300 space-y-3 leading-relaxed", children: [(0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `${sectionPath}.shippingSummary`, children: shippingSummary }), (0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `${sectionPath}.shippingReturns`, className: "text-slate-400", children: shippingReturns })] }))] })] }) })] }) }));
52
52
  }
@@ -38,7 +38,7 @@ function EditableProductGrid({ sectionPath = 'home', title = 'Featured Collectio
38
38
  return ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveCategory(cat), className: `px-4 py-2 rounded-xl text-xs font-bold transition-all duration-200 ${isActive
39
39
  ? 'bg-white text-slate-950 shadow-md scale-102 font-extrabold'
40
40
  : 'bg-slate-900/60 text-slate-400 hover:text-white border border-slate-800/80 hover:bg-slate-850'}`, children: cat }, cat));
41
- }) }))] }), filteredProducts.length > 0 ? ((0, jsx_runtime_1.jsx)("div", { className: `grid ${gridColClasses} gap-6 sm:gap-8`, children: filteredProducts.map((product, idx) => {
41
+ }) }))] }), filteredProducts.length > 0 ? ((0, jsx_runtime_1.jsx)("div", { className: `deneb-product-grid grid ${gridColClasses} gap-6 sm:gap-8`, children: filteredProducts.map((product, idx) => {
42
42
  const itemPath = `${sectionPath}.${cardPrefix}${idx + 1}`;
43
43
  return ((0, jsx_runtime_1.jsxs)("div", { className: "relative group", children: [(0, jsx_runtime_1.jsx)(EditableProductCard_1.EditableProductCard, { itemPath: itemPath, product: product, cardVariant: cardVariant, className: "h-full" }), onQuickView && ((0, jsx_runtime_1.jsx)("div", { className: "absolute top-4 right-4 z-20 opacity-0 group-hover:opacity-100 transition-opacity duration-200", children: (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => onQuickView(product, itemPath), className: "p-2.5 rounded-xl bg-slate-950/80 backdrop-blur-md text-white hover:bg-lime-400 hover:text-slate-950 shadow-lg transition-all active:scale-95", title: "Quick View", "aria-label": `Quick View ${product.name || product.title}`, children: (0, jsx_runtime_1.jsxs)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: [(0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z" }), (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" })] }) }) }))] }, product.id || idx));
44
44
  }) })) : (
@@ -2,15 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EditableSection = EditableSection;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const SECTION_PADDING_MAP = {
6
- none: '0',
7
- xs: '1.5rem 0',
8
- sm: '2.5rem 0',
9
- md: '4rem 0',
10
- lg: '6rem 0',
11
- xl: '8rem 0',
12
- '2xl': '10rem 0',
13
- };
5
+ const responsive_1 = require("./utils/responsive");
6
+ const SECTION_PADDING_MAP = responsive_1.RESPONSIVE_SECTION_PADDING;
14
7
  /**
15
8
  * EditableSection standardizes section spacing and automatically applies the required
16
9
  * `data-design-section` marker for 100% fivora contract compliance.
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ /**
3
+ * Injects viewport-aware CSS for all DENEB UI components.
4
+ * Works without Tailwind — every template gets mobile / tablet / desktop behavior
5
+ * when this is mounted once (included automatically by ThemeStyles).
6
+ */
7
+ export declare function ResponsiveBaseStyles(): React.JSX.Element;
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ResponsiveBaseStyles = ResponsiveBaseStyles;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ /**
6
+ * Injects viewport-aware CSS for all DENEB UI components.
7
+ * Works without Tailwind — every template gets mobile / tablet / desktop behavior
8
+ * when this is mounted once (included automatically by ThemeStyles).
9
+ */
10
+ function ResponsiveBaseStyles() {
11
+ const css = `
12
+ /* ── Breakpoints: mobile <768 | tablet 768–1023 | desktop ≥1024 ── */
13
+
14
+ /* Navbar: hide desktop nav + compact header on mobile */
15
+ .deneb-desktop-nav { display: none !important; }
16
+ .deneb-mobile-toggle { display: flex !important; }
17
+ .deneb-header-cta { display: none !important; }
18
+
19
+ @media (min-width: 768px) {
20
+ .deneb-desktop-nav { display: flex !important; }
21
+ .deneb-mobile-toggle { display: none !important; }
22
+ .deneb-header-cta { display: inline-flex !important; }
23
+ .deneb-mobile-drawer { display: none !important; }
24
+ }
25
+
26
+ @media (max-width: 767px) {
27
+ .deneb-site-title { font-size: 1rem !important; max-width: 9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
28
+ .deneb-logo { height: 32px !important; max-width: 100px !important; }
29
+ }
30
+
31
+ /* Responsive grid columns via data attributes */
32
+ .editable-grid[data-deneb-responsive-cols="true"] {
33
+ grid-template-columns: repeat(var(--deneb-cols, 1), minmax(0, 1fr));
34
+ }
35
+ @media (min-width: 640px) {
36
+ .editable-grid[data-deneb-responsive-cols="true"] {
37
+ grid-template-columns: repeat(var(--deneb-cols-tablet, 2), minmax(0, 1fr));
38
+ }
39
+ }
40
+ @media (min-width: 1024px) {
41
+ .editable-grid[data-deneb-responsive-cols="true"] {
42
+ grid-template-columns: repeat(var(--deneb-cols-desktop, 3), minmax(0, 1fr));
43
+ }
44
+ }
45
+
46
+ /* Horizontal product card stacks on mobile */
47
+ .editable-product-card.is-horizontal { flex-direction: column !important; }
48
+ .editable-product-card.is-horizontal .deneb-product-card-media { width: 100% !important; }
49
+ @media (min-width: 640px) {
50
+ .editable-product-card.is-horizontal { flex-direction: row !important; align-items: center !important; }
51
+ .editable-product-card.is-horizontal .deneb-product-card-media { width: 38% !important; }
52
+ }
53
+
54
+ /* Card padding scales down on small screens */
55
+ .editable-pricing-card,
56
+ .editable-testimonial-card {
57
+ padding: clamp(1.25rem, 4vw, 2.5rem) clamp(1rem, 3vw, 2rem) !important;
58
+ }
59
+ .editable-pricing-card .deneb-pricing-amount {
60
+ font-size: clamp(2rem, 6vw, 2.75rem) !important;
61
+ }
62
+
63
+ /* Dialog: tighter padding on phones */
64
+ .deneb-dialog-portal { padding: clamp(0.5rem, 3vw, 1rem) !important; }
65
+ .deneb-dialog-content { padding: clamp(1.25rem, 4vw, 2rem) !important; border-radius: clamp(12px, 3vw, 20px) !important; }
66
+ .deneb-dialog-content h2 { font-size: clamp(1.1rem, 4vw, 1.35rem) !important; }
67
+
68
+ /* Floating contact: prevent popup overflow */
69
+ .deneb-contact-popup {
70
+ width: min(18rem, calc(100vw - 2rem)) !important;
71
+ max-width: calc(100vw - 2rem) !important;
72
+ }
73
+ @media (max-width: 479px) {
74
+ .deneb-floating-contact { bottom: 1rem !important; right: 1rem !important; left: auto !important; }
75
+ .deneb-floating-contact.deneb-floating-left { left: 1rem !important; right: auto !important; }
76
+ }
77
+
78
+ /* Filter sidebar: collapsible on mobile, always visible on tablet+ */
79
+ .deneb-filter-mobile-toggle { display: flex; width: 100%; align-items: center; justify-content: space-between; }
80
+ @media (min-width: 768px) {
81
+ .deneb-filter-mobile-toggle { display: none !important; }
82
+ .deneb-filter-sidebar-panel { display: block !important; }
83
+ }
84
+ @media (max-width: 767px) {
85
+ .deneb-filter-sidebar-panel { display: none; }
86
+ .deneb-filter-sidebar-panel.is-open { display: block; }
87
+ .deneb-filter-sidebar .deneb-filter-size-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
88
+ }
89
+
90
+ /* Contact actions: stack on mobile when row layout */
91
+ @media (max-width: 639px) {
92
+ .deneb-contact-actions.deneb-layout-row {
93
+ flex-direction: column !important;
94
+ align-items: stretch !important;
95
+ }
96
+ .deneb-contact-actions.deneb-layout-row > * { width: 100%; }
97
+ }
98
+
99
+ /* Contact form title */
100
+ .deneb-contact-form-title { font-size: clamp(1.25rem, 4vw, 1.75rem) !important; }
101
+
102
+ /* Product detail: size grid on xs */
103
+ @media (max-width: 479px) {
104
+ .deneb-product-detail-sizes { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
105
+ .deneb-product-detail-gallery { max-height: 420px !important; }
106
+ }
107
+
108
+ /* Footer / trust badges / product grid fallbacks when Tailwind is absent */
109
+ @media (max-width: 639px) {
110
+ .deneb-footer-grid { grid-template-columns: 1fr !important; }
111
+ .deneb-trust-grid { grid-template-columns: 1fr !important; }
112
+ .deneb-product-grid { grid-template-columns: 1fr !important; }
113
+ }
114
+ @media (min-width: 640px) and (max-width: 1023px) {
115
+ .deneb-footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
116
+ .deneb-trust-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
117
+ .deneb-product-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
118
+ }
119
+ @media (min-width: 1024px) {
120
+ .deneb-footer-grid { grid-template-columns: repeat(4, minmax(0, 1fr)) !important; }
121
+ .deneb-trust-grid { grid-template-columns: repeat(4, minmax(0, 1fr)) !important; }
122
+ }
123
+
124
+ /* Sticky mobile bar: hide on desktop */
125
+ .deneb-sticky-mobile-bar { display: flex; }
126
+ @media (min-width: 1024px) {
127
+ .deneb-sticky-mobile-bar { display: none !important; }
128
+ }
129
+
130
+ /* Dialog animations */
131
+ @keyframes deneb-fade-in { from { opacity: 0; } to { opacity: 1; } }
132
+ @keyframes deneb-zoom-in { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: scale(1); } }
133
+ @keyframes deneb-pop { from { opacity: 0; transform: translateY(8px) scale(0.96); } to { opacity: 1; transform: translateY(0) scale(1); } }
134
+ `;
135
+ return (0, jsx_runtime_1.jsx)("style", { "data-deneb-responsive": "true", dangerouslySetInnerHTML: { __html: css } });
136
+ }
@@ -17,6 +17,7 @@ exports.getFieldStyle = getFieldStyle;
17
17
  exports.useFieldStyle = useFieldStyle;
18
18
  const jsx_runtime_1 = require("react/jsx-runtime");
19
19
  const react_1 = require("react");
20
+ const ResponsiveBaseStyles_1 = require("./ResponsiveBaseStyles");
20
21
  exports.DENEB_PREVIEW_DATA_MESSAGE = 'DENEB_PREVIEW_SITE_DATA';
21
22
  exports.PREVIEW_DATA_MESSAGE = 'FIVORA_PREVIEW_SITE_DATA';
22
23
  const PREVIOUS_PREVIEW_PREFIX = `${['MARKET', 'PLACE'].join('')}_PREVIEW_`;
@@ -248,7 +249,7 @@ function SiteDataProvider({ children, initialSiteData, fallbackSiteData, }) {
248
249
  return () => window.removeEventListener('message', onMessage);
249
250
  }, []);
250
251
  const value = (0, react_1.useMemo)(() => siteData, [siteData]);
251
- return ((0, jsx_runtime_1.jsx)(exports.SiteDataContext.Provider, { value: value, children: children }));
252
+ return ((0, jsx_runtime_1.jsxs)(exports.SiteDataContext.Provider, { value: value, children: [(0, jsx_runtime_1.jsx)(ResponsiveBaseStyles_1.ResponsiveBaseStyles, {}), children] }));
252
253
  }
253
254
  function useSiteData() {
254
255
  return (0, react_1.useContext)(exports.SiteDataContext);
@@ -70,7 +70,7 @@ function StickyMobileBar({ fieldPath, actions, showOnDesktop = false, className
70
70
  return ((0, jsx_runtime_1.jsx)("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13 10V3L4 14h7v7l9-11h-7z" }) }));
71
71
  }
72
72
  };
73
- return ((0, jsx_runtime_1.jsx)("aside", { className: `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: {
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
74
  backgroundColor: 'rgba(255, 255, 255, 0.92)',
75
75
  backdropFilter: 'blur(12px)',
76
76
  WebkitBackdropFilter: 'blur(12px)',
@@ -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 ResponsiveBaseStyles_1 = require("./ResponsiveBaseStyles");
8
9
  /**
9
10
  * Pre-configured, high-converting theme presets tailored for different business categories.
10
11
  * Allows developers and AI agents to instantly generate distinct designs without copy-pasting styles.
@@ -177,5 +178,5 @@ function ThemeStyles({ theme, defaultPrimary = '#2563eb', defaultSecondary = '#0
177
178
  ${cssLines}
178
179
  }
179
180
  `;
180
- return (0, jsx_runtime_1.jsx)("style", { dangerouslySetInnerHTML: { __html: css } });
181
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ResponsiveBaseStyles_1.ResponsiveBaseStyles, {}), (0, jsx_runtime_1.jsx)("style", { dangerouslySetInnerHTML: { __html: css } })] }));
181
182
  }
@@ -60,7 +60,7 @@ function TrustBadges({ fieldPath = 'content.trustBadges', title, subtitle, badge
60
60
  };
61
61
  return ((0, jsx_runtime_1.jsxs)("section", { className: `w-full py-8 my-4 ${className}`, "data-preview-field-path": fieldPath, style: style, children: [(title || subtitle) && ((0, jsx_runtime_1.jsxs)("div", { className: "text-center mb-8", children: [title && ((0, jsx_runtime_1.jsx)("h3", { className: "text-xl sm:text-2xl font-bold tracking-tight text-slate-900", children: title })), subtitle && ((0, jsx_runtime_1.jsx)("p", { className: "mt-1 text-sm text-slate-600 max-w-xl mx-auto", children: subtitle }))] })), (0, jsx_runtime_1.jsx)("div", { className: variant === 'inline'
62
62
  ? 'flex flex-wrap items-center justify-around gap-6'
63
- : 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-6', children: badges.map((badge) => ((0, jsx_runtime_1.jsxs)("div", { className: `flex items-start gap-4 p-5 rounded-2xl transition-all duration-200 hover:-translate-y-0.5 ${variant === 'cards'
63
+ : 'deneb-trust-grid grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-6', children: badges.map((badge) => ((0, jsx_runtime_1.jsxs)("div", { className: `flex items-start gap-4 p-5 rounded-2xl transition-all duration-200 hover:-translate-y-0.5 ${variant === 'cards'
64
64
  ? 'bg-white border border-slate-200/80 shadow-sm hover:shadow-md'
65
65
  : 'bg-transparent'}`, children: [(0, jsx_runtime_1.jsx)("div", { className: "flex-shrink-0 p-2.5 rounded-xl bg-slate-50 border border-slate-100 flex items-center justify-center", children: renderIcon(badge) }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-sm font-semibold text-slate-900 leading-tight", children: badge.title }), (0, jsx_runtime_1.jsx)("p", { className: "mt-1 text-xs text-slate-500 leading-relaxed", children: badge.description })] })] }, badge.id))) })] }));
66
66
  }
@@ -56,7 +56,8 @@ function FloatingContactWidget({ fieldPath = 'contact', defaultPhone, defaultWha
56
56
  position: 'absolute',
57
57
  bottom: '4.25rem',
58
58
  [isRight ? 'right' : 'left']: '0',
59
- width: '18rem',
59
+ width: 'min(18rem, calc(100vw - 2rem))',
60
+ maxWidth: 'calc(100vw - 2rem)',
60
61
  backgroundColor: '#ffffff',
61
62
  borderRadius: '1rem',
62
63
  boxShadow: '0 20px 25px -5px rgba(0, 0, 0, 0.15), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
@@ -64,5 +65,5 @@ function FloatingContactWidget({ fieldPath = 'contact', defaultPhone, defaultWha
64
65
  overflow: 'hidden',
65
66
  animation: 'deneb-pop 0.2s cubic-bezier(0.16, 1, 0.3, 1)',
66
67
  };
67
- return ((0, jsx_runtime_1.jsxs)("div", { className: `deneb-floating-contact fixed z-50 bottom-6 ${isRight ? 'right-6' : 'left-6'} ${className}`, style: containerStyle, "data-preview-field-path": fieldPath, children: [isOpen && ((0, jsx_runtime_1.jsxs)("div", { className: "deneb-contact-popup absolute bottom-16 bg-white rounded-2xl shadow-2xl border border-slate-200 w-72 overflow-hidden text-slate-800", style: menuStyle, children: [(0, jsx_runtime_1.jsxs)("div", { className: "bg-slate-900 text-white p-4 flex items-center justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h4", { className: "font-bold text-sm leading-tight text-white", children: storeName }), (0, jsx_runtime_1.jsxs)("p", { className: "text-xs text-emerald-400 font-medium flex items-center gap-1.5 mt-0.5", children: [(0, jsx_runtime_1.jsx)("span", { className: "w-2 h-2 rounded-full bg-emerald-400 animate-pulse" }), "Online & Ready to Help"] })] }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setIsOpen(false), className: "text-slate-400 hover:text-white p-1 rounded transition-colors", "aria-label": "Close contact drawer", children: (0, jsx_runtime_1.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", 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" })] }) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "p-3 space-y-2 text-sm bg-slate-50", children: [hasWhatsApp && ((0, jsx_runtime_1.jsxs)("a", { href: (0, urls_1.createWhatsAppUrl)(whatsapp, defaultMessage), target: "_blank", rel: "noopener noreferrer", className: "flex items-center gap-3 p-2.5 rounded-xl bg-white border border-slate-200/80 hover:border-emerald-400 hover:shadow-sm transition-all text-slate-800", "data-preview-field-path": `${fieldPath}.whatsapp`, children: [(0, jsx_runtime_1.jsx)("div", { className: "w-9 h-9 rounded-lg bg-emerald-50 text-emerald-600 flex items-center justify-center flex-shrink-0", children: (0, jsx_runtime_1.jsx)("svg", { width: "20", height: "20", 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-.694.062-1.116-.073-.266-.086-.61-.225-1.047-.417-1.854-.814-3.056-2.695-3.15-2.819-.092-.124-.755-.999-.755-1.907 0-.909.479-1.353.649-1.536.17-.183.371-.23.495-.23.124 0 .248.002.355.008.113.006.265-.043.414.316.155.372.531 1.296.577 1.39.046.094.077.204.015.328-.061.124-.092.202-.184.31-.092.108-.195.241-.278.324-.093.093-.19.195-.082.381.109.186.483.797 1.037 1.289.713.633 1.314.829 1.501.922.186.093.295.078.404-.047.11-.124.467-.543.591-.729.124-.186.248-.155.418-.093.17.062 1.082.51 1.268.603.186.093.31.14.356.217.046.077.046.449-.098.854z" }) }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 min-w-0", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-semibold text-slate-900 text-xs", children: "Chat on WhatsApp" }), (0, jsx_runtime_1.jsx)("div", { className: "text-[11px] text-slate-500 truncate", children: whatsapp })] })] })), hasPhone && ((0, jsx_runtime_1.jsxs)("a", { href: (0, urls_1.createPhoneUrl)(phone), className: "flex items-center gap-3 p-2.5 rounded-xl bg-white border border-slate-200/80 hover:border-blue-400 hover:shadow-sm transition-all text-slate-800", "data-preview-field-path": `${fieldPath}.phone`, children: [(0, jsx_runtime_1.jsx)("div", { className: "w-9 h-9 rounded-lg bg-blue-50 text-blue-600 flex items-center justify-center flex-shrink-0", children: (0, jsx_runtime_1.jsx)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", 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.jsxs)("div", { className: "flex-1 min-w-0", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-semibold text-slate-900 text-xs", children: "Direct Call" }), (0, jsx_runtime_1.jsx)("div", { className: "text-[11px] text-slate-500 truncate", children: phone })] })] })), hasEmail && ((0, jsx_runtime_1.jsxs)("a", { href: (0, urls_1.createEmailUrl)(email, `Inquiry: ${storeName}`), className: "flex items-center gap-3 p-2.5 rounded-xl bg-white border border-slate-200/80 hover:border-purple-400 hover:shadow-sm transition-all text-slate-800", "data-preview-field-path": `${fieldPath}.email`, children: [(0, jsx_runtime_1.jsx)("div", { className: "w-9 h-9 rounded-lg bg-purple-50 text-purple-600 flex items-center justify-center flex-shrink-0", children: (0, jsx_runtime_1.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [(0, jsx_runtime_1.jsx)("path", { d: "M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z" }), (0, jsx_runtime_1.jsx)("polyline", { points: "22,6 12,13 2,6" })] }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 min-w-0", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-semibold text-slate-900 text-xs", children: "Send Email" }), (0, jsx_runtime_1.jsx)("div", { className: "text-[11px] text-slate-500 truncate", children: email })] })] }))] })] })), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setIsOpen(!isOpen), style: bubbleStyle, className: "deneb-bubble hover:scale-105 active:scale-95 flex items-center justify-center focus:outline-none", "aria-label": "Toggle contact channels", children: isOpen ? ((0, jsx_runtime_1.jsxs)("svg", { width: "24", height: "24", 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" })] })) : ((0, jsx_runtime_1.jsx)("svg", { width: "28", height: "28", 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-.694.062-1.116-.073-.266-.086-.61-.225-1.047-.417-1.854-.814-3.056-2.695-3.15-2.819-.092-.124-.755-.999-.755-1.907 0-.909.479-1.353.649-1.536.17-.183.371-.23.495-.23.124 0 .248.002.355.008.113.006.265-.043.414.316.155.372.531 1.296.577 1.39.046.094.077.204.015.328-.061.124-.092.202-.184.31-.092.108-.195.241-.278.324-.093.093-.19.195-.082.381.109.186.483.797 1.037 1.289.713.633 1.314.829 1.501.922.186.093.295.078.404-.047.11-.124.467-.543.591-.729.124-.186.248-.155.418-.093.17.062 1.082.51 1.268.603.186.093.31.14.356.217.046.077.046.449-.098.854z" }) })) })] }));
68
+ return ((0, jsx_runtime_1.jsxs)("div", { className: `deneb-floating-contact fixed z-50 bottom-6 ${isRight ? 'right-6 deneb-floating-right' : 'left-6 deneb-floating-left'} ${className}`, style: containerStyle, "data-preview-field-path": fieldPath, children: [isOpen && ((0, jsx_runtime_1.jsxs)("div", { className: "deneb-contact-popup absolute bottom-16 bg-white rounded-2xl shadow-2xl border border-slate-200 w-72 overflow-hidden text-slate-800", style: menuStyle, children: [(0, jsx_runtime_1.jsxs)("div", { className: "bg-slate-900 text-white p-4 flex items-center justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h4", { className: "font-bold text-sm leading-tight text-white", children: storeName }), (0, jsx_runtime_1.jsxs)("p", { className: "text-xs text-emerald-400 font-medium flex items-center gap-1.5 mt-0.5", children: [(0, jsx_runtime_1.jsx)("span", { className: "w-2 h-2 rounded-full bg-emerald-400 animate-pulse" }), "Online & Ready to Help"] })] }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setIsOpen(false), className: "text-slate-400 hover:text-white p-1 rounded transition-colors", "aria-label": "Close contact drawer", children: (0, jsx_runtime_1.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", 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" })] }) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "p-3 space-y-2 text-sm bg-slate-50", children: [hasWhatsApp && ((0, jsx_runtime_1.jsxs)("a", { href: (0, urls_1.createWhatsAppUrl)(whatsapp, defaultMessage), target: "_blank", rel: "noopener noreferrer", className: "flex items-center gap-3 p-2.5 rounded-xl bg-white border border-slate-200/80 hover:border-emerald-400 hover:shadow-sm transition-all text-slate-800", "data-preview-field-path": `${fieldPath}.whatsapp`, children: [(0, jsx_runtime_1.jsx)("div", { className: "w-9 h-9 rounded-lg bg-emerald-50 text-emerald-600 flex items-center justify-center flex-shrink-0", children: (0, jsx_runtime_1.jsx)("svg", { width: "20", height: "20", 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-.694.062-1.116-.073-.266-.086-.61-.225-1.047-.417-1.854-.814-3.056-2.695-3.15-2.819-.092-.124-.755-.999-.755-1.907 0-.909.479-1.353.649-1.536.17-.183.371-.23.495-.23.124 0 .248.002.355.008.113.006.265-.043.414.316.155.372.531 1.296.577 1.39.046.094.077.204.015.328-.061.124-.092.202-.184.31-.092.108-.195.241-.278.324-.093.093-.19.195-.082.381.109.186.483.797 1.037 1.289.713.633 1.314.829 1.501.922.186.093.295.078.404-.047.11-.124.467-.543.591-.729.124-.186.248-.155.418-.093.17.062 1.082.51 1.268.603.186.093.31.14.356.217.046.077.046.449-.098.854z" }) }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 min-w-0", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-semibold text-slate-900 text-xs", children: "Chat on WhatsApp" }), (0, jsx_runtime_1.jsx)("div", { className: "text-[11px] text-slate-500 truncate", children: whatsapp })] })] })), hasPhone && ((0, jsx_runtime_1.jsxs)("a", { href: (0, urls_1.createPhoneUrl)(phone), className: "flex items-center gap-3 p-2.5 rounded-xl bg-white border border-slate-200/80 hover:border-blue-400 hover:shadow-sm transition-all text-slate-800", "data-preview-field-path": `${fieldPath}.phone`, children: [(0, jsx_runtime_1.jsx)("div", { className: "w-9 h-9 rounded-lg bg-blue-50 text-blue-600 flex items-center justify-center flex-shrink-0", children: (0, jsx_runtime_1.jsx)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", 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.jsxs)("div", { className: "flex-1 min-w-0", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-semibold text-slate-900 text-xs", children: "Direct Call" }), (0, jsx_runtime_1.jsx)("div", { className: "text-[11px] text-slate-500 truncate", children: phone })] })] })), hasEmail && ((0, jsx_runtime_1.jsxs)("a", { href: (0, urls_1.createEmailUrl)(email, `Inquiry: ${storeName}`), className: "flex items-center gap-3 p-2.5 rounded-xl bg-white border border-slate-200/80 hover:border-purple-400 hover:shadow-sm transition-all text-slate-800", "data-preview-field-path": `${fieldPath}.email`, children: [(0, jsx_runtime_1.jsx)("div", { className: "w-9 h-9 rounded-lg bg-purple-50 text-purple-600 flex items-center justify-center flex-shrink-0", children: (0, jsx_runtime_1.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [(0, jsx_runtime_1.jsx)("path", { d: "M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z" }), (0, jsx_runtime_1.jsx)("polyline", { points: "22,6 12,13 2,6" })] }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 min-w-0", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-semibold text-slate-900 text-xs", children: "Send Email" }), (0, jsx_runtime_1.jsx)("div", { className: "text-[11px] text-slate-500 truncate", children: email })] })] }))] })] })), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setIsOpen(!isOpen), style: bubbleStyle, className: "deneb-bubble hover:scale-105 active:scale-95 flex items-center justify-center focus:outline-none", "aria-label": "Toggle contact channels", children: isOpen ? ((0, jsx_runtime_1.jsxs)("svg", { width: "24", height: "24", 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" })] })) : ((0, jsx_runtime_1.jsx)("svg", { width: "28", height: "28", 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-.694.062-1.116-.073-.266-.086-.61-.225-1.047-.417-1.854-.814-3.056-2.695-3.15-2.819-.092-.124-.755-.999-.755-1.907 0-.909.479-1.353.649-1.536.17-.183.371-.23.495-.23.124 0 .248.002.355.008.113.006.265-.043.414.316.155.372.531 1.296.577 1.39.046.094.077.204.015.328-.061.124-.092.202-.184.31-.092.108-.195.241-.278.324-.093.093-.19.195-.082.381.109.186.483.797 1.037 1.289.713.633 1.314.829 1.501.922.186.093.295.078.404-.047.11-.124.467-.543.591-.729.124-.186.248-.155.418-.093.17.062 1.082.51 1.268.603.186.093.31.14.356.217.046.077.046.449-.098.854z" }) })) })] }));
68
69
  }
package/dist/index.d.ts CHANGED
@@ -32,6 +32,8 @@ export * from './cart/useCart';
32
32
  export * from './EditableCartDrawer';
33
33
  export * from './EditableFilterSidebar';
34
34
  export * from './SiteDataProvider';
35
+ export * from './ThemeStyles';
36
+ export { ResponsiveBaseStyles } from './ResponsiveBaseStyles';
35
37
  export * from './utils';
36
38
  export * from './core';
37
39
  export * from './contact';
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
18
18
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.DENEB_AUTHOR = exports.DENEB_FRAMEWORK_VERSION = exports.DENEB_FRAMEWORK_NAME = exports.FilterSidebar = exports.CartDrawer = exports.FloatingContactWidget = exports.CookieConsentBanner = exports.ProductQuickView = exports.TrustBadges = exports.StickyMobileBar = exports.CategoryPills = exports.AnnouncementBar = exports.HeroSplit = exports.Hero = exports.Footer = exports.Header = exports.Navbar = exports.ContactForm = exports.FAQ = exports.Accordion = exports.TestimonialCard = exports.PricingCard = exports.ServiceCard = exports.CustomerReviews = exports.ProductDetail = exports.ProductGrid = exports.ProductCard = exports.List = exports.Box = exports.Section = exports.Grid = exports.Image = exports.Quote = exports.Badge = exports.Paragraph = exports.Heading = exports.Text = exports.Dialog = exports.Card = exports.Button = void 0;
21
+ exports.DENEB_AUTHOR = exports.DENEB_FRAMEWORK_VERSION = exports.DENEB_FRAMEWORK_NAME = exports.FilterSidebar = exports.CartDrawer = exports.FloatingContactWidget = exports.CookieConsentBanner = exports.ProductQuickView = exports.TrustBadges = exports.StickyMobileBar = exports.CategoryPills = exports.AnnouncementBar = exports.HeroSplit = exports.Hero = exports.Footer = exports.Header = exports.Navbar = exports.ContactForm = exports.FAQ = exports.Accordion = exports.TestimonialCard = exports.PricingCard = exports.ServiceCard = exports.CustomerReviews = exports.ProductDetail = exports.ProductGrid = exports.ProductCard = exports.List = exports.Box = exports.Section = exports.Grid = exports.Image = exports.Quote = exports.Badge = exports.Paragraph = exports.Heading = exports.Text = exports.Dialog = exports.Card = exports.Button = exports.ResponsiveBaseStyles = void 0;
22
22
  __exportStar(require("./EditableText"), exports);
23
23
  __exportStar(require("./EditableImage"), exports);
24
24
  __exportStar(require("./EditableList"), exports);
@@ -49,6 +49,9 @@ __exportStar(require("./cart/useCart"), exports);
49
49
  __exportStar(require("./EditableCartDrawer"), exports);
50
50
  __exportStar(require("./EditableFilterSidebar"), exports);
51
51
  __exportStar(require("./SiteDataProvider"), exports);
52
+ __exportStar(require("./ThemeStyles"), exports);
53
+ var ResponsiveBaseStyles_1 = require("./ResponsiveBaseStyles");
54
+ Object.defineProperty(exports, "ResponsiveBaseStyles", { enumerable: true, get: function () { return ResponsiveBaseStyles_1.ResponsiveBaseStyles; } });
52
55
  // Smart template components & actions
53
56
  __exportStar(require("./utils"), exports);
54
57
  __exportStar(require("./core"), exports);
@@ -1 +1,2 @@
1
1
  export * from './urls';
2
+ export * from './responsive';
@@ -15,3 +15,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./urls"), exports);
18
+ __exportStar(require("./responsive"), exports);
@@ -0,0 +1,33 @@
1
+ /** Standard DENEB UI breakpoints (mobile-first). */
2
+ export declare const BREAKPOINTS: {
3
+ readonly xs: 480;
4
+ readonly sm: 640;
5
+ readonly md: 768;
6
+ readonly lg: 1024;
7
+ readonly xl: 1280;
8
+ };
9
+ export type BreakpointKey = keyof typeof BREAKPOINTS;
10
+ export type DeviceTier = 'mobile' | 'tablet' | 'desktop';
11
+ export declare function getDeviceTier(width: number): DeviceTier;
12
+ export declare function mediaQueryUp(breakpoint: BreakpointKey): string;
13
+ export declare function mediaQueryDown(breakpoint: BreakpointKey): string;
14
+ /**
15
+ * Subscribe to a min-width media query. SSR-safe (defaults to false until mounted).
16
+ */
17
+ export declare function useMediaQuery(query: string, defaultValue?: boolean): boolean;
18
+ /** Current viewport tier: mobile (<768), tablet (768–1023), desktop (≥1024). */
19
+ export declare function useDeviceTier(): DeviceTier;
20
+ export declare function useIsMobile(): boolean;
21
+ export declare function useIsTablet(): boolean;
22
+ export declare function useIsDesktop(): boolean;
23
+ /** Map section padding tokens to fluid clamp values that scale across devices. */
24
+ export declare const RESPONSIVE_SECTION_PADDING: Record<string, string>;
25
+ export interface ResponsiveColumnsConfig {
26
+ mobile?: number;
27
+ tablet?: number;
28
+ desktop?: number;
29
+ }
30
+ export declare function resolveResponsiveColumns(columns: number | ResponsiveColumnsConfig | undefined, minCardWidth?: string): {
31
+ template: string;
32
+ dataAttrs?: Record<string, string>;
33
+ };
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.RESPONSIVE_SECTION_PADDING = exports.BREAKPOINTS = void 0;
5
+ exports.getDeviceTier = getDeviceTier;
6
+ exports.mediaQueryUp = mediaQueryUp;
7
+ exports.mediaQueryDown = mediaQueryDown;
8
+ exports.useMediaQuery = useMediaQuery;
9
+ exports.useDeviceTier = useDeviceTier;
10
+ exports.useIsMobile = useIsMobile;
11
+ exports.useIsTablet = useIsTablet;
12
+ exports.useIsDesktop = useIsDesktop;
13
+ exports.resolveResponsiveColumns = resolveResponsiveColumns;
14
+ const react_1 = require("react");
15
+ /** Standard DENEB UI breakpoints (mobile-first). */
16
+ exports.BREAKPOINTS = {
17
+ xs: 480,
18
+ sm: 640,
19
+ md: 768,
20
+ lg: 1024,
21
+ xl: 1280,
22
+ };
23
+ function getDeviceTier(width) {
24
+ if (width < exports.BREAKPOINTS.md)
25
+ return 'mobile';
26
+ if (width < exports.BREAKPOINTS.lg)
27
+ return 'tablet';
28
+ return 'desktop';
29
+ }
30
+ function mediaQueryUp(breakpoint) {
31
+ return `(min-width: ${exports.BREAKPOINTS[breakpoint]}px)`;
32
+ }
33
+ function mediaQueryDown(breakpoint) {
34
+ return `(max-width: ${exports.BREAKPOINTS[breakpoint] - 0.02}px)`;
35
+ }
36
+ /**
37
+ * Subscribe to a min-width media query. SSR-safe (defaults to false until mounted).
38
+ */
39
+ function useMediaQuery(query, defaultValue = false) {
40
+ const [matches, setMatches] = (0, react_1.useState)(defaultValue);
41
+ (0, react_1.useEffect)(() => {
42
+ if (typeof window === 'undefined' || typeof window.matchMedia !== 'function')
43
+ return;
44
+ const mql = window.matchMedia(query);
45
+ const onChange = () => setMatches(mql.matches);
46
+ onChange();
47
+ mql.addEventListener('change', onChange);
48
+ return () => mql.removeEventListener('change', onChange);
49
+ }, [query]);
50
+ return matches;
51
+ }
52
+ /** Current viewport tier: mobile (<768), tablet (768–1023), desktop (≥1024). */
53
+ function useDeviceTier() {
54
+ const isDesktop = useMediaQuery(mediaQueryUp('lg'));
55
+ const isTablet = useMediaQuery(mediaQueryUp('md'));
56
+ if (isDesktop)
57
+ return 'desktop';
58
+ if (isTablet)
59
+ return 'tablet';
60
+ return 'mobile';
61
+ }
62
+ function useIsMobile() {
63
+ return useDeviceTier() === 'mobile';
64
+ }
65
+ function useIsTablet() {
66
+ return useDeviceTier() === 'tablet';
67
+ }
68
+ function useIsDesktop() {
69
+ return useDeviceTier() === 'desktop';
70
+ }
71
+ /** Map section padding tokens to fluid clamp values that scale across devices. */
72
+ exports.RESPONSIVE_SECTION_PADDING = {
73
+ none: '0',
74
+ xs: 'clamp(1rem, 3vw, 1.5rem) 0',
75
+ sm: 'clamp(1.5rem, 4vw, 2.5rem) 0',
76
+ md: 'clamp(2rem, 5vw, 4rem) 0',
77
+ lg: 'clamp(2.5rem, 6vw, 6rem) 0',
78
+ xl: 'clamp(3rem, 7vw, 8rem) 0',
79
+ '2xl': 'clamp(3.5rem, 8vw, 10rem) 0',
80
+ };
81
+ function resolveResponsiveColumns(columns, minCardWidth = '280px') {
82
+ if (typeof columns === 'number') {
83
+ return { template: `repeat(${columns}, minmax(0, 1fr))` };
84
+ }
85
+ if (columns && typeof columns === 'object') {
86
+ const mobile = columns.mobile ?? 1;
87
+ const tablet = columns.tablet ?? columns.mobile ?? 2;
88
+ const desktop = columns.desktop ?? columns.tablet ?? 3;
89
+ return {
90
+ template: `repeat(${mobile}, minmax(0, 1fr))`,
91
+ dataAttrs: {
92
+ 'data-deneb-responsive-cols': 'true',
93
+ 'data-cols-mobile': String(mobile),
94
+ 'data-cols-tablet': String(tablet),
95
+ 'data-cols-desktop': String(desktop),
96
+ },
97
+ };
98
+ }
99
+ return { template: `repeat(auto-fit, minmax(${minCardWidth}, 1fr))` };
100
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deneb-ui/ui",
3
- "version": "2.0.22",
4
- "description": "DENEB UI - The premier visual-first React component framework for the modern web. Created by Chamika Gayashan & Induranga Kawishwara.",
3
+ "version": "2.0.23",
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",
7
7
  "publishConfig": {
@@ -12,7 +12,7 @@
12
12
  "url": "git+https://github.com/deneb-ui/core.git",
13
13
  "directory": "packages/deneb-ui"
14
14
  },
15
- "homepage": "https://github.com/deneb-ui/core#readme",
15
+ "homepage": "https://deneb.fivora.site",
16
16
  "bugs": {
17
17
  "url": "https://github.com/deneb-ui/core/issues"
18
18
  },
@@ -28,14 +28,23 @@
28
28
  "deneb",
29
29
  "deneb-ui",
30
30
  "fivora",
31
+ "react",
32
+ "nextjs",
33
+ "components",
34
+ "ui",
31
35
  "ecommerce",
32
- "shadcn",
33
- "heroui",
36
+ "storefront",
34
37
  "visual-editing",
35
- "nextjs",
36
- "react"
38
+ "responsive",
39
+ "typescript",
40
+ "shadcn",
41
+ "tailwind"
37
42
  ],
38
43
  "author": "Chamika Gayashan & Induranga Kawishwara",
44
+ "contributors": [
45
+ "Chamika Gayashan <https://github.com/chamikathereal>",
46
+ "Induranga Kawishwara <https://github.com/Induranga-kawishwara>"
47
+ ],
39
48
  "license": "MIT",
40
49
  "dependencies": {},
41
50
  "peerDependencies": {