@mandolop97/constructor-nexora 1.5.0 → 1.7.1

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/NEXORA.md ADDED
@@ -0,0 +1,934 @@
1
+ # Nexora Visual Builder — Full Technical Documentation
2
+
3
+ > **Package:** `@mandolop97/constructor-nexora`
4
+ > **Contract Version:** 1.7.0
5
+ > **This file ships with the NPM package.** Any developer or AI assistant working in a project where this package is installed can read this documentation from `node_modules/@mandolop97/constructor-nexora/NEXORA.md`.
6
+
7
+ ---
8
+
9
+ ## Table of Contents
10
+
11
+ 1. [Architecture Overview](#1-architecture-overview)
12
+ 2. [Core Types](#2-core-types)
13
+ 3. [NexoraBuilderApp — Main Component API](#3-nexorabuilderapp--main-component-api)
14
+ 4. [PageRenderer — Schema Rendering](#4-pagerenderer--schema-rendering)
15
+ 5. [Block System & Registry](#5-block-system--registry)
16
+ 6. [Node Factory](#6-node-factory)
17
+ 7. [Style System](#7-style-system)
18
+ 8. [Theme Tokens](#8-theme-tokens)
19
+ 9. [Data Binding & RenderContext](#9-data-binding--rendercontext)
20
+ 10. [Slot System](#10-slot-system)
21
+ 11. [Multi-Page System](#11-multi-page-system)
22
+ 12. [Publish Pipeline](#12-publish-pipeline)
23
+ 13. [Internationalization (i18n)](#13-internationalization-i18n)
24
+ 14. [Extensibility](#14-extensibility)
25
+ 15. [All Package Exports](#15-all-package-exports)
26
+ 16. [Integration Examples](#16-integration-examples)
27
+
28
+ ---
29
+
30
+ ## 1. Architecture Overview
31
+
32
+ The builder follows a **schema-first** model: the entire UI is described as a flat JSON tree (`Schema`) that is rendered recursively by `PageRenderer`.
33
+
34
+ ### Render Modes (`RenderMode`)
35
+
36
+ | Mode | Use Case | Characteristics |
37
+ |-----------|----------------------|--------------------------------------------------|
38
+ | `edit` | Visual builder | Selection outlines, drop zones, drag & drop |
39
+ | `preview` | Clean preview | No editing controls |
40
+ | `public` | Published site | Production mode, no builder dependencies |
41
+
42
+ ### Data Flow
43
+
44
+ ```
45
+ Host App
46
+ └─ <NexoraBuilderApp initialSchema={...} onSave={...} />
47
+ └─ BuilderEditorShell (internal schema state + undo/redo)
48
+ ├─ TopBar (actions: save, publish, preview, export)
49
+ ├─ BlocksPalette (left sidebar: draggable blocks)
50
+ ├─ BuilderCanvas (central canvas with PageRenderer in edit mode)
51
+ └─ Inspector (right sidebar: props, styles, theme)
52
+ ```
53
+
54
+ ### Data Ownership Policy
55
+
56
+ | Layer | Responsibility | Prohibitions |
57
+ |------------------|-------------------------------|-------------------------------------|
58
+ | Host/Template | Fetch + adapt data. Build RenderContext. Provide hostData. | Cannot modify schema nodes directly |
59
+ | Builder (editor) | Schema CRUD. Adapt hostData for preview. Validate before publish. | NO fetch to external APIs. NO direct DB calls for business data. |
60
+ | Renderer | Render nodes from schema + resolved context. Pure. | NO fetch. NO state mutation. Read-only. |
61
+
62
+ ---
63
+
64
+ ## 2. Core Types
65
+
66
+ ### `Schema`
67
+
68
+ ```typescript
69
+ interface Schema {
70
+ id: string;
71
+ version: number;
72
+ updatedAt: string;
73
+ themeTokens: ThemeTokens;
74
+ rootNodeId: string;
75
+ nodes: Record<string, SchemaNode>;
76
+ globalStyles?: Record<string, GlobalStyleDef>;
77
+ }
78
+ ```
79
+
80
+ Flat map of nodes. `rootNodeId` points to the root node. Children are referenced by ID in `children: string[]`.
81
+
82
+ ### `SchemaNode`
83
+
84
+ ```typescript
85
+ interface SchemaNode {
86
+ id: string;
87
+ type: NodeType;
88
+ props: NodeProps;
89
+ style: NodeStyle;
90
+ children: string[];
91
+ locked?: boolean;
92
+ hidden?: boolean;
93
+ customName?: string;
94
+ customCSS?: string;
95
+ appliedGlobalStyles?: string[];
96
+ slot?: SlotAssignment;
97
+ }
98
+ ```
99
+
100
+ ### `NodeType`
101
+
102
+ Built-in types:
103
+
104
+ - **Layout:** `Section`, `Container`, `Grid`, `Stack`
105
+ - **Content:** `Text`, `Image`, `Divider`, `Badge`, `Spacer`, `Icon`, `SocialIcons`
106
+ - **UI:** `Button`, `Card`, `Input`
107
+ - **Interactive:** `Accordion`, `TabsBlock`, `VideoEmbed`, `FormBlock`
108
+ - **Commerce:** `ProductCard`, `ProductGrid`, `CollectionGrid`
109
+ - **Site (global):** `Navbar`, `Footer`, `AnnouncementBar`
110
+ - **Template blocks:** `HeroSection`, `FeatureBar`, `TestimonialCard`, `NewsletterSection`, `ImageBanner`, `RichTextSection`, `CTASection`, `TestimonialSection`, `FAQSection`
111
+
112
+ Extensible with `string & {}` for custom host types.
113
+
114
+ ### `NodeStyle`
115
+
116
+ Object with ~80+ CSS properties organized in categories:
117
+
118
+ - **Layout & Box Model:** `padding`, `margin`, `gap`, `width`, `height`, `minHeight`, `maxWidth`, `display`, `flexDirection`, `alignItems`, `justifyContent`, `gridTemplateColumns`, `position`, `zIndex`, etc.
119
+ - **Typography:** `color`, `fontSize`, `fontWeight`, `fontFamily`, `lineHeight`, `letterSpacing`, `textAlign`, `textTransform`, `textDecoration`, etc.
120
+ - **Background:** `backgroundColor`, `backgroundImage`, `backgroundSize`, `backgroundPosition`, `backgroundGradient`, etc.
121
+ - **Border:** `borderColor`, `borderWidth`, `borderRadius`, `borderStyle`, etc.
122
+ - **Shadow & Effects:** `boxShadow`, `opacity`, `filter`, `backdropFilter`, `clipPath`, etc.
123
+ - **Transforms:** `transform`, `transformOrigin`, `perspective`
124
+ - **Transitions:** `transition`, `transitionProperty`, `transitionDuration`, etc.
125
+ - **Animations:** `animation`, `animationName`, `animationDuration`, etc.
126
+ - **Pseudo-state overrides:** `hover`, `focus`, `active` — partial style overrides per pseudo-state
127
+ - **Responsive overrides:** `responsive.{sm|md|lg|xl}` — partial style overrides per breakpoint (generates `@container` queries)
128
+
129
+ ### `NodeProps`
130
+
131
+ Semantic properties for each node type: `text`, `href`, `src`, `alt`, `label`, `price`, `links[]`, `items[]`, `panels[]`, `videoUrl`, `heading`, `subtitle`, `ctaText`, `ctaHref`, `scrollAnimation`, etc. Accepts `[key: string]: any` for custom props.
132
+
133
+ ### `ThemeTokens`
134
+
135
+ ```typescript
136
+ interface ThemeTokens {
137
+ colors: {
138
+ primary: string;
139
+ secondary: string;
140
+ background: string;
141
+ text: string;
142
+ muted: string;
143
+ border: string;
144
+ accent?: string;
145
+ };
146
+ typography: {
147
+ fontFamily: string;
148
+ baseSize: string;
149
+ headingScale: number;
150
+ };
151
+ radius: { sm: string; md: string; lg: string };
152
+ spacing: { xs: string; sm: string; md: string; lg: string; xl: string };
153
+ gradient?: string;
154
+ defaultCardLayout?: 'vertical' | 'horizontal' | 'minimal' | 'overlay';
155
+ }
156
+ ```
157
+
158
+ ### `AnimationPreset`
159
+
160
+ Available presets: `fadeIn`, `fadeOut`, `slideUp`, `slideDown`, `slideLeft`, `slideRight`, `scaleIn`, `scaleOut`, `bounceIn`, `pulse`, `shake`, `none`.
161
+
162
+ ---
163
+
164
+ ## 3. NexoraBuilderApp — Main Component API
165
+
166
+ The main entry point for the visual editor.
167
+
168
+ ```typescript
169
+ interface NexoraBuilderAppProps {
170
+ /** Initial schema to load in the editor */
171
+ initialSchema?: Schema;
172
+ /** Domain for publishing */
173
+ domain?: string;
174
+ /** Current page slug */
175
+ pageSlug?: string;
176
+
177
+ // ── Callbacks ──
178
+ onSave?: (schema: Schema) => void;
179
+ onPublish?: (schema: Schema) => void;
180
+ onPreview?: (schema: Schema) => void;
181
+ onExport?: (schema: Schema) => void;
182
+ onSaveWithSlug?: (slug: string, schema: Schema) => void;
183
+ onPublishSubmit?: (payload: PublishPayload) => Promise<void>;
184
+
185
+ // ── Multi-page ──
186
+ pages?: PageDefinition[];
187
+ activePage?: string;
188
+ onPageChange?: (slug: string) => void;
189
+
190
+ // ── Localization ──
191
+ locale?: 'es' | 'en' | BuilderLocale;
192
+
193
+ // ── Extensibility ──
194
+ customComponents?: CustomComponentMap;
195
+ extraBlocks?: BlockDefinition[];
196
+
197
+ // ── Custom injection ──
198
+ customStylesheets?: string[]; // External CSS URLs
199
+ customCSS?: string; // Raw CSS string
200
+ customScripts?: string[]; // External script URLs
201
+
202
+ // ── Asset handling ──
203
+ onImageUpload?: (file: File) => Promise<string>;
204
+ resolveAssetUrl?: (path: string) => string;
205
+
206
+ // ── Data ──
207
+ hostData?: Record<string, any>;
208
+ renderContext?: RenderContext;
209
+
210
+ className?: string;
211
+ }
212
+ ```
213
+
214
+ ### Usage
215
+
216
+ ```tsx
217
+ import { NexoraBuilderApp } from '@mandolop97/constructor-nexora';
218
+ import '@mandolop97/constructor-nexora/styles.css';
219
+
220
+ function App() {
221
+ return (
222
+ <NexoraBuilderApp
223
+ initialSchema={mySchema}
224
+ onSave={(schema) => saveToDatabase(schema)}
225
+ onPublish={(schema) => publishSite(schema)}
226
+ locale="en"
227
+ />
228
+ );
229
+ }
230
+ ```
231
+
232
+ ---
233
+
234
+ ## 4. PageRenderer — Schema Rendering
235
+
236
+ Recursive renderer that traverses the node tree from `rootNodeId`. Used both inside the builder and for standalone rendering (e.g., published sites).
237
+
238
+ ```tsx
239
+ import { PageRenderer } from '@mandolop97/constructor-nexora';
240
+
241
+ // Render a schema outside the builder
242
+ <PageRenderer
243
+ schema={mySchema}
244
+ mode="public"
245
+ renderContext={myRenderContext}
246
+ />
247
+ ```
248
+
249
+ ### NodeComponentProps
250
+
251
+ Every node component receives:
252
+
253
+ ```typescript
254
+ interface NodeComponentProps {
255
+ node: SchemaNode;
256
+ mode: RenderMode;
257
+ renderChildren: (childIds: string[]) => React.ReactNode;
258
+ mockData?: Record<string, any>;
259
+ }
260
+ ```
261
+
262
+ ---
263
+
264
+ ## 5. Block System & Registry
265
+
266
+ ### `BlockDefinition`
267
+
268
+ ```typescript
269
+ interface BlockDefinition {
270
+ type: NodeType;
271
+ label: string;
272
+ icon?: React.ComponentType;
273
+ category: string;
274
+ canHaveChildren: boolean;
275
+ defaultProps?: Partial<NodeProps>;
276
+ defaultStyle?: Partial<NodeStyle>;
277
+ inspectorFields: InspectorFieldDef[];
278
+ compositeFactory?: () => CompositeNodeTree;
279
+ templateType?: TemplateType;
280
+ }
281
+ ```
282
+
283
+ ### `InspectorFieldDef`
284
+
285
+ ```typescript
286
+ interface InspectorFieldDef {
287
+ key: string;
288
+ label: string;
289
+ type: 'text' | 'select' | 'color' | 'number' | 'image' | 'toggle'
290
+ | 'slider' | 'textarea' | 'link' | 'icon' | 'spacing'
291
+ | 'group' | 'binding' | 'array';
292
+ options?: { label: string; value: string }[];
293
+ min?: number;
294
+ max?: number;
295
+ step?: number;
296
+ placeholder?: string;
297
+ rows?: number;
298
+ children?: InspectorFieldDef[]; // For 'group' type
299
+ arrayFields?: ArrayFieldDef[]; // For 'array' type
300
+ newItemDefaults?: Record<string, any>;
301
+ addLabel?: string;
302
+ maxItems?: number;
303
+ allowedDataSources?: string[]; // For 'binding' type
304
+ bindableFields?: string[];
305
+ }
306
+ ```
307
+
308
+ ### Composite Blocks
309
+
310
+ `compositeFactory` returns `{ rootId, nodes }` — a pre-built mini node tree (e.g., HeroSection with Container + Text + Button).
311
+
312
+ ### Registry API
313
+
314
+ ```typescript
315
+ import { blockRegistry, registerBlock, registerBlocks, getBlockDef,
316
+ getCategories, getBlocksByCategory, getCategoriesForTemplate } from '@mandolop97/constructor-nexora';
317
+
318
+ // Register custom blocks
319
+ registerBlock(myBlockDef);
320
+ registerBlocks([block1, block2]);
321
+
322
+ // Query blocks
323
+ getBlockDef('Button'); // → BlockDefinition | undefined
324
+ getCategories(); // → string[]
325
+ getBlocksByCategory('Layout'); // → BlockDefinition[]
326
+ getCategoriesForTemplate('page'); // → string[]
327
+ ```
328
+
329
+ ---
330
+
331
+ ## 6. Node Factory
332
+
333
+ ```typescript
334
+ import { createNode, createNodeTree, isContainerType, duplicateNodeTree } from '@mandolop97/constructor-nexora';
335
+
336
+ createNode('Button'); // Single node with defaults from registry
337
+ createNodeTree('HeroSection'); // Full composite tree if compositeFactory exists
338
+ isContainerType('Section'); // true — can have children
339
+ duplicateNodeTree(nodeId, nodes); // Deep clone with new IDs
340
+ ```
341
+
342
+ ---
343
+
344
+ ## 7. Style System
345
+
346
+ ```typescript
347
+ import { nodeStyleToCSS, generatePseudoStateCSS, generateResponsiveCSS, themeTokensToCSS } from '@mandolop97/constructor-nexora';
348
+
349
+ // Convert NodeStyle to React.CSSProperties
350
+ const css = nodeStyleToCSS(node.style);
351
+
352
+ // Generate :hover/:focus/:active CSS rules
353
+ const pseudoCSS = generatePseudoStateCSS(node.id, node.style);
354
+
355
+ // Generate @container responsive queries
356
+ const responsiveCSS = generateResponsiveCSS(node.id, node.style);
357
+
358
+ // Convert ThemeTokens to CSS custom properties
359
+ const themeCSSVars = themeTokensToCSS(schema.themeTokens);
360
+ ```
361
+
362
+ ### CSS Scoping
363
+
364
+ The editor lives inside `.nxr-editor` which defines fallback CSS variables for Tailwind/Shadcn tokens, avoiding conflicts with the host application.
365
+
366
+ ---
367
+
368
+ ## 8. Theme Tokens
369
+
370
+ ThemeTokens are injected as CSS custom properties in the canvas:
371
+
372
+ ```css
373
+ --primary: [value]
374
+ --secondary: [value]
375
+ --background: [value]
376
+ --foreground: [value] /* = colors.text */
377
+ --muted: [value]
378
+ --border: [value]
379
+ --accent: [value]
380
+ --radius: [value] /* = radius.md */
381
+ --font-family: [value]
382
+ --font-size-base: [value]
383
+ ```
384
+
385
+ The `ThemeEditor` component updates these tokens in the schema, re-injected in real time.
386
+
387
+ ---
388
+
389
+ ## 9. Data Binding & RenderContext
390
+
391
+ ### RenderContext v1.7.0
392
+
393
+ The single source of truth for all rendering data, built by the Host/Template layer:
394
+
395
+ ```typescript
396
+ interface RenderContext {
397
+ mode: RenderMode;
398
+ page?: PageContext;
399
+ data?: {
400
+ products: any[];
401
+ collections: any[];
402
+ pages: any[];
403
+ settings: Record<string, any>;
404
+ cardTemplate?: {
405
+ nodes: Record<string, SchemaNode>;
406
+ rootNodeId: string;
407
+ themeTokens?: ThemeTokens;
408
+ };
409
+ custom: Record<string, any>;
410
+ };
411
+ currentItem?: any;
412
+ currentIndex?: number;
413
+ theme?: ThemeTokens;
414
+ resolveAssetUrl?: (path: string) => string;
415
+ }
416
+ ```
417
+
418
+ ### PageContext
419
+
420
+ ```typescript
421
+ interface PageContext {
422
+ pageType: PageType;
423
+ slug: string;
424
+ mode: RenderMode;
425
+ params?: Record<string, string>;
426
+ query?: Record<string, string>;
427
+ metadata?: PageMetadata;
428
+ }
429
+ ```
430
+
431
+ ### Building RenderContext
432
+
433
+ ```typescript
434
+ import { buildRenderContext, buildEditContext, createIterationContext,
435
+ validateRenderContext, isStrictRenderContext } from '@mandolop97/constructor-nexora';
436
+
437
+ // For public/preview mode
438
+ const ctx = buildRenderContext({
439
+ mode: 'public',
440
+ page: { pageType: 'home', slug: '/' },
441
+ products: myProducts,
442
+ collections: myCollections,
443
+ settings: mySettings,
444
+ });
445
+
446
+ // For edit mode (uses sample data automatically)
447
+ const editCtx = buildEditContext(hostData, themeTokens);
448
+
449
+ // For collection iteration (e.g., inside ProductGrid)
450
+ const itemCtx = createIterationContext(parentCtx, product, index);
451
+ ```
452
+
453
+ ### Data Binding Types
454
+
455
+ ```typescript
456
+ interface DataBinding {
457
+ propKey: string; // Node prop (e.g., 'text', 'src', 'price')
458
+ fieldPath: string; // Data path (e.g., 'product.title')
459
+ transform?: string; // Optional transform (e.g., 'formatPrice')
460
+ }
461
+
462
+ interface NodeBindings {
463
+ dataSource?: NodeDataSource;
464
+ bindings?: DataBinding[];
465
+ fallbackProps?: Record<string, any>;
466
+ mode: 'manual' | 'bound' | 'hybrid';
467
+ }
468
+ ```
469
+
470
+ ### Binding Utilities
471
+
472
+ ```typescript
473
+ import { resolveBindings, hydrateTemplate, hydrateNodeForItem,
474
+ resolveFieldPath, setFieldPath,
475
+ createDefaultBindings, hasActiveBindings, getBoundProps,
476
+ registerTransform, getAvailableTransforms } from '@mandolop97/constructor-nexora';
477
+ ```
478
+
479
+ ### Host Data / Sample Data
480
+
481
+ ```typescript
482
+ import { DEFAULT_SAMPLE_PRODUCTS, DEFAULT_SAMPLE_COLLECTIONS,
483
+ DEFAULT_SAMPLE_SETTINGS, buildHostData } from '@mandolop97/constructor-nexora';
484
+ ```
485
+
486
+ ---
487
+
488
+ ## 10. Slot System
489
+
490
+ Slots enable template integration with controlled editability:
491
+
492
+ ```typescript
493
+ type SlotBehavior = 'locked' | 'editable' | 'dynamic';
494
+
495
+ interface SlotAssignment {
496
+ __slot: string; // Slot ID (e.g., 'header', 'footer', 'main')
497
+ behavior: SlotBehavior; // What can be done with the slot content
498
+ fallbackNodeId?: string;
499
+ }
500
+ ```
501
+
502
+ | Behavior | Description |
503
+ |------------|----------------------------------------------------------------|
504
+ | `locked` | Render as-is. Inspector disabled. Cannot delete/move. |
505
+ | `editable` | Full inspector access. Can reorder children. |
506
+ | `dynamic` | Data-driven. Bindings resolved at render. Children from data. |
507
+
508
+ ### Slot Utilities
509
+
510
+ ```typescript
511
+ import { getSlotAssignment, isInSlot, getSlotBehavior, isSlotLocked,
512
+ isSlotEditable, isSlotDynamic, getNodesInSlot, getSlotFallback,
513
+ getSlotConstraints, validateSlots } from '@mandolop97/constructor-nexora';
514
+ ```
515
+
516
+ ---
517
+
518
+ ## 11. Multi-Page System
519
+
520
+ ```tsx
521
+ <NexoraBuilderApp
522
+ pages={[
523
+ { slug: 'home', title: 'Home', schema: homeSchema, templateType: 'page' },
524
+ { slug: 'header', title: 'Header', schema: headerSchema,
525
+ templateType: 'header', canvasSize: { width: 1200, height: 80 } },
526
+ ]}
527
+ activePage="home"
528
+ onPageChange={(slug) => setActivePage(slug)}
529
+ onSaveWithSlug={(slug, schema) => saveToDb(slug, schema)}
530
+ />
531
+ ```
532
+
533
+ ### Template Types
534
+
535
+ | Type | Description |
536
+ |-------------|--------------------------------|
537
+ | `page` | Full page |
538
+ | `header` | Site header fragment |
539
+ | `footer` | Site footer fragment |
540
+ | `component` | Reusable component |
541
+ | `single` | Single piece (e.g., banner) |
542
+
543
+ ### Page Types
544
+
545
+ Available page types: `home`, `products`, `product-detail`, `collection`, `cart`, `checkout`, `faq`, `contact`, `help`, `privacy`, `terms`, `wishlist`, `custom`.
546
+
547
+ ### Default Schemas
548
+
549
+ ```typescript
550
+ import { PAGE_DEFINITIONS, getDefaultSchemaForSlug,
551
+ createHomeSchema, createProductsSchema, createFAQSchema,
552
+ createContactSchema, createHelpSchema, createPrivacySchema,
553
+ createTermsSchema, createWishlistSchema } from '@mandolop97/constructor-nexora';
554
+ ```
555
+
556
+ ---
557
+
558
+ ## 12. Publish Pipeline
559
+
560
+ ```typescript
561
+ interface PublishPipeline {
562
+ saveDraft: (schema: Schema) => Promise<void>;
563
+ validate: (schema: Schema, opts?: ValidatorOptions) => { errors: string[]; warnings: string[] };
564
+ preview?: (schema: Schema) => Promise<string>;
565
+ publish: (payload: any) => Promise<void>;
566
+ }
567
+ ```
568
+
569
+ Rules:
570
+ - `validate().errors.length > 0` **blocks** publish.
571
+ - Warnings are displayed but do NOT block.
572
+
573
+ ### Pre-Publish Validation
574
+
575
+ ```typescript
576
+ import { validateForPublish } from '@mandolop97/constructor-nexora';
577
+
578
+ const result = validateForPublish(schema);
579
+ // result: { valid: boolean; errors: ValidationIssue[]; warnings: ValidationIssue[] }
580
+ ```
581
+
582
+ ### Schema Validation
583
+
584
+ ```typescript
585
+ import { validateSchema } from '@mandolop97/constructor-nexora';
586
+
587
+ const result = validateSchema(schema);
588
+ // result: { valid: boolean; errors: string[] }
589
+ ```
590
+
591
+ ---
592
+
593
+ ## 13. Internationalization (i18n)
594
+
595
+ ```tsx
596
+ // Use a predefined locale
597
+ <NexoraBuilderApp locale="es" />
598
+ <NexoraBuilderApp locale="en" />
599
+
600
+ // Use a custom locale object
601
+ <NexoraBuilderApp locale={{
602
+ save: 'Guardar',
603
+ publish: 'Publicar',
604
+ // ... all keys
605
+ }} />
606
+ ```
607
+
608
+ Programmatic API:
609
+
610
+ ```typescript
611
+ import { setLocaleByCode, setLocale, t, es, en, translateCategory } from '@mandolop97/constructor-nexora';
612
+
613
+ setLocaleByCode('en');
614
+ setLocale(myCustomLocale);
615
+ t('save'); // → 'Save'
616
+ translateCategory('Layout'); // → translated category name
617
+ ```
618
+
619
+ ---
620
+
621
+ ## 14. Extensibility
622
+
623
+ ### Custom Components
624
+
625
+ ```tsx
626
+ import { NexoraBuilderApp } from '@mandolop97/constructor-nexora';
627
+ import type { NodeComponent } from '@mandolop97/constructor-nexora';
628
+
629
+ const MyWidget: NodeComponent = ({ node, mode, renderChildren }) => (
630
+ <div>{node.props.text}</div>
631
+ );
632
+
633
+ <NexoraBuilderApp
634
+ customComponents={{ MyWidget }}
635
+ extraBlocks={[{
636
+ type: 'MyWidget',
637
+ label: 'My Widget',
638
+ category: 'Custom',
639
+ canHaveChildren: false,
640
+ defaultProps: { text: 'Hello' },
641
+ inspectorFields: [{ key: 'text', label: 'Text', type: 'text' }],
642
+ }]}
643
+ />
644
+ ```
645
+
646
+ ### Custom Styles & Scripts
647
+
648
+ ```tsx
649
+ <NexoraBuilderApp
650
+ customStylesheets={['https://cdn.example.com/theme.css']}
651
+ customCSS=".my-class { color: red; }"
652
+ customScripts={['https://cdn.tailwindcss.com']}
653
+ />
654
+ ```
655
+
656
+ ### Persistence
657
+
658
+ The builder is **stateless regarding storage**. The host controls persistence:
659
+
660
+ ```tsx
661
+ <NexoraBuilderApp
662
+ onSave={(schema) => saveToDatabase(schema)}
663
+ onSaveWithSlug={(slug, schema) => savePageToDb(slug, schema)}
664
+ onPublish={(schema) => publishSite(schema)}
665
+ onPublishSubmit={async (payload) => {
666
+ // payload: { domain, pages, status }
667
+ await publishToProduction(payload);
668
+ }}
669
+ />
670
+ ```
671
+
672
+ ---
673
+
674
+ ## 15. All Package Exports
675
+
676
+ ### Components
677
+
678
+ | Export | Description |
679
+ |-------------------------|--------------------------------------------------|
680
+ | `NexoraBuilderApp` | Main visual editor component |
681
+ | `PageRenderer` | Standalone schema renderer |
682
+ | `CustomStylesInjector` | Inject custom CSS in public render |
683
+ | `MediaGallery` | Media gallery component |
684
+ | `ProductPicker` | Product picker component |
685
+ | `PageManager` | Page list/selector component |
686
+
687
+ ### Block Registry
688
+
689
+ | Export | Description |
690
+ |-------------------------------|----------------------------------------|
691
+ | `blockRegistry` | The block registry instance |
692
+ | `registerBlock(def)` | Register a single block |
693
+ | `registerBlocks(defs[])` | Register multiple blocks |
694
+ | `getBlockDef(type)` | Get block definition by type |
695
+ | `getCategories()` | List all block categories |
696
+ | `getBlocksByCategory(cat)` | List blocks in a category |
697
+ | `getCategoriesForTemplate(t)` | Filter categories by template type |
698
+
699
+ ### Node Utilities
700
+
701
+ | Export | Description |
702
+ |---------------------------|----------------------------------------|
703
+ | `createNode(type)` | Create node with registry defaults |
704
+ | `createNodeTree(type)` | Create composite node tree |
705
+ | `isContainerType(type)` | Check if type accepts children |
706
+ | `duplicateNodeTree(id,n)` | Deep clone with new IDs |
707
+
708
+ ### Style Utilities
709
+
710
+ | Export | Description |
711
+ |----------------------------|---------------------------------------|
712
+ | `nodeStyleToCSS(style)` | Convert NodeStyle to CSSProperties |
713
+ | `generatePseudoStateCSS()` | Generate :hover/:focus/:active CSS |
714
+ | `generateResponsiveCSS()` | Generate @container queries |
715
+ | `themeTokensToCSS(tokens)` | Convert ThemeTokens to CSS vars |
716
+
717
+ ### Schema & Validation
718
+
719
+ | Export | Description |
720
+ |----------------------------|---------------------------------------|
721
+ | `createDefaultHomeSchema()`| Default home page schema |
722
+ | `validateSchema(schema)` | Validate schema structure |
723
+ | `validateForPublish(schema)`| Pre-publish validation |
724
+
725
+ ### Data Binding
726
+
727
+ | Export | Description |
728
+ |----------------------------|---------------------------------------|
729
+ | `resolveBindings()` | Resolve data bindings on a node |
730
+ | `hydrateTemplate()` | Hydrate template with data |
731
+ | `hydrateNodeForItem()` | Hydrate node for a single data item |
732
+ | `resolveFieldPath()` | Resolve a dot-path on an object |
733
+ | `setFieldPath()` | Set a value at a dot-path |
734
+ | `createDefaultBindings()` | Create default bindings for a node |
735
+ | `hasActiveBindings()` | Check if a node has active bindings |
736
+ | `getBoundProps()` | Get resolved bound props |
737
+ | `registerTransform()` | Register a custom data transform |
738
+ | `getAvailableTransforms()` | List available transforms |
739
+
740
+ ### RenderContext Utilities
741
+
742
+ | Export | Description |
743
+ |-----------------------------|---------------------------------------|
744
+ | `buildRenderContext(opts)` | Build complete RenderContext |
745
+ | `buildEditContext(data,t)` | Build edit-mode context |
746
+ | `createIterationContext()` | Create iteration context for loops |
747
+ | `validateRenderContext()` | Validate a RenderContext |
748
+ | `isStrictRenderContext()` | Check if context is production-ready |
749
+
750
+ ### Slot Utilities
751
+
752
+ | Export | Description |
753
+ |-----------------------------|---------------------------------------|
754
+ | `getSlotAssignment(node)` | Get slot assignment from a node |
755
+ | `isInSlot(node)` | Check if node is in a slot |
756
+ | `getSlotBehavior(node)` | Get slot behavior |
757
+ | `isSlotLocked(node)` | Check if slot is locked |
758
+ | `isSlotEditable(node)` | Check if slot is editable |
759
+ | `isSlotDynamic(node)` | Check if slot is dynamic |
760
+ | `getNodesInSlot()` | Get all nodes in a slot |
761
+ | `getSlotFallback()` | Get slot fallback node |
762
+ | `getSlotConstraints()` | Get slot constraints |
763
+ | `validateSlots()` | Validate all slot assignments |
764
+
765
+ ### Host Data
766
+
767
+ | Export | Description |
768
+ |--------------------------------|------------------------------------|
769
+ | `DEFAULT_SAMPLE_PRODUCTS` | Sample product data for preview |
770
+ | `DEFAULT_SAMPLE_COLLECTIONS` | Sample collection data |
771
+ | `DEFAULT_SAMPLE_SETTINGS` | Sample site settings |
772
+ | `buildHostData(raw)` | Build normalized host data |
773
+
774
+ ### Default Page Schemas
775
+
776
+ | Export | Description |
777
+ |------------------------------|-------------------------------------|
778
+ | `createHomeSchema()` | Home page schema |
779
+ | `createProductsSchema()` | Products listing schema |
780
+ | `createFAQSchema()` | FAQ page schema |
781
+ | `createContactSchema()` | Contact page schema |
782
+ | `createHelpSchema()` | Help center schema |
783
+ | `createPrivacySchema()` | Privacy policy schema |
784
+ | `createTermsSchema()` | Terms of service schema |
785
+ | `createWishlistSchema()` | Wishlist page schema |
786
+ | `PAGE_DEFINITIONS` | All page definitions |
787
+ | `getDefaultSchemaForSlug(s)` | Get default schema for a slug |
788
+
789
+ ### i18n
790
+
791
+ | Export | Description |
792
+ |-------------------------------|------------------------------------|
793
+ | `setLocale(locale)` | Set custom locale object |
794
+ | `setLocaleByCode(code)` | Set locale by code ('es'/'en') |
795
+ | `t(key)` | Translate a key |
796
+ | `es` / `en` | Built-in locale objects |
797
+ | `translateCategory(cat)` | Translate block category name |
798
+
799
+ ### Types (TypeScript)
800
+
801
+ All types are exported for full TypeScript support:
802
+
803
+ ```typescript
804
+ import type {
805
+ Schema, SchemaNode, NodeType, BuiltInNodeType, NodeProps, NodeStyle,
806
+ ThemeTokens, Page, PageDefinition, RenderMode, TemplateType, AnimationPreset,
807
+ RenderContext, PageContext, DataBinding, NodeBindings, NodeDataSource,
808
+ BoundSchemaNode, SlotBehavior, SlotAssignment,
809
+ PublishStage, ValidatorOptions, PublishPipeline,
810
+ TextNodeProps, ImageNodeProps, ButtonNodeProps,
811
+ ProductCardNodeProps, ProductGridNodeProps, CollectionGridNodeProps,
812
+ HeroSectionNodeProps, ImageBannerNodeProps, RichTextSectionNodeProps,
813
+ CTASectionNodeProps, TestimonialSectionNodeProps, FAQSectionNodeProps,
814
+ NavbarNodeProps, FooterNodeProps,
815
+ NodeComponentProps, NodeComponent, CustomComponentMap,
816
+ BlockDefinition, InspectorFieldDef, CompositeNodeTree,
817
+ PageType, PageMetadata, VisibilityRule, DeviceVisibility,
818
+ BuilderLocale, PublishPayload, SchemaValidationResult,
819
+ PublishValidationResult, ValidationIssue,
820
+ BuildRenderContextOptions, SlotConstraints, PageSchemaDefinition,
821
+ } from '@mandolop97/constructor-nexora';
822
+ ```
823
+
824
+ ### Constants
825
+
826
+ | Export | Description |
827
+ |---------------------|-------------------------------------------|
828
+ | `EDITOR_VERSION` | Current editor version string |
829
+ | `ANIMATION_PRESETS` | Map of animation preset → CSS animation |
830
+
831
+ ---
832
+
833
+ ## 16. Integration Examples
834
+
835
+ ### Minimal Setup
836
+
837
+ ```tsx
838
+ import { NexoraBuilderApp } from '@mandolop97/constructor-nexora';
839
+ import '@mandolop97/constructor-nexora/styles.css';
840
+
841
+ export default function BuilderPage() {
842
+ return (
843
+ <NexoraBuilderApp
844
+ onSave={(schema) => console.log('Saved:', schema)}
845
+ locale="en"
846
+ />
847
+ );
848
+ }
849
+ ```
850
+
851
+ ### E-Commerce Template with Data
852
+
853
+ ```tsx
854
+ import { NexoraBuilderApp, buildRenderContext } from '@mandolop97/constructor-nexora';
855
+ import '@mandolop97/constructor-nexora/styles.css';
856
+
857
+ export default function StoreBuilder({ products, collections, settings }) {
858
+ const renderContext = buildRenderContext({
859
+ mode: 'edit',
860
+ products,
861
+ collections,
862
+ settings,
863
+ });
864
+
865
+ return (
866
+ <NexoraBuilderApp
867
+ initialSchema={savedSchema}
868
+ renderContext={renderContext}
869
+ hostData={{ products, collections, settings }}
870
+ onSave={(schema) => api.saveSchema(schema)}
871
+ onPublishSubmit={async (payload) => api.publish(payload)}
872
+ locale="en"
873
+ />
874
+ );
875
+ }
876
+ ```
877
+
878
+ ### Standalone Renderer (Published Site)
879
+
880
+ ```tsx
881
+ import { PageRenderer, buildRenderContext, CustomStylesInjector } from '@mandolop97/constructor-nexora';
882
+ import '@mandolop97/constructor-nexora/styles.css';
883
+
884
+ export default function PublicPage({ schema, products, settings }) {
885
+ const ctx = buildRenderContext({
886
+ mode: 'public',
887
+ page: { pageType: 'home', slug: '/' },
888
+ products,
889
+ settings,
890
+ });
891
+
892
+ return (
893
+ <>
894
+ <CustomStylesInjector css={schema.customCSS} />
895
+ <PageRenderer schema={schema} mode="public" renderContext={ctx} />
896
+ </>
897
+ );
898
+ }
899
+ ```
900
+
901
+ ### Custom Block Extension
902
+
903
+ ```tsx
904
+ import { NexoraBuilderApp } from '@mandolop97/constructor-nexora';
905
+ import type { NodeComponent, BlockDefinition } from '@mandolop97/constructor-nexora';
906
+
907
+ const CountdownTimer: NodeComponent = ({ node }) => (
908
+ <div className="countdown">
909
+ <h3>{node.props.heading || 'Sale ends in'}</h3>
910
+ <span>{node.props.targetDate || '2025-12-31'}</span>
911
+ </div>
912
+ );
913
+
914
+ const countdownBlock: BlockDefinition = {
915
+ type: 'CountdownTimer',
916
+ label: 'Countdown Timer',
917
+ category: 'Marketing',
918
+ canHaveChildren: false,
919
+ defaultProps: { heading: 'Sale ends in', targetDate: '2025-12-31' },
920
+ inspectorFields: [
921
+ { key: 'heading', label: 'Heading', type: 'text' },
922
+ { key: 'targetDate', label: 'Target Date', type: 'text', placeholder: 'YYYY-MM-DD' },
923
+ ],
924
+ };
925
+
926
+ <NexoraBuilderApp
927
+ customComponents={{ CountdownTimer }}
928
+ extraBlocks={[countdownBlock]}
929
+ />
930
+ ```
931
+
932
+ ---
933
+
934
+ *This documentation is auto-generated and ships with the `@mandolop97/constructor-nexora` NPM package. For the latest version, check the package source.*