@mandolop97/constructor-nexora 1.3.1 → 1.7.0

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.
Files changed (39) hide show
  1. package/dist/NexoraBuilderApp.d.ts +8 -1
  2. package/dist/components/builder/ArrayEditor.d.ts +27 -0
  3. package/dist/components/builder/BindingsPanel.d.ts +7 -0
  4. package/dist/components/builder/BuilderCanvas.d.ts +10 -1
  5. package/dist/components/builder/BuilderEditorShell.d.ts +8 -1
  6. package/dist/components/builder/Inspector.d.ts +5 -2
  7. package/dist/components/builder/ThemeEditor.d.ts +4 -2
  8. package/dist/components/schema/NodeRegistry.d.ts +3 -1
  9. package/dist/components/schema/PageRenderer.d.ts +10 -1
  10. package/dist/components/schema/ScrollAnimationWrapper.d.ts +10 -0
  11. package/dist/components/schema/SortableNodeWrapper.d.ts +4 -1
  12. package/dist/components/schema/ThemeContext.d.ts +3 -0
  13. package/dist/components/schema/nodes/CommerceNodes.d.ts +3 -0
  14. package/dist/components/schema/nodes/TemplateNodes.d.ts +5 -0
  15. package/dist/components/ui/badge.d.ts +1 -1
  16. package/dist/components/ui/button.d.ts +2 -2
  17. package/dist/components/ui/resizable.d.ts +1 -1
  18. package/dist/components/ui/sheet.d.ts +1 -1
  19. package/dist/components/ui/sidebar.d.ts +1 -1
  20. package/dist/components/ui/toggle-group.d.ts +2 -2
  21. package/dist/components/ui/toggle.d.ts +2 -2
  22. package/dist/{index-7fNEj0ds.js → index-BPfPxgpF.js} +11889 -9283
  23. package/dist/index.css +1 -1
  24. package/dist/index.d.ts +14 -1
  25. package/dist/index.js +81 -40
  26. package/dist/lib/binding-utils.d.ts +51 -0
  27. package/dist/lib/block-registry.d.ts +30 -4
  28. package/dist/lib/card-template-utils.d.ts +35 -0
  29. package/dist/lib/host-data.d.ts +69 -0
  30. package/dist/lib/mock-data.d.ts +5 -0
  31. package/dist/lib/publish-validator.d.ts +33 -0
  32. package/dist/lib/render-context-utils.d.ts +55 -0
  33. package/dist/lib/slot-utils.d.ts +66 -0
  34. package/dist/lib/style-utils.d.ts +13 -0
  35. package/dist/{lucide-react-xAdwTOxQ.js → lucide-react-D6zDllQb.js} +8214 -8313
  36. package/dist/types/contract.d.ts +475 -0
  37. package/dist/types/page-types.d.ts +65 -0
  38. package/dist/types/schema.d.ts +21 -1
  39. package/package.json +1 -1
@@ -0,0 +1,475 @@
1
+ /**
2
+ * ════════════════════════════════════════════════════════════════════════════
3
+ * NEXORA VISUAL BUILDER — OFFICIAL CONTRACT v1.7.0
4
+ * ════════════════════════════════════════════════════════════════════════════
5
+ *
6
+ * This file defines the **shared contract** between the Nexora Visual Builder
7
+ * and any host template that installs it via NPM.
8
+ *
9
+ * Both systems MUST use these exact types, names, and structures to ensure
10
+ * full compatibility and seamless data flow.
11
+ *
12
+ * VERSION: 1.7.0
13
+ *
14
+ * ── DATA OWNERSHIP POLICY ──
15
+ *
16
+ * ┌─────────────┬────────────────────────────┬───────────────────────────┐
17
+ * │ Layer │ Responsibility │ Prohibitions │
18
+ * ├─────────────┼────────────────────────────┼───────────────────────────┤
19
+ * │ Host/Template│ Fetch + adapt data. │ Cannot modify schema │
20
+ * │ (consumer) │ Build RenderContext. │ nodes directly. │
21
+ * │ │ Provide hostData. │ │
22
+ * ├─────────────┼────────────────────────────┼───────────────────────────┤
23
+ * │ Builder │ Schema CRUD. │ NO fetch to external APIs │
24
+ * │ (editor) │ Adapt hostData for preview. │ NO direct DB calls for │
25
+ * │ │ Validate before publish. │ business data. │
26
+ * ├─────────────┼────────────────────────────┼───────────────────────────┤
27
+ * │ Renderer │ Render nodes from schema + │ NO fetch. NO state │
28
+ * │ (PageRender)│ resolved context. Pure. │ mutation. Read-only. │
29
+ * └─────────────┴────────────────────────────┴───────────────────────────┘
30
+ */
31
+ import { NodeStyle, ThemeTokens, AnimationPreset, SchemaNode, Schema } from './schema';
32
+ import { PageType, PageMetadata } from './page-types';
33
+ /** All built-in node types supported by the builder */
34
+ export type BuiltInNodeType = 'Section' | 'Container' | 'Grid' | 'Stack' | 'Text' | 'Image' | 'Divider' | 'Badge' | 'Spacer' | 'Icon' | 'SocialIcons' | 'Button' | 'Card' | 'Input' | 'Accordion' | 'TabsBlock' | 'VideoEmbed' | 'FormBlock' | 'ProductCard' | 'ProductGrid' | 'CollectionGrid' | 'Navbar' | 'Footer' | 'AnnouncementBar' | 'HeroSection' | 'FeatureBar' | 'TestimonialCard' | 'NewsletterSection' | 'ImageBanner' | 'RichTextSection' | 'CTASection' | 'TestimonialSection' | 'FAQSection';
35
+ /** Extensible node type — accepts built-in types plus any custom string */
36
+ export type NodeType = BuiltInNodeType | (string & {});
37
+ /** Supported data sources for binding */
38
+ export type DataSourceType = 'products' | 'collections' | 'pages' | 'media' | 'settings' | 'custom';
39
+ /** A binding maps a node prop to a data field */
40
+ export interface DataBinding {
41
+ /** The prop key on the node (e.g., 'text', 'src', 'price') */
42
+ propKey: string;
43
+ /** The field path in the data source (e.g., 'product.title', 'product.images[0].url') */
44
+ fieldPath: string;
45
+ /** Optional transform function name (e.g., 'formatPrice', 'uppercase') */
46
+ transform?: string;
47
+ }
48
+ /** Data source configuration for a node */
49
+ export interface NodeDataSource {
50
+ /** Type of data source */
51
+ type: DataSourceType;
52
+ /** Query/filter parameters */
53
+ query?: {
54
+ collection?: string;
55
+ category?: string;
56
+ limit?: number;
57
+ sort?: 'newest' | 'oldest' | 'price-asc' | 'price-desc' | 'popular';
58
+ filter?: Record<string, any>;
59
+ };
60
+ /** Whether this node iterates over multiple items (e.g., ProductGrid) */
61
+ isCollection?: boolean;
62
+ /** Variable name for the current item in iteration context */
63
+ itemVariable?: string;
64
+ }
65
+ /** Complete binding configuration for a node */
66
+ export interface NodeBindings {
67
+ /** Data source configuration */
68
+ dataSource?: NodeDataSource;
69
+ /** Property bindings */
70
+ bindings?: DataBinding[];
71
+ /** Fallback props when no data is available */
72
+ fallbackProps?: Record<string, any>;
73
+ /** Binding mode */
74
+ mode: 'manual' | 'bound' | 'hybrid';
75
+ }
76
+ /** Base props shared by all nodes */
77
+ export interface BaseNodeProps {
78
+ /** Custom display name in layers panel */
79
+ customName?: string;
80
+ /** Scroll-triggered animation */
81
+ scrollAnimation?: AnimationPreset | 'none';
82
+ scrollAnimationDelay?: string;
83
+ scrollAnimationDuration?: string;
84
+ }
85
+ /** Text node props */
86
+ export interface TextNodeProps extends BaseNodeProps {
87
+ text?: string;
88
+ level?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span';
89
+ }
90
+ /** Image node props */
91
+ export interface ImageNodeProps extends BaseNodeProps {
92
+ src?: string;
93
+ alt?: string;
94
+ loading?: 'lazy' | 'eager';
95
+ }
96
+ /** Button node props */
97
+ export interface ButtonNodeProps extends BaseNodeProps {
98
+ text?: string;
99
+ href?: string;
100
+ variant?: 'default' | 'outline' | 'secondary' | 'ghost' | 'link';
101
+ size?: 'sm' | 'md' | 'lg';
102
+ }
103
+ /** ProductCard props (for template) */
104
+ export interface ProductCardNodeProps extends BaseNodeProps {
105
+ productId?: string;
106
+ title?: string;
107
+ price?: string;
108
+ originalPrice?: string;
109
+ image?: string;
110
+ badge?: string;
111
+ inStock?: boolean;
112
+ }
113
+ /** ProductGrid props */
114
+ export interface ProductGridNodeProps extends BaseNodeProps {
115
+ columns?: number;
116
+ limit?: number;
117
+ category?: string;
118
+ gap?: string;
119
+ collection?: string;
120
+ sort?: 'newest' | 'oldest' | 'price-asc' | 'price-desc' | 'popular';
121
+ }
122
+ /** CollectionGrid props */
123
+ export interface CollectionGridNodeProps extends BaseNodeProps {
124
+ columns?: number;
125
+ limit?: number;
126
+ gap?: string;
127
+ showTitle?: boolean;
128
+ showCount?: boolean;
129
+ }
130
+ /** HeroSection props */
131
+ export interface HeroSectionNodeProps extends BaseNodeProps {
132
+ heading?: string;
133
+ text?: string;
134
+ subtitle?: string;
135
+ ctaText?: string;
136
+ ctaHref?: string;
137
+ secondaryCtaText?: string;
138
+ secondaryCtaHref?: string;
139
+ src?: string;
140
+ overlayOpacity?: string;
141
+ overlayColor?: string;
142
+ textAlign?: 'left' | 'center' | 'right';
143
+ minHeight?: string;
144
+ }
145
+ /** ImageBanner props */
146
+ export interface ImageBannerNodeProps extends BaseNodeProps {
147
+ src?: string;
148
+ alt?: string;
149
+ href?: string;
150
+ overlayText?: string;
151
+ overlayPosition?: 'top' | 'center' | 'bottom';
152
+ }
153
+ /** RichTextSection props */
154
+ export interface RichTextSectionNodeProps extends BaseNodeProps {
155
+ content?: string;
156
+ columns?: 1 | 2;
157
+ }
158
+ /** CTASection props */
159
+ export interface CTASectionNodeProps extends BaseNodeProps {
160
+ heading?: string;
161
+ description?: string;
162
+ primaryCtaText?: string;
163
+ primaryCtaHref?: string;
164
+ secondaryCtaText?: string;
165
+ secondaryCtaHref?: string;
166
+ backgroundStyle?: 'solid' | 'gradient' | 'image';
167
+ backgroundImage?: string;
168
+ }
169
+ /** TestimonialSection props */
170
+ export interface TestimonialSectionNodeProps extends BaseNodeProps {
171
+ heading?: string;
172
+ testimonials?: Array<{
173
+ quote: string;
174
+ author: string;
175
+ role?: string;
176
+ avatar?: string;
177
+ rating?: number;
178
+ }>;
179
+ layout?: 'grid' | 'carousel' | 'stack';
180
+ }
181
+ /** FAQSection props */
182
+ export interface FAQSectionNodeProps extends BaseNodeProps {
183
+ heading?: string;
184
+ subtitle?: string;
185
+ items?: Array<{
186
+ question: string;
187
+ answer: string;
188
+ }>;
189
+ layout?: 'accordion' | 'grid';
190
+ }
191
+ /** Navbar props */
192
+ export interface NavbarNodeProps extends BaseNodeProps {
193
+ logoText?: string;
194
+ logoSrc?: string;
195
+ links?: Array<{
196
+ text: string;
197
+ href: string;
198
+ }>;
199
+ showSearch?: boolean;
200
+ showCart?: boolean;
201
+ showAccount?: boolean;
202
+ mobileMenuStyle?: 'sidebar' | 'dropdown';
203
+ announcementText?: string;
204
+ announcementHref?: string;
205
+ announcementDismissible?: boolean;
206
+ }
207
+ /** Footer props */
208
+ export interface FooterNodeProps extends BaseNodeProps {
209
+ logoText?: string;
210
+ logoSrc?: string;
211
+ copyright?: string;
212
+ links?: Array<{
213
+ text: string;
214
+ href: string;
215
+ }>;
216
+ columns?: Array<{
217
+ title: string;
218
+ links: Array<{
219
+ text: string;
220
+ href: string;
221
+ }>;
222
+ }>;
223
+ socialLinks?: Array<{
224
+ platform: string;
225
+ url: string;
226
+ }>;
227
+ showNewsletter?: boolean;
228
+ newsletterTitle?: string;
229
+ newsletterPlaceholder?: string;
230
+ }
231
+ /** Extended schema node with data binding support */
232
+ export interface BoundSchemaNode extends SchemaNode {
233
+ /** Data binding configuration */
234
+ bindings?: NodeBindings;
235
+ /** Metadata for builder/renderer */
236
+ metadata?: {
237
+ /** Node was created from a template */
238
+ fromTemplate?: string;
239
+ /** Template version */
240
+ templateVersion?: string;
241
+ /** Node is a master template that others reference */
242
+ isMasterTemplate?: boolean;
243
+ /** Last edited timestamp */
244
+ lastEdited?: string;
245
+ /** Created by (user or system) */
246
+ createdBy?: 'user' | 'system';
247
+ };
248
+ }
249
+ export type RenderMode = 'public' | 'preview' | 'edit';
250
+ /** Runtime context for the current page */
251
+ export interface PageContext {
252
+ /** Type of the current page */
253
+ pageType: PageType;
254
+ /** Current page slug */
255
+ slug: string;
256
+ /** URL parameters (e.g., product handle, collection handle) */
257
+ params?: Record<string, string>;
258
+ /** Query string parameters */
259
+ query?: Record<string, string>;
260
+ /** Render mode — replaces the old `isPreview` boolean */
261
+ mode: RenderMode;
262
+ /** The page metadata (SEO, OG, etc.) */
263
+ metadata?: PageMetadata;
264
+ }
265
+ /**
266
+ * RenderContext v1.7.0 — The single source of truth for all rendering data.
267
+ *
268
+ * Built by the Host/Template layer and consumed read-only by Builder and Renderer.
269
+ */
270
+ export interface RenderContext {
271
+ /** Current render mode */
272
+ mode: RenderMode;
273
+ /** Page-level context (optional — auto-built from mode if not provided) */
274
+ page?: PageContext;
275
+ /** All data available for binding resolution */
276
+ data?: {
277
+ /** E-commerce product data */
278
+ products: any[];
279
+ /** Product collections / categories */
280
+ collections: any[];
281
+ /** CMS / content pages */
282
+ pages: any[];
283
+ /** Global site settings (store name, currency, language, etc.) */
284
+ settings: Record<string, any>;
285
+ /** Card template schema for hydration (used by ProductGrid) */
286
+ cardTemplate?: {
287
+ nodes: Record<string, SchemaNode>;
288
+ rootNodeId: string;
289
+ themeTokens?: ThemeTokens;
290
+ };
291
+ /** Host-defined custom data sources */
292
+ custom: Record<string, any>;
293
+ };
294
+ /** Iteration context — set by collection renderers (e.g., ProductGrid) */
295
+ currentItem?: any;
296
+ /** Current item index in iteration */
297
+ currentIndex?: number;
298
+ /** Theme tokens snapshot */
299
+ theme?: ThemeTokens;
300
+ /** Resolve asset paths to full URLs */
301
+ resolveAssetUrl?: (path: string) => string;
302
+ }
303
+ /**
304
+ * Slot behavior determines what can be done with a slot's content:
305
+ * - locked: Render as-is. Inspector disabled. Cannot delete/move.
306
+ * - editable: Full inspector access. Can reorder children.
307
+ * - dynamic: Data-driven. Bindings resolved at render. Children generated from data.
308
+ */
309
+ export type SlotBehavior = 'locked' | 'editable' | 'dynamic';
310
+ /**
311
+ * Slot assignment for template integration.
312
+ *
313
+ * Fallback rules:
314
+ * - If slot has no children AND fallbackNodeId is set → render fallback node.
315
+ * - If slot has no children AND no fallback → render empty placeholder (edit mode only).
316
+ */
317
+ export interface SlotAssignment {
318
+ /** Slot identifier (e.g. 'header', 'footer', 'main', 'sidebar') */
319
+ __slot: string;
320
+ /** Slot behavior */
321
+ behavior: SlotBehavior;
322
+ /** Fallback node ID if slot is empty */
323
+ fallbackNodeId?: string;
324
+ }
325
+ export type PublishStage = 'draft' | 'validated' | 'preview' | 'published';
326
+ /** Options for the validation step */
327
+ export interface ValidatorOptions {
328
+ /** Treat warnings as errors */
329
+ strict?: boolean;
330
+ /** Page type for context-aware validation */
331
+ pageType?: PageType;
332
+ }
333
+ /**
334
+ * Publication pipeline contract.
335
+ *
336
+ * Rules:
337
+ * - `validate().errors.length > 0` blocks publish.
338
+ * - Warnings are displayed but do NOT block.
339
+ * - Preview is optional.
340
+ */
341
+ export interface PublishPipeline {
342
+ /** 1. Save work-in-progress */
343
+ saveDraft: (schema: Schema) => Promise<void>;
344
+ /** 2. Run validation — must pass with 0 errors to proceed */
345
+ validate: (schema: Schema, opts?: ValidatorOptions) => {
346
+ errors: string[];
347
+ warnings: string[];
348
+ };
349
+ /** 3. Generate preview (optional) — returns preview URL */
350
+ preview?: (schema: Schema) => Promise<string>;
351
+ /** 4. Publish to production */
352
+ publish: (payload: any) => Promise<void>;
353
+ }
354
+ export type TemplateType = 'page' | 'header' | 'footer' | 'component' | 'single';
355
+ export interface PageDefinition {
356
+ slug: string;
357
+ title: string;
358
+ schema: Schema;
359
+ status?: 'published' | 'draft';
360
+ templateType?: TemplateType;
361
+ category?: string;
362
+ icon?: React.ComponentType;
363
+ canvasSize?: {
364
+ width: number;
365
+ height: number;
366
+ };
367
+ /**
368
+ * Host-provided data for edit/preview binding resolution.
369
+ * @deprecated Use `hostData` instead. This alias is kept for backward compatibility.
370
+ */
371
+ mockData?: Record<string, any>;
372
+ /** Host-provided data for edit/preview binding resolution */
373
+ hostData?: Record<string, any>;
374
+ }
375
+ export interface InspectorFieldDef {
376
+ key: string;
377
+ label: string;
378
+ type: 'text' | 'select' | 'color' | 'number' | 'image' | 'toggle' | 'slider' | 'textarea' | 'link' | 'icon' | 'spacing' | 'group' | 'binding';
379
+ options?: {
380
+ label: string;
381
+ value: string;
382
+ }[];
383
+ min?: number;
384
+ max?: number;
385
+ step?: number;
386
+ placeholder?: string;
387
+ rows?: number;
388
+ accept?: string;
389
+ children?: InspectorFieldDef[];
390
+ defaultValue?: any;
391
+ /** For binding type: allowed data sources */
392
+ allowedDataSources?: DataSourceType[];
393
+ /** For binding type: available fields */
394
+ bindableFields?: string[];
395
+ }
396
+ export interface BlockDefinition {
397
+ type: NodeType;
398
+ label: string;
399
+ category: 'Layout' | 'Content' | 'UI' | 'Interactive' | 'Commerce' | 'Site' | 'Template' | string;
400
+ icon: React.ComponentType<{
401
+ className?: string;
402
+ }>;
403
+ canHaveChildren: boolean;
404
+ defaultProps: Record<string, any>;
405
+ defaultStyle: Partial<NodeStyle>;
406
+ allowedParents?: NodeType[];
407
+ allowedChildren?: NodeType[];
408
+ inspectorFields?: InspectorFieldDef[];
409
+ allowedTemplateTypes?: TemplateType[];
410
+ /** Factory for composite blocks */
411
+ compositeFactory?: () => {
412
+ rootId: string;
413
+ nodes: Record<string, SchemaNode>;
414
+ };
415
+ /** Whether this block supports data binding */
416
+ supportsBinding?: boolean;
417
+ /** Default binding configuration */
418
+ defaultBindings?: NodeBindings;
419
+ /** Documentation/help text */
420
+ description?: string;
421
+ }
422
+ /**
423
+ * This interface documents what the @mandolop97/constructor-nexora package exports.
424
+ * Host templates should import these items to integrate with the builder.
425
+ */
426
+ export interface NexoraExports {
427
+ NexoraBuilderApp: React.ComponentType<any>;
428
+ PageRenderer: React.ComponentType<any>;
429
+ CustomStylesInjector: React.ComponentType<any>;
430
+ createHomeSchema: () => Schema;
431
+ createProductsSchema: () => Schema;
432
+ createFAQSchema: () => Schema;
433
+ createContactSchema: () => Schema;
434
+ createHelpSchema: () => Schema;
435
+ createPrivacySchema: () => Schema;
436
+ createTermsSchema: () => Schema;
437
+ createWishlistSchema: () => Schema;
438
+ PAGE_DEFINITIONS: PageDefinition[];
439
+ getDefaultSchemaForSlug: (slug: string) => Schema | null;
440
+ blockRegistry: BlockDefinition[];
441
+ getBlockDef: (type: NodeType) => BlockDefinition | undefined;
442
+ registerBlock: (def: BlockDefinition) => void;
443
+ registerBlocks: (defs: BlockDefinition[]) => void;
444
+ getCategories: () => string[];
445
+ getBlocksByCategory: (category: string, templateType?: TemplateType) => BlockDefinition[];
446
+ createNode: (type: NodeType) => SchemaNode;
447
+ createNodeTree: (type: NodeType) => {
448
+ rootId: string;
449
+ nodes: Record<string, SchemaNode>;
450
+ };
451
+ duplicateNodeTree: (sourceId: string, nodes: Record<string, SchemaNode>) => {
452
+ newNodes: Record<string, SchemaNode>;
453
+ newRootId: string;
454
+ };
455
+ isContainerType: (type: NodeType) => boolean;
456
+ nodeStyleToCSS: (style: NodeStyle, nodeId: string) => string;
457
+ themeTokensToCSS: (tokens: ThemeTokens) => React.CSSProperties;
458
+ generatePseudoStateCSS: (style: NodeStyle, nodeId: string) => string;
459
+ generateResponsiveCSS: (style: NodeStyle, nodeId: string) => string;
460
+ validateSchema: (schema: any) => {
461
+ schema: Schema | null;
462
+ errors: string[];
463
+ };
464
+ resolveBindings: (node: BoundSchemaNode, context: RenderContext) => Record<string, any>;
465
+ hydrateTemplate: (template: Schema, data: any) => Schema;
466
+ EDITOR_VERSION: string;
467
+ }
468
+ /** Union of all node prop types */
469
+ export type AllNodeProps = TextNodeProps | ImageNodeProps | ButtonNodeProps | ProductCardNodeProps | ProductGridNodeProps | CollectionGridNodeProps | HeroSectionNodeProps | ImageBannerNodeProps | RichTextSectionNodeProps | CTASectionNodeProps | TestimonialSectionNodeProps | FAQSectionNodeProps | NavbarNodeProps | FooterNodeProps | BaseNodeProps;
470
+ /** Type guard for checking if a node supports binding */
471
+ export declare function supportsDataBinding(nodeType: NodeType): boolean;
472
+ /** Type guard for checking if a node is a commerce block */
473
+ export declare function isCommerceBlock(nodeType: NodeType): boolean;
474
+ /** Type guard for checking if a node is a template block */
475
+ export declare function isTemplateBlock(nodeType: NodeType): boolean;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * ════════════════════════════════════════════════════════════════════════════
3
+ * NEXORA — PAGE TYPES, METADATA, VISIBILITY & CONSTRAINTS
4
+ * ════════════════════════════════════════════════════════════════════════════
5
+ */
6
+ import { NodeType } from './schema';
7
+ /** Supported page types for the e-commerce builder */
8
+ export type PageType = 'home' | 'collection' | 'product' | 'cart' | 'checkout' | 'static' | 'landing' | 'blog' | 'blog-post' | 'account' | 'search' | 'custom';
9
+ /** Mapping of page types to human-readable labels */
10
+ export declare const PAGE_TYPE_LABELS: Record<PageType, string>;
11
+ export interface PageMetadata {
12
+ /** Page title for <title> tag and og:title */
13
+ title?: string;
14
+ /** Meta description for SEO and og:description */
15
+ description?: string;
16
+ /** Open Graph image URL */
17
+ ogImage?: string;
18
+ /** Canonical URL */
19
+ canonical?: string;
20
+ /** Additional meta tags */
21
+ meta?: Array<{
22
+ name: string;
23
+ content: string;
24
+ }>;
25
+ /** Whether search engines should index this page */
26
+ noIndex?: boolean;
27
+ /** JSON-LD structured data */
28
+ jsonLd?: Record<string, any>;
29
+ }
30
+ /**
31
+ * @deprecated Import PageContext from '@/types/contract' instead.
32
+ * This re-export is kept for backward compatibility.
33
+ */
34
+ export type { PageContext } from './contract';
35
+ export type DeviceVisibility = 'all' | 'desktop' | 'tablet' | 'mobile' | 'desktop+tablet' | 'tablet+mobile';
36
+ export interface VisibilityRule {
37
+ /** Show/hide on specific devices */
38
+ device?: DeviceVisibility;
39
+ /** Show only on specific page types */
40
+ pageTypes?: PageType[];
41
+ /** Show only when user is authenticated */
42
+ requireAuth?: boolean;
43
+ /** Custom condition expression (future) */
44
+ condition?: string;
45
+ /** Schedule visibility */
46
+ schedule?: {
47
+ startDate?: string;
48
+ endDate?: string;
49
+ };
50
+ }
51
+ /** Configuration for locking specific props on a node */
52
+ export interface LockedPropsConfig {
53
+ /** List of prop keys that are locked (cannot be edited) */
54
+ lockedProps?: string[];
55
+ /** List of style keys that are locked */
56
+ lockedStyles?: string[];
57
+ /** Whether the entire node is locked from deletion */
58
+ preventDelete?: boolean;
59
+ /** Whether the node can be moved/reordered */
60
+ preventMove?: boolean;
61
+ }
62
+ /** Default block-to-page-type compatibility map */
63
+ export declare const BLOCK_PAGE_TYPE_DEFAULTS: Partial<Record<NodeType, PageType[]>>;
64
+ /** Check if a block type is compatible with a page type */
65
+ export declare function isBlockCompatibleWithPage(blockType: NodeType, pageType: PageType, allowedPageTypes?: PageType[]): boolean;
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
- export type BuiltInNodeType = 'Section' | 'Container' | 'Grid' | 'Stack' | 'Text' | 'Image' | 'Divider' | 'Badge' | 'Button' | 'Card' | 'Input' | 'ProductCard' | 'Navbar' | 'Footer' | 'AnnouncementBar' | 'FeatureBar' | 'TestimonialCard' | 'NewsletterSection' | 'HeroSection' | 'Accordion' | 'TabsBlock' | 'VideoEmbed' | 'Spacer' | 'Icon' | 'SocialIcons' | 'FormBlock';
2
+ import type { SlotAssignment } from './contract';
3
+ export type BuiltInNodeType = 'Section' | 'Container' | 'Grid' | 'Stack' | 'Text' | 'Image' | 'Divider' | 'Badge' | 'Button' | 'Card' | 'Input' | 'ProductCard' | 'ProductGrid' | 'CollectionGrid' | 'Navbar' | 'Footer' | 'AnnouncementBar' | 'FeatureBar' | 'TestimonialCard' | 'NewsletterSection' | 'HeroSection' | 'ImageBanner' | 'RichTextSection' | 'CTASection' | 'TestimonialSection' | 'FAQSection' | 'Accordion' | 'TabsBlock' | 'VideoEmbed' | 'Spacer' | 'Icon' | 'SocialIcons' | 'FormBlock';
3
4
  /** Extensible node type — accepts all built-in types plus any custom string. */
4
5
  export type NodeType = BuiltInNodeType | (string & {});
5
6
  export interface NodeStyle {
@@ -160,6 +161,10 @@ export interface NodeProps {
160
161
  videoUrl?: string;
161
162
  autoplay?: boolean;
162
163
  muted?: boolean;
164
+ /** Scroll animation */
165
+ scrollAnimation?: 'fadeIn' | 'slideUp' | 'slideLeft' | 'slideRight' | 'scaleIn' | 'none';
166
+ scrollAnimationDelay?: string;
167
+ scrollAnimationDuration?: string;
163
168
  /** Allow arbitrary extra props from custom blocks */
164
169
  [key: string]: any;
165
170
  }
@@ -174,6 +179,10 @@ export interface SchemaNode {
174
179
  customName?: string;
175
180
  /** Raw CSS applied to this specific widget */
176
181
  customCSS?: string;
182
+ /** IDs of global styles applied to this node */
183
+ appliedGlobalStyles?: string[];
184
+ /** Slot assignment for template integration */
185
+ slot?: SlotAssignment;
177
186
  }
178
187
  export interface ThemeTokens {
179
188
  colors: {
@@ -203,6 +212,12 @@ export interface ThemeTokens {
203
212
  xl: string;
204
213
  };
205
214
  gradient?: string;
215
+ /** Default ProductCard layout used across the site */
216
+ defaultCardLayout?: 'vertical' | 'horizontal' | 'minimal' | 'overlay';
217
+ }
218
+ export interface GlobalStyleDef {
219
+ label: string;
220
+ style: Partial<NodeStyle>;
206
221
  }
207
222
  export interface Schema {
208
223
  id: string;
@@ -211,6 +226,8 @@ export interface Schema {
211
226
  themeTokens: ThemeTokens;
212
227
  rootNodeId: string;
213
228
  nodes: Record<string, SchemaNode>;
229
+ /** Reusable global style classes */
230
+ globalStyles?: Record<string, GlobalStyleDef>;
214
231
  }
215
232
  export interface Page {
216
233
  id: string;
@@ -230,7 +247,10 @@ export interface PageDefinition {
230
247
  width: number;
231
248
  height: number;
232
249
  };
250
+ /** @deprecated Use hostData */
233
251
  mockData?: Record<string, any>;
252
+ /** Host-provided data for edit/preview binding resolution */
253
+ hostData?: Record<string, any>;
234
254
  }
235
255
  export type RenderMode = 'public' | 'preview' | 'edit';
236
256
  export type TemplateType = 'page' | 'header' | 'footer' | 'component' | 'single';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mandolop97/constructor-nexora",
3
3
  "private": false,
4
- "version": "1.3.1",
4
+ "version": "1.7.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",