@deneb-ui/ui 2.0.48 → 2.0.50

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
@@ -156,8 +156,12 @@ export default function Page() {
156
156
  ### 7. Runtime State & Theming Primitives
157
157
  | Component / Hook | Module Path | Purpose |
158
158
  | :--- | :--- | :--- |
159
- | `SiteDataProvider` | `SiteDataProvider` | Real-time `BroadcastChannel` & `postMessage` state synchronizer |
160
- | `useSiteData` | `SiteDataProvider` | React hook to access live synchronized `siteData` |
159
+ | `SiteDataProvider` / `DenebDataProvider` | `SiteDataProvider` | Real-time backend catalog fetcher & `postMessage` preview state synchronizer |
160
+ | `useProducts` | `SiteDataProvider` | React hook to access live synchronized products list (`content.products`) |
161
+ | `useServices` | `SiteDataProvider` | React hook to access live synchronized services list (`content.services`) |
162
+ | `useSiteCatalog` | `SiteDataProvider` | Returns `{ products, services, project, siteInstance, api }` in one call |
163
+ | `useSiteApi` | `SiteDataProvider` | Returns official Fivora backend endpoints (`catalogUrl`, `contactUrl`, `analyticsUrl`) |
164
+ | `useSiteData` / `useDenebData` | `SiteDataProvider` | React hook to access full live synchronized `siteData` |
161
165
  | `ThemeStyles` | `ThemeStyles` | Dynamic CSS variable injector for colors, fonts, and radii |
162
166
  | `ResponsiveBaseStyles`| `ResponsiveBaseStyles` | Universal fluid typography & responsive baseline styles |
163
167
  | `DenebComponentStyles`| `DenebComponentStyles` | Scoped component style definitions |
@@ -165,6 +169,94 @@ export default function Page() {
165
169
  | `useDenebFonts` | `fonts/useDenebFonts` | Hook for checking active font definitions |
166
170
  | `CartProvider` / `useCart`| `cart/useCart` | Global cart state management with persistent storage |
167
171
 
172
+ ---
173
+
174
+ ## Data Fetching & Backend Integration Hooks
175
+
176
+ ### 1. `useProducts(fallback?: ProductItem[])`
177
+ Retrieves the live products list from the site data. Automatically resolves top-level `content.products`, nested `content.home.products`, and live backend rehydration updates from `api.catalogUrl`.
178
+
179
+ ```tsx
180
+ import { useProducts, ProductGrid } from '@deneb-ui/ui';
181
+
182
+ export default function CatalogSection() {
183
+ const products = useProducts();
184
+
185
+ return (
186
+ <ProductGrid
187
+ title="Featured Collection"
188
+ subtitle="Handpicked Styles"
189
+ products={products}
190
+ categories={['All', 'Accessories', 'Apparel']}
191
+ cardVariant="modern-glass" // 'modern-glass' | 'classic' | 'minimal' | 'horizontal'
192
+ columns={{ mobile: 1, tablet: 2, desktop: 3 }}
193
+ />
194
+ );
195
+ }
196
+ ```
197
+
198
+ ### 2. `useSiteApi()`
199
+ Returns the official backend API configuration object (`SiteDataApiConfig`) defined in `site-data.json`. Use this hook whenever you need to connect custom forms or direct API calls to the backend:
200
+
201
+ ```tsx
202
+ import { useSiteApi } from '@deneb-ui/ui';
203
+
204
+ export default function ApiDemo() {
205
+ const api = useSiteApi();
206
+
207
+ // api?.baseUrl -> "https://api.fivora.site"
208
+ // api?.catalogUrl -> "https://api.fivora.site/site-catalog/:slug/live-data"
209
+ // api?.contactUrl -> "https://api.fivora.site/site-contact"
210
+ // api?.analyticsUrl -> "https://api.fivora.site/site-analytics/page-view"
211
+
212
+ return null;
213
+ }
214
+ ```
215
+
216
+ ### 3. `useSiteCatalog()`
217
+ Convenience hook that bundles catalog metadata and live status together:
218
+
219
+ ```tsx
220
+ import { useSiteCatalog } from '@deneb-ui/ui';
221
+
222
+ export default function CatalogOverview() {
223
+ const { products, services, project, siteInstance, api } = useSiteCatalog();
224
+
225
+ return (
226
+ <div>
227
+ <h3>{project?.title}</h3>
228
+ <p>Active live products: {products.length}</p>
229
+ <p>Active live services: {services.length}</p>
230
+ </div>
231
+ );
232
+ }
233
+ ```
234
+
235
+ ### 4. `useServices(fallback?: ServiceItem[])`
236
+ Retrieves the live services list from `content.services` or `content.home.services`:
237
+
238
+ ```tsx
239
+ import { useServices, ServiceCard } from '@deneb-ui/ui';
240
+
241
+ export default function ServicesList() {
242
+ const services = useServices();
243
+
244
+ return (
245
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
246
+ {services.map((service, index) => (
247
+ <ServiceCard
248
+ key={service.id || index}
249
+ itemPath={`services[${index}]`}
250
+ service={service}
251
+ />
252
+ ))}
253
+ </div>
254
+ );
255
+ }
256
+ ```
257
+
258
+ ---
259
+
168
260
  ## Component Guides & API Reference
169
261
 
170
262
  ### 1. `GoogleFeedback` (`EditableGoogleFeedback`)
@@ -19,11 +19,12 @@ export interface EditableProductGridProps extends React.HTMLAttributes<HTMLEleme
19
19
  */
20
20
  subtitle?: string;
21
21
  /**
22
- * Array of product items.
22
+ * Array of product items. If omitted or empty, automatically pulls live products using useProducts().
23
23
  */
24
- products: ProductItem[];
24
+ products?: ProductItem[];
25
25
  /**
26
26
  * Optional category filter tabs (e.g. ['All', 'Sneakers', 'Performance', 'Lifestyle']).
27
+ * If omitted, automatically derived from product categories.
27
28
  */
28
29
  categories?: string[];
29
30
  /**
@@ -52,9 +53,9 @@ export interface EditableProductGridProps extends React.HTMLAttributes<HTMLEleme
52
53
  /**
53
54
  * EditableProductGrid is an elite, fully responsive e-commerce showcase grid
54
55
  * with interactive category filtering, live Fivora visual editing synchronization,
55
- * and built-in Quick View modal triggers.
56
+ * automatic useProducts() fallback rehydration, and built-in Quick View modal triggers.
56
57
  *
57
58
  * Created by Chamika Gayashan & Induranga Kawishwara
58
59
  */
59
- export declare function EditableProductGrid({ sectionPath, listPath, title, subtitle, products, categories, cardVariant, columns, onQuickView, cardPrefix, className, style, ...props }: EditableProductGridProps): React.JSX.Element;
60
+ export declare function EditableProductGrid({ sectionPath, listPath, title, subtitle, products: userProducts, categories, cardVariant, columns, onQuickView, cardPrefix, className, style, ...props }: EditableProductGridProps): React.JSX.Element;
60
61
  export declare const ProductGrid: typeof EditableProductGrid;
@@ -5,14 +5,26 @@ exports.EditableProductGrid = EditableProductGrid;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const react_1 = require("react");
7
7
  const EditableProductCard_1 = require("./EditableProductCard");
8
+ const SiteDataProvider_1 = require("./SiteDataProvider");
8
9
  /**
9
10
  * EditableProductGrid is an elite, fully responsive e-commerce showcase grid
10
11
  * with interactive category filtering, live Fivora visual editing synchronization,
11
- * and built-in Quick View modal triggers.
12
+ * automatic useProducts() fallback rehydration, and built-in Quick View modal triggers.
12
13
  *
13
14
  * Created by Chamika Gayashan & Induranga Kawishwara
14
15
  */
15
- function EditableProductGrid({ sectionPath = 'home', listPath = 'products', title = 'Featured Collection', subtitle = 'Just Dropped', products = [], categories = ['All'], cardVariant = 'modern-glass', columns = { mobile: 1, tablet: 2, desktop: 4 }, onQuickView, cardPrefix = 'product', className = '', style, ...props }) {
16
+ function EditableProductGrid({ sectionPath = 'home', listPath = 'products', title = 'Featured Collection', subtitle = 'Just Dropped', products: userProducts, categories = ['All'], cardVariant = 'modern-glass', columns = { mobile: 1, tablet: 2, desktop: 4 }, onQuickView, cardPrefix = 'product', className = '', style, ...props }) {
17
+ const liveProducts = (0, SiteDataProvider_1.useProducts)();
18
+ const products = userProducts && userProducts.length > 0 ? userProducts : liveProducts;
19
+ const resolvedCategories = (0, react_1.useMemo)(() => {
20
+ if (categories && categories.length > 1) {
21
+ return categories;
22
+ }
23
+ const distinct = Array.from(new Set(products
24
+ .map((p) => p.category)
25
+ .filter((cat) => typeof cat === 'string' && cat.trim().length > 0)));
26
+ return distinct.length > 0 ? ['All', ...distinct] : categories;
27
+ }, [categories, products]);
16
28
  const [activeCategory, setActiveCategory] = (0, react_1.useState)(categories[0] || 'All');
17
29
  const filteredProducts = (0, react_1.useMemo)(() => {
18
30
  if (!activeCategory || activeCategory.toLowerCase() === 'all') {
@@ -33,7 +45,7 @@ function EditableProductGrid({ sectionPath = 'home', listPath = 'products', titl
33
45
  const dClass = d === 3 ? 'lg:grid-cols-3' : d === 2 ? 'lg:grid-cols-2' : 'lg:grid-cols-4';
34
46
  return `${mClass} ${tClass} ${dClass}`;
35
47
  }, [columns]);
36
- return ((0, jsx_runtime_1.jsxs)("section", { "data-preview-page-key": sectionPath, className: `editable-product-grid max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16 ${className}`.trim(), style: style, ...props, children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col md:flex-row md:items-end justify-between mb-10 gap-6", children: [(0, jsx_runtime_1.jsxs)("div", { children: [subtitle && ((0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.gridSubtitle`, className: "text-xs font-black tracking-widest uppercase text-lime-400 block mb-2", children: subtitle })), (0, jsx_runtime_1.jsx)("h2", { "data-preview-field-path": `${sectionPath}.gridTitle`, className: "text-3xl sm:text-4xl font-extrabold tracking-tight text-white leading-tight", children: title })] }), categories.length > 1 && ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-wrap items-center gap-2", children: categories.map((cat) => {
48
+ return ((0, jsx_runtime_1.jsxs)("section", { "data-preview-page-key": sectionPath, className: `editable-product-grid max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16 ${className}`.trim(), style: style, ...props, children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col md:flex-row md:items-end justify-between mb-10 gap-6", children: [(0, jsx_runtime_1.jsxs)("div", { children: [subtitle && ((0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.gridSubtitle`, className: "text-xs font-black tracking-widest uppercase text-lime-400 block mb-2", children: subtitle })), (0, jsx_runtime_1.jsx)("h2", { "data-preview-field-path": `${sectionPath}.gridTitle`, className: "text-3xl sm:text-4xl font-extrabold tracking-tight text-white leading-tight", children: title })] }), resolvedCategories.length > 1 && ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-wrap items-center gap-2", children: resolvedCategories.map((cat) => {
37
49
  const isActive = activeCategory.toLowerCase() === cat.toLowerCase();
38
50
  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
51
  ? 'bg-white text-slate-950 shadow-md scale-102 font-extrabold'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deneb-ui/ui",
3
- "version": "2.0.48",
3
+ "version": "2.0.50",
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",
@@ -49,7 +49,7 @@
49
49
  ],
50
50
  "license": "MIT",
51
51
  "dependencies": {
52
- "@deneb-ui/core": "^2.0.48"
52
+ "@deneb-ui/core": "^2.0.50"
53
53
  },
54
54
  "peerDependencies": {
55
55
  "react": "^18.0.0 || ^19.0.0",