@shopkit/builder 0.1.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.
@@ -0,0 +1,1338 @@
1
+ import React, { ComponentType, ReactNode } from 'react';
2
+
3
+ /**
4
+ * Commerce Client Interface
5
+ *
6
+ * Consumers implement this interface to provide data fetching capabilities
7
+ * for the page builder. This abstraction allows the page builder to work
8
+ * with any commerce platform (Shopify, custom backends, etc.)
9
+ */
10
+ /**
11
+ * Parameters for fetching a single product
12
+ */
13
+ interface ProductQueryParams {
14
+ handle?: string;
15
+ id?: string;
16
+ }
17
+ /**
18
+ * Parameters for fetching multiple products
19
+ */
20
+ interface ProductsQueryParams {
21
+ first?: number;
22
+ after?: string;
23
+ handles?: string[];
24
+ query?: string;
25
+ sortKey?: string;
26
+ reverse?: boolean;
27
+ }
28
+ /**
29
+ * Parameters for fetching a single collection
30
+ */
31
+ interface CollectionQueryParams {
32
+ handle?: string;
33
+ id?: string;
34
+ productLimit?: number;
35
+ }
36
+ /**
37
+ * Parameters for fetching multiple collections
38
+ */
39
+ interface CollectionsQueryParams {
40
+ first?: number;
41
+ after?: string;
42
+ query?: string;
43
+ }
44
+ /**
45
+ * Parameters for fetching collection with filters (faceted search)
46
+ */
47
+ interface CollectionWithFiltersParams {
48
+ handle: string;
49
+ filters?: Array<Record<string, any>>;
50
+ sortKey?: string;
51
+ reverse?: boolean;
52
+ first?: number;
53
+ after?: string;
54
+ page?: number;
55
+ itemsPerPage?: number;
56
+ }
57
+ /**
58
+ * Parameters for fetching collection by handler
59
+ */
60
+ interface CollectionsByHandlerParams {
61
+ handle: string;
62
+ productLimit?: number;
63
+ sort?: string;
64
+ filter?: Record<string, any>;
65
+ }
66
+ /**
67
+ * Commerce Client Interface
68
+ *
69
+ * Required methods that must be implemented by consumers.
70
+ * Optional methods can be implemented for advanced features.
71
+ */
72
+ interface ICommerceClient {
73
+ /**
74
+ * Fetch a single product by handle or ID
75
+ */
76
+ getProduct(params: ProductQueryParams): Promise<any>;
77
+ /**
78
+ * Fetch multiple products with pagination and filtering
79
+ */
80
+ getProducts(params: ProductsQueryParams): Promise<{
81
+ products: any[];
82
+ pageInfo?: any;
83
+ }>;
84
+ /**
85
+ * Fetch product recommendations for a given product
86
+ */
87
+ getProductRecommendations(productIdOrHandle: string): Promise<any[]>;
88
+ /**
89
+ * Fetch a single collection by handle or ID
90
+ */
91
+ getCollection(params: CollectionQueryParams): Promise<any>;
92
+ /**
93
+ * Fetch multiple collections with pagination
94
+ */
95
+ getCollections(params: CollectionsQueryParams): Promise<{
96
+ collections: any[];
97
+ pageInfo?: any;
98
+ }>;
99
+ /**
100
+ * Optional: Fetch collection with faceted filters
101
+ * Used for collection pages with filtering functionality
102
+ */
103
+ getCollectionWithFilters?(params: CollectionWithFiltersParams): Promise<any>;
104
+ /**
105
+ * Optional: Fetch collection by handler with specific parameters
106
+ * Used for featured collections, category pages, etc.
107
+ */
108
+ getCollectionsByHandler?(params: CollectionsByHandlerParams): Promise<any>;
109
+ }
110
+
111
+ /**
112
+ * Page Builder Theme Types
113
+ *
114
+ * Local type definitions for theme-related functionality within the page builder.
115
+ * These types are intentionally defined here to maintain package independence.
116
+ *
117
+ * When the page builder is extracted as a standalone package, these types
118
+ * will be the contract that consumers must implement.
119
+ *
120
+ * NOTE: These types mirror @/lib/theme/types/theme.ts to maintain consistency.
121
+ * When updating these types, ensure the theme module types are kept in sync.
122
+ *
123
+ * @module lib/page-builder/types/theme
124
+ */
125
+ /**
126
+ * Theme role - determines the state/purpose of a theme
127
+ */
128
+ type ThemeRole = "live" | "draft" | "preview";
129
+ /**
130
+ * Theme configuration object
131
+ *
132
+ * Contains design tokens organized by category.
133
+ * All values are CSS-compatible strings or numbers.
134
+ */
135
+ interface ThemeConfig {
136
+ /**
137
+ * Color palette (e.g., primary, secondary, background, text)
138
+ */
139
+ colors?: Record<string, string>;
140
+ /**
141
+ * Typography settings (fonts, sizes, weights, line heights)
142
+ */
143
+ typography?: Record<string, string | number>;
144
+ /**
145
+ * Spacing values (margins, paddings, gaps)
146
+ */
147
+ spacing?: Record<string, string>;
148
+ /**
149
+ * Border radius values
150
+ */
151
+ borderRadius?: Record<string, string>;
152
+ /**
153
+ * Box shadow definitions
154
+ */
155
+ boxShadow?: Record<string, string>;
156
+ /**
157
+ * Transition settings (duration, timing)
158
+ */
159
+ transition?: Record<string, string>;
160
+ /**
161
+ * Z-index layer definitions
162
+ */
163
+ zIndex?: Record<string, number>;
164
+ /**
165
+ * Font weight definitions
166
+ */
167
+ fontWeight?: Record<string, number>;
168
+ /**
169
+ * Width definitions
170
+ */
171
+ width?: Record<string, string>;
172
+ /**
173
+ * Allow additional custom configuration sections
174
+ */
175
+ [key: string]: Record<string, string | number> | undefined;
176
+ }
177
+ /**
178
+ * Complete theme object with metadata
179
+ */
180
+ interface Theme {
181
+ /**
182
+ * Unique theme identifier
183
+ */
184
+ id: string;
185
+ /**
186
+ * Human-readable theme name
187
+ */
188
+ name: string;
189
+ /**
190
+ * Theme role (live, draft, preview)
191
+ */
192
+ role: ThemeRole;
193
+ /**
194
+ * Theme configuration with all design tokens
195
+ */
196
+ config: ThemeConfig;
197
+ /**
198
+ * Creation timestamp (ISO string)
199
+ */
200
+ createdAt: string;
201
+ /**
202
+ * Last update timestamp (ISO string)
203
+ */
204
+ updatedAt: string;
205
+ }
206
+ /**
207
+ * Theme Loader Interface
208
+ *
209
+ * Consumers implement this interface to provide theme loading capabilities.
210
+ * Themes can be loaded from file system, API, database, or any other source.
211
+ *
212
+ * @example
213
+ * ```typescript
214
+ * const themeLoader: IThemeLoader = {
215
+ * async loadTheme(merchantName: string): Promise<Theme> {
216
+ * const data = await fetchThemeFromAPI(merchantName);
217
+ * return {
218
+ * id: data.id,
219
+ * name: data.name,
220
+ * role: data.role,
221
+ * config: data.config,
222
+ * createdAt: data.createdAt,
223
+ * updatedAt: data.updatedAt,
224
+ * };
225
+ * }
226
+ * };
227
+ * ```
228
+ */
229
+ interface IThemeLoader {
230
+ /**
231
+ * Load the active theme for a merchant
232
+ *
233
+ * @param merchantName - The merchant identifier
234
+ * @returns Promise resolving to the theme configuration
235
+ * @throws Error if theme cannot be loaded
236
+ */
237
+ loadTheme(merchantName: string): Promise<Theme>;
238
+ }
239
+
240
+ /**
241
+ * Data Source Types
242
+ *
243
+ * Defines data source configuration for fetching commerce data.
244
+ */
245
+ /**
246
+ * Data source types constant
247
+ * Defines all available data source types
248
+ */
249
+ declare const DATA_SOURCE_TYPES: {
250
+ /** Single product by handle or ID */
251
+ readonly PRODUCT: "PRODUCT";
252
+ /** Multiple products with query/pagination */
253
+ readonly PRODUCTS: "PRODUCTS";
254
+ /** Multiple products by specific handles */
255
+ readonly PRODUCTS_BY_HANDLES: "PRODUCTS_BY_HANDLES";
256
+ /** Single collection by handle or ID */
257
+ readonly COLLECTION: "COLLECTION";
258
+ /** Multiple collections with pagination */
259
+ readonly COLLECTIONS: "COLLECTIONS";
260
+ /** Collection with faceted filters (for collection pages) */
261
+ readonly COLLECTION_PAGE_WITH_FILTERS: "COLLECTION_PAGE_WITH_FILTERS";
262
+ /** Collection by handler with custom params */
263
+ readonly COLLECTION_BY_HANDLES: "COLLECTION_BY_HANDLES";
264
+ /** Static data (no fetching required) */
265
+ readonly STATIC: "STATIC";
266
+ /** Product recommendations */
267
+ readonly PRODUCT_RECOMMENDATIONS: "PRODUCT_RECOMMENDATIONS";
268
+ };
269
+ /**
270
+ * Data source type union
271
+ */
272
+ type DataSourceType = (typeof DATA_SOURCE_TYPES)[keyof typeof DATA_SOURCE_TYPES];
273
+ /**
274
+ * Data source configuration
275
+ *
276
+ * Defines how to fetch data for a page or widget.
277
+ */
278
+ interface DataSourceConfig {
279
+ /**
280
+ * Type of data source
281
+ */
282
+ type: DataSourceType | string;
283
+ /**
284
+ * Parameters for the data source
285
+ * Structure depends on the data source type
286
+ */
287
+ params: Record<string, any>;
288
+ /**
289
+ * Whether this data source is required for page rendering
290
+ * If true, page will fail if data cannot be fetched
291
+ */
292
+ required: boolean;
293
+ }
294
+
295
+ /**
296
+ * Page Configuration Types
297
+ *
298
+ * Defines the structure of page templates including sections and widgets.
299
+ */
300
+
301
+ /**
302
+ * Spacing values for padding/margin
303
+ */
304
+ interface Spacing {
305
+ top: number;
306
+ right: number;
307
+ bottom: number;
308
+ left: number;
309
+ }
310
+ /**
311
+ * Responsive spacing configuration
312
+ */
313
+ interface ResponsiveSpacing {
314
+ padding?: Spacing;
315
+ margin?: Spacing;
316
+ }
317
+ /**
318
+ * Section settings configuration
319
+ */
320
+ interface SectionSettings {
321
+ /**
322
+ * Layout mode
323
+ * - "page": Constrained to container width
324
+ * - "full": Full viewport width
325
+ */
326
+ layout: "page" | "full";
327
+ /**
328
+ * Responsive settings per breakpoint
329
+ */
330
+ responsive?: {
331
+ mobile?: ResponsiveSpacing;
332
+ tablet?: ResponsiveSpacing;
333
+ desktop?: ResponsiveSpacing;
334
+ wide?: ResponsiveSpacing;
335
+ };
336
+ /**
337
+ * Default padding (fallback)
338
+ */
339
+ padding?: Spacing;
340
+ /**
341
+ * Default margin (fallback)
342
+ */
343
+ margin?: Spacing;
344
+ /**
345
+ * Additional custom settings
346
+ */
347
+ [key: string]: any;
348
+ }
349
+ /**
350
+ * Widget responsive configuration
351
+ */
352
+ interface WidgetResponsiveConfig {
353
+ mobile?: Record<string, any>;
354
+ tablet?: Record<string, any>;
355
+ desktop?: Record<string, any>;
356
+ wide?: Record<string, any>;
357
+ }
358
+ /**
359
+ * Widget configuration
360
+ *
361
+ * Defines a single widget within a section.
362
+ */
363
+ interface WidgetConfig {
364
+ /**
365
+ * Unique widget identifier
366
+ */
367
+ id: string;
368
+ /**
369
+ * Human-readable widget name
370
+ */
371
+ name: string;
372
+ /**
373
+ * Widget type - must match a registered widget in the registry
374
+ */
375
+ type: string;
376
+ /**
377
+ * Reference to a data source key in the page's dataSources
378
+ */
379
+ dataSourceKey?: string;
380
+ /**
381
+ * Widget settings/configuration
382
+ * Supports translation keys with "t:" prefix
383
+ */
384
+ settings: Record<string, any>;
385
+ /**
386
+ * Responsive setting overrides per breakpoint
387
+ */
388
+ responsive?: WidgetResponsiveConfig;
389
+ }
390
+ /**
391
+ * Section configuration
392
+ *
393
+ * Defines a section of a page containing widgets.
394
+ */
395
+ interface SectionConfig {
396
+ /**
397
+ * Unique section identifier
398
+ */
399
+ id: string;
400
+ /**
401
+ * Human-readable section name
402
+ */
403
+ name: string;
404
+ /**
405
+ * Section type identifier
406
+ */
407
+ type: string;
408
+ /**
409
+ * Section settings including layout and spacing
410
+ */
411
+ settings: SectionSettings;
412
+ /**
413
+ * Widgets contained in this section
414
+ */
415
+ widgets: WidgetConfig[];
416
+ }
417
+ /**
418
+ * Page configuration
419
+ *
420
+ * The root configuration object defining a complete page template.
421
+ */
422
+ interface PageConfig {
423
+ /**
424
+ * Unique page/template identifier
425
+ */
426
+ id: string;
427
+ /**
428
+ * Data sources available to widgets on this page
429
+ * Key is the data source identifier, value is the configuration
430
+ */
431
+ dataSources: Record<string, DataSourceConfig>;
432
+ /**
433
+ * Page sections in render order
434
+ */
435
+ sections: SectionConfig[];
436
+ /**
437
+ * Theme overrides for this specific page
438
+ */
439
+ theme?: Record<string, any>;
440
+ /**
441
+ * Responsive configuration for the page
442
+ */
443
+ responsive?: any;
444
+ /**
445
+ * Custom breakpoint configuration
446
+ */
447
+ breakpoints?: any;
448
+ /**
449
+ * Additional metadata
450
+ */
451
+ [key: string]: any;
452
+ }
453
+ /**
454
+ * Template type alias
455
+ * A template is just a PageConfig
456
+ */
457
+ type Template = PageConfig;
458
+ /**
459
+ * Page configuration helpers
460
+ */
461
+ declare class PageConfigHelpers {
462
+ /**
463
+ * Get all data source keys used by widgets
464
+ */
465
+ static getUsedDataSources(pageConfig: PageConfig): string[];
466
+ /**
467
+ * Find a widget by ID
468
+ */
469
+ static findWidget(pageConfig: PageConfig, widgetId: string): WidgetConfig | null;
470
+ /**
471
+ * Find a section by ID
472
+ */
473
+ static findSection(pageConfig: PageConfig, sectionId: string): SectionConfig | null;
474
+ /**
475
+ * Generate a unique ID with prefix
476
+ */
477
+ static generateId(prefix: string): string;
478
+ /**
479
+ * Validate page configuration structure
480
+ */
481
+ static validate(pageConfig: PageConfig): {
482
+ valid: boolean;
483
+ errors: string[];
484
+ };
485
+ }
486
+ /**
487
+ * Schema definition for sections - used by the editor to generate forms
488
+ */
489
+ interface SectionSchema {
490
+ /** Section type identifier */
491
+ type: string;
492
+ /** Display name for the editor */
493
+ name: string;
494
+ /** Description for the editor */
495
+ description?: string;
496
+ /** Settings schema for the section (editor-only, shape matches DynamicForm) */
497
+ settingsSchema: Record<string, {
498
+ type: "text" | "number" | "boolean" | "select" | "spacing" | "image" | "faq" | "richtext" | "objectArray" | "array";
499
+ label?: string;
500
+ default?: any;
501
+ options?: Array<{
502
+ value: any;
503
+ label: string;
504
+ }>;
505
+ min?: number;
506
+ max?: number;
507
+ step?: number;
508
+ unit?: string;
509
+ optional?: boolean;
510
+ fields?: string[];
511
+ placeholder?: string;
512
+ }>;
513
+ }
514
+ /**
515
+ * Schema definition for widgets - used by the editor to generate forms
516
+ */
517
+ interface WidgetSchema {
518
+ /** Widget type identifier */
519
+ type: string;
520
+ /** Display name for the editor */
521
+ name: string;
522
+ /** Description for the editor */
523
+ description?: string;
524
+ /** Settings schema for the widget */
525
+ settingsSchema: Record<string, {
526
+ type: "text" | "number" | "boolean" | "select" | "spacing" | "object" | "array" | "objectArray" | "richtext";
527
+ label?: string;
528
+ default?: any;
529
+ options?: Array<{
530
+ value: any;
531
+ label: string;
532
+ }>;
533
+ min?: number;
534
+ max?: number;
535
+ unit?: string;
536
+ optional?: boolean;
537
+ properties?: Record<string, any>;
538
+ fields?: string[];
539
+ }>;
540
+ /** Whether this widget requires a data source */
541
+ requiresDataSource?: boolean;
542
+ /** Compatible data source types */
543
+ compatibleDataSources?: string[];
544
+ /** Responsive settings that can be overridden */
545
+ responsiveSettings?: string[];
546
+ }
547
+ /**
548
+ * Registry types for the editor
549
+ */
550
+ interface SectionRegistry {
551
+ [key: string]: SectionSchema;
552
+ }
553
+ /**
554
+ * Widget Registry for editor (different from IWidgetRegistry)
555
+ * Maps widget type names to their schemas
556
+ */
557
+ interface WidgetSchemaRegistry {
558
+ [key: string]: WidgetSchema;
559
+ }
560
+
561
+ /**
562
+ * Template Loader Interface
563
+ *
564
+ * Consumers implement this interface to provide template loading capabilities.
565
+ * Templates can be loaded from file system, API, CMS, or any other source.
566
+ */
567
+
568
+ /**
569
+ * Template variant mapping configuration
570
+ * Maps API data fields to template variants
571
+ */
572
+ interface TemplateVariantMapping {
573
+ /**
574
+ * The API field to check for variant determination
575
+ * Supports dot notation for nested fields (e.g., "collection.handle")
576
+ */
577
+ apiField: string;
578
+ /**
579
+ * Map of API field values to template variant names
580
+ * Optional - if not provided, defaultVariant is used
581
+ */
582
+ variantMap?: Record<string, string>;
583
+ /**
584
+ * Default variant to use if no match is found
585
+ */
586
+ defaultVariant: string;
587
+ }
588
+ /**
589
+ * Template Variant Registry
590
+ * Registry of template variant mappings by template type
591
+ */
592
+ interface TemplateVariantRegistry {
593
+ [templateType: string]: TemplateVariantMapping;
594
+ }
595
+ /**
596
+ * Variant Registry Result
597
+ * Wrapper for variant registry returned by loadVariantRegistry
598
+ */
599
+ interface VariantRegistryResult {
600
+ variantRegistry: TemplateVariantRegistry;
601
+ }
602
+ /**
603
+ * Template Loader Interface
604
+ *
605
+ * Provides methods to load page templates and variant registries.
606
+ */
607
+ interface ITemplateLoader {
608
+ /**
609
+ * Load a page template configuration
610
+ *
611
+ * @param merchantName - The merchant identifier
612
+ * @param templateName - The template type (e.g., "home", "product", "collection")
613
+ * @param variant - The template variant (e.g., "default", "featured")
614
+ * @returns Promise resolving to the page configuration
615
+ */
616
+ loadTemplate(merchantName: string, templateName: string, variant: string): Promise<PageConfig>;
617
+ /**
618
+ * Load variant registry for automatic variant selection
619
+ * Optional - if not implemented, "default" variant is always used
620
+ *
621
+ * @param merchantName - The merchant identifier
622
+ * @returns Promise resolving to the variant registry wrapper or null
623
+ */
624
+ loadVariantRegistry?(merchantName: string): Promise<VariantRegistryResult | null>;
625
+ }
626
+
627
+ /**
628
+ * Widget Registry Interface and Default Implementation
629
+ *
630
+ * The widget registry maps widget type strings to React components.
631
+ * Consumers can use the default WidgetRegistry class or provide their own implementation.
632
+ */
633
+
634
+ /**
635
+ * Widget registration entry
636
+ */
637
+ interface WidgetRegistration {
638
+ type: string;
639
+ component: ComponentType<any>;
640
+ }
641
+ /**
642
+ * Widget Registry Interface
643
+ *
644
+ * Maps widget type strings to React components for rendering.
645
+ */
646
+ interface IWidgetRegistry {
647
+ /**
648
+ * Register a single widget component
649
+ *
650
+ * @param type - The widget type identifier
651
+ * @param component - The React component to render
652
+ */
653
+ register(type: string, component: ComponentType<any>): void;
654
+ /**
655
+ * Register multiple widget components at once
656
+ *
657
+ * @param widgets - Array of widget registrations
658
+ */
659
+ registerAll(widgets: WidgetRegistration[]): void;
660
+ /**
661
+ * Get a widget component by type
662
+ *
663
+ * @param type - The widget type identifier
664
+ * @returns The React component or undefined if not found
665
+ */
666
+ get(type: string): ComponentType<any> | undefined;
667
+ /**
668
+ * Check if a widget type is registered
669
+ *
670
+ * @param type - The widget type identifier
671
+ * @returns True if the widget is registered
672
+ */
673
+ has(type: string): boolean;
674
+ /**
675
+ * Get all registered widget types
676
+ *
677
+ * @returns Array of registered widget type identifiers
678
+ */
679
+ getRegisteredTypes(): string[];
680
+ }
681
+ /**
682
+ * Default Widget Registry Implementation
683
+ *
684
+ * A simple Map-based implementation of the widget registry.
685
+ * Consumers can use this directly or provide their own implementation.
686
+ */
687
+ declare class WidgetRegistry implements IWidgetRegistry {
688
+ private widgets;
689
+ /**
690
+ * Register a single widget component
691
+ */
692
+ register(type: string, component: ComponentType<any>): void;
693
+ /**
694
+ * Register multiple widget components at once
695
+ */
696
+ registerAll(widgets: WidgetRegistration[]): void;
697
+ /**
698
+ * Get a widget component by type
699
+ */
700
+ get(type: string): ComponentType<any> | undefined;
701
+ /**
702
+ * Check if a widget type is registered
703
+ */
704
+ has(type: string): boolean;
705
+ /**
706
+ * Get all registered widget types
707
+ */
708
+ getRegisteredTypes(): string[];
709
+ /**
710
+ * Clear all registered widgets
711
+ */
712
+ clear(): void;
713
+ /**
714
+ * Get the total count of registered widgets
715
+ */
716
+ get size(): number;
717
+ }
718
+
719
+ /**
720
+ * Route Context Types
721
+ *
722
+ * Defines the context passed to the page builder for rendering.
723
+ */
724
+ /**
725
+ * Viewport breakpoint type
726
+ */
727
+ type Breakpoint = "mobile" | "tablet" | "desktop" | "wide";
728
+ /**
729
+ * Breakpoint configuration for responsive design
730
+ */
731
+ interface BreakpointConfig {
732
+ mobile: {
733
+ max: number;
734
+ };
735
+ tablet: {
736
+ min: number;
737
+ max: number;
738
+ };
739
+ desktop: {
740
+ min: number;
741
+ max: number;
742
+ };
743
+ wide: {
744
+ min: number;
745
+ };
746
+ custom?: Record<string, {
747
+ min?: number;
748
+ max?: number;
749
+ }>;
750
+ }
751
+ /**
752
+ * Default breakpoints
753
+ */
754
+ declare const DEFAULT_BREAKPOINTS: BreakpointConfig;
755
+ /**
756
+ * Viewport information
757
+ */
758
+ interface ViewportInfo {
759
+ width: number;
760
+ height: number;
761
+ breakpoint: Breakpoint;
762
+ }
763
+ /**
764
+ * Route Context
765
+ *
766
+ * Contains all information about the current route being rendered.
767
+ */
768
+ interface RouteContext {
769
+ /**
770
+ * Template name to use for rendering
771
+ * e.g., "home", "product", "collection"
772
+ */
773
+ templateName: string;
774
+ /**
775
+ * Current page path
776
+ * e.g., "/", "/products/my-product", "/collections/featured"
777
+ */
778
+ path: string;
779
+ /**
780
+ * URL path parameters
781
+ * e.g., { handle: "my-product" }
782
+ */
783
+ params: Record<string, string>;
784
+ /**
785
+ * URL query parameters
786
+ * e.g., { sort: "price-asc", page: "2" }
787
+ */
788
+ query?: Record<string, string | string[] | undefined>;
789
+ /**
790
+ * Product handle (for product pages)
791
+ */
792
+ productHandle?: string;
793
+ /**
794
+ * Collection handle (for collection pages)
795
+ */
796
+ collectionHandle?: string;
797
+ /**
798
+ * Current viewport information
799
+ */
800
+ viewport?: ViewportInfo;
801
+ /**
802
+ * Whether to fetch template from API (for visual editor integration)
803
+ */
804
+ fetchAPITemplate?: boolean;
805
+ /**
806
+ * Additional custom context data
807
+ */
808
+ [key: string]: any;
809
+ }
810
+
811
+ /**
812
+ * Section Renderer Interface
813
+ *
814
+ * Defines the function type for rendering section wrappers.
815
+ * Consumers can provide custom section rendering logic for styling,
816
+ * responsive behavior, or special section types.
817
+ */
818
+
819
+ /**
820
+ * Context provided to section renderers
821
+ */
822
+ interface SectionRenderContext {
823
+ /**
824
+ * Merged theme and page styles
825
+ */
826
+ styles: Record<string, any>;
827
+ /**
828
+ * Current route context
829
+ */
830
+ routeContext: RouteContext;
831
+ /**
832
+ * Current breakpoint (if detected)
833
+ */
834
+ breakpoint?: "mobile" | "tablet" | "desktop" | "wide";
835
+ }
836
+ /**
837
+ * Section Renderer Function Type
838
+ *
839
+ * A function that renders a section wrapper around its children widgets.
840
+ *
841
+ * @param section - The section configuration
842
+ * @param children - The rendered widget React nodes
843
+ * @param context - Additional context including styles and route info
844
+ * @returns A React node representing the rendered section
845
+ */
846
+ type SectionRenderer = (section: SectionConfig, children: ReactNode[], context: SectionRenderContext) => ReactNode;
847
+
848
+ /**
849
+ * Locale Type
850
+ *
851
+ * Defines supported locales for the page builder.
852
+ * Internalized to avoid external dependencies.
853
+ */
854
+ /**
855
+ * Supported locale codes
856
+ */
857
+ type Locale = "en" | "hi" | string;
858
+ /**
859
+ * Default locale
860
+ */
861
+ declare const DEFAULT_LOCALE: Locale;
862
+
863
+ /**
864
+ * Page Building Engine
865
+ *
866
+ * The main orchestrator that coordinates all other components to render a page.
867
+ * All dependencies are injected via constructor for complete encapsulation.
868
+ */
869
+
870
+ /**
871
+ * Render Page Parameters
872
+ */
873
+ interface RenderPageParams {
874
+ /**
875
+ * Merchant identifier - REQUIRED, no fallback
876
+ */
877
+ merchantName: string;
878
+ /**
879
+ * Route context with template name, path, params
880
+ */
881
+ routeContext: RouteContext;
882
+ /**
883
+ * Locale for this render
884
+ */
885
+ locale?: Locale;
886
+ /**
887
+ * Translation messages for i18n
888
+ */
889
+ messages?: Record<string, any>;
890
+ /**
891
+ * Optional pre-loaded page config (skips template loading)
892
+ */
893
+ pageConfig?: PageConfig;
894
+ }
895
+
896
+ /**
897
+ * Page Builder Factory Function
898
+ *
899
+ * The single public API for creating a page builder instance.
900
+ * All dependencies are injected through the options parameter.
901
+ */
902
+
903
+ /**
904
+ * Options for creating a page builder instance
905
+ */
906
+ interface PageBuilderOptions {
907
+ /**
908
+ * Commerce client for fetching products, collections, etc.
909
+ * REQUIRED - consumers must implement ICommerceClient
910
+ */
911
+ commerceClient: ICommerceClient;
912
+ /**
913
+ * Theme loader for fetching merchant themes
914
+ * REQUIRED - consumers implement how themes are loaded
915
+ */
916
+ themeLoader: IThemeLoader;
917
+ /**
918
+ * Template loader for fetching page templates
919
+ * REQUIRED - consumers implement how templates are loaded
920
+ */
921
+ templateLoader: ITemplateLoader;
922
+ /**
923
+ * Widget registry with all registered widget components
924
+ * REQUIRED - consumers populate with their widgets
925
+ */
926
+ widgetRegistry: IWidgetRegistry;
927
+ /**
928
+ * Custom section renderer component
929
+ * OPTIONAL - defaults to a basic <section> wrapper
930
+ */
931
+ sectionRenderer?: SectionRenderer;
932
+ /**
933
+ * Default locale for the page builder
934
+ * OPTIONAL - defaults to 'en'
935
+ */
936
+ defaultLocale?: Locale;
937
+ }
938
+ /**
939
+ * Validation result for page config
940
+ */
941
+ interface ValidationResult {
942
+ valid: boolean;
943
+ errors: string[];
944
+ }
945
+ /**
946
+ * Page Builder Interface
947
+ *
948
+ * The public interface returned by createPageBuilder()
949
+ */
950
+ interface PageBuilder {
951
+ /**
952
+ * Render a page to React nodes
953
+ */
954
+ renderPage(params: RenderPageParams): Promise<React.ReactNode>;
955
+ /**
956
+ * Clear internal caches
957
+ */
958
+ clearCache(): void;
959
+ /**
960
+ * Validate a page configuration
961
+ */
962
+ validateConfig(config: PageConfig): ValidationResult;
963
+ }
964
+ /**
965
+ * Create a new page builder instance
966
+ *
967
+ * This is the main entry point for using the page builder.
968
+ * All dependencies are provided through the options parameter.
969
+ *
970
+ * @example
971
+ * ```typescript
972
+ * import { createPageBuilder, WidgetRegistry } from '@/lib/page-builder';
973
+ *
974
+ * // Create and populate widget registry
975
+ * const widgetRegistry = new WidgetRegistry();
976
+ * widgetRegistry.registerAll([
977
+ * { type: 'Header', component: HeaderWidget },
978
+ * { type: 'ProductCard', component: ProductCardWidget },
979
+ * ]);
980
+ *
981
+ * // Create page builder with all dependencies
982
+ * const pageBuilder = createPageBuilder({
983
+ * commerceClient: myCommerceClient,
984
+ * themeLoader: myThemeLoader,
985
+ * templateLoader: myTemplateLoader,
986
+ * widgetRegistry,
987
+ * defaultLocale: 'en',
988
+ * });
989
+ *
990
+ * // Use in pages
991
+ * const content = await pageBuilder.renderPage({
992
+ * merchantName: 'my-merchant',
993
+ * routeContext: {
994
+ * templateName: 'home',
995
+ * path: '/',
996
+ * params: {},
997
+ * },
998
+ * });
999
+ * ```
1000
+ */
1001
+ declare function createPageBuilder(options: PageBuilderOptions): PageBuilder;
1002
+
1003
+ /**
1004
+ * Layout and Alignment Options
1005
+ *
1006
+ * Type-safe constants for layout and alignment values used in templates.
1007
+ * These constants are exported from the page-builder package for use in templates.
1008
+ */
1009
+ /**
1010
+ * Section Types
1011
+ * Defines the semantic types of sections in a page layout.
1012
+ * Moved here from ui/layout/constants to centralize all template constants.
1013
+ */
1014
+ declare const SECTION_TYPES: {
1015
+ readonly HEADER_SECTION: "HEADER_SECTION";
1016
+ readonly GRID_SECTION: "GRID_SECTION";
1017
+ readonly HERO_SECTION: "HERO_SECTION";
1018
+ readonly CONTENT_SECTION: "CONTENT_SECTION";
1019
+ readonly FOOTER_SECTION: "FOOTER_SECTION";
1020
+ };
1021
+ type SectionType = (typeof SECTION_TYPES)[keyof typeof SECTION_TYPES];
1022
+ /**
1023
+ * Section Layout Options
1024
+ * Extracted from section schema registry
1025
+ */
1026
+ declare const SECTION_LAYOUT_OPTIONS: {
1027
+ readonly PAGE: "page";
1028
+ readonly FULL: "full";
1029
+ };
1030
+ /**
1031
+ * Section Alignment Options
1032
+ * Extracted from section schema registry
1033
+ */
1034
+ declare const SECTION_ALIGNMENT_OPTIONS: {
1035
+ readonly LEFT: "left";
1036
+ readonly CENTER: "center";
1037
+ readonly RIGHT: "right";
1038
+ };
1039
+ /**
1040
+ * Widget Aspect Ratio Options
1041
+ * Extracted from widget schema registry
1042
+ */
1043
+ declare const ASPECT_RATIO_OPTIONS: {
1044
+ readonly SQUARE: "1:1";
1045
+ readonly STANDARD: "4:3";
1046
+ readonly CLASSIC: "3:2";
1047
+ readonly WIDE: "16:9";
1048
+ };
1049
+ /**
1050
+ * Widget Text Alignment Options
1051
+ */
1052
+ declare const TEXT_ALIGNMENT_OPTIONS: {
1053
+ readonly LEFT: "left";
1054
+ readonly CENTER: "center";
1055
+ readonly RIGHT: "right";
1056
+ };
1057
+ /**
1058
+ * Card Style Options
1059
+ */
1060
+ declare const CARD_STYLE_OPTIONS: {
1061
+ readonly STANDARD: "standard";
1062
+ readonly COMPACT: "compact";
1063
+ readonly MINIMAL: "minimal";
1064
+ };
1065
+ /**
1066
+ * Type definitions for better type safety
1067
+ */
1068
+ type SectionLayoutOption = (typeof SECTION_LAYOUT_OPTIONS)[keyof typeof SECTION_LAYOUT_OPTIONS];
1069
+ type SectionAlignmentOption = (typeof SECTION_ALIGNMENT_OPTIONS)[keyof typeof SECTION_ALIGNMENT_OPTIONS];
1070
+ type AspectRatioOption = (typeof ASPECT_RATIO_OPTIONS)[keyof typeof ASPECT_RATIO_OPTIONS];
1071
+ type TextAlignmentOption = (typeof TEXT_ALIGNMENT_OPTIONS)[keyof typeof TEXT_ALIGNMENT_OPTIONS];
1072
+ type CardStyleOption = (typeof CARD_STYLE_OPTIONS)[keyof typeof CARD_STYLE_OPTIONS];
1073
+
1074
+ /**
1075
+ * Widget Props Types
1076
+ *
1077
+ * Base prop types that all widgets receive from the page builder.
1078
+ */
1079
+
1080
+ /**
1081
+ * Base Widget Props
1082
+ *
1083
+ * All widgets receive these props from the page builder.
1084
+ * Widgets can extend this with their own specific data and settings types.
1085
+ *
1086
+ * @template TData - Type of data the widget receives (default: any)
1087
+ * @template TSettings - Type of settings the widget accepts (default: Record<string, any>)
1088
+ */
1089
+ interface WidgetProps<TData = any, TSettings = Record<string, any>> {
1090
+ /**
1091
+ * Unique widget instance ID
1092
+ */
1093
+ id: string;
1094
+ /**
1095
+ * Data fetched from the widget's data source
1096
+ */
1097
+ data: TData;
1098
+ /**
1099
+ * Widget configuration settings
1100
+ * These come from the template and may include translated values
1101
+ */
1102
+ settings: TSettings;
1103
+ /**
1104
+ * Current locale
1105
+ */
1106
+ locale?: Locale;
1107
+ /**
1108
+ * Current route context
1109
+ */
1110
+ routeContext?: RouteContext;
1111
+ /**
1112
+ * Optional CSS class name for additional styling
1113
+ */
1114
+ className?: string;
1115
+ }
1116
+
1117
+ /**
1118
+ * Default Section Wrapper Component
1119
+ *
1120
+ * A simple default section wrapper used when consumers don't provide
1121
+ * a custom section renderer.
1122
+ */
1123
+
1124
+ /**
1125
+ * Default Section Wrapper
1126
+ *
1127
+ * Renders a section with responsive spacing and layout constraints.
1128
+ */
1129
+ declare function DefaultSectionWrapper(section: SectionConfig, children: React.ReactNode[], context: SectionRenderContext): React.ReactNode;
1130
+
1131
+ /**
1132
+ * File System Preset
1133
+ *
1134
+ * Pre-configured page builder for file-system based theme and template loading.
1135
+ * This preset is fully injectable - all dependencies must be provided by the consumer.
1136
+ *
1137
+ * ## Usage
1138
+ *
1139
+ * ```typescript
1140
+ * import { getPageBuilder } from "@/lib/page-builder/presets";
1141
+ * import { WIDGET_MANIFEST } from "@/widgets/.generated/manifest";
1142
+ * import { getCommerceClient } from "@/lib/data-layer";
1143
+ * import { SectionWrapper } from "@/ui/layout/SectionWrapper";
1144
+ *
1145
+ * // Initialize with required dependencies
1146
+ * const pageBuilder = getPageBuilder({
1147
+ * widgets: WIDGET_MANIFEST,
1148
+ * commerceClient: getCommerceClient(),
1149
+ * sectionRenderer: SectionWrapper,
1150
+ * themeLoader: { loadTheme: async (merchant) => import(`@/themes/${merchant}/theme.json`) },
1151
+ * templateLoader: { loadTemplate: async (merchant, template, variant) => ... },
1152
+ * });
1153
+ *
1154
+ * // Use in page
1155
+ * const content = await pageBuilder.renderPage({
1156
+ * merchantName: "wellversed",
1157
+ * routeContext: { templateName: "home", path: "/", params: {} },
1158
+ * });
1159
+ * ```
1160
+ */
1161
+
1162
+ /**
1163
+ * Widget registration entry
1164
+ */
1165
+ interface WidgetEntry {
1166
+ type: string;
1167
+ component: React.ComponentType<any>;
1168
+ }
1169
+ /**
1170
+ * Options for creating a file-system based page builder
1171
+ *
1172
+ * All dependencies are injectable - no external imports are used internally.
1173
+ */
1174
+ interface FileSystemPresetOptions {
1175
+ /**
1176
+ * Array of widget registrations.
1177
+ * REQUIRED - must be provided by consumer.
1178
+ *
1179
+ * @example
1180
+ * ```typescript
1181
+ * import { WIDGET_MANIFEST } from "@/widgets/.generated/manifest";
1182
+ * getPageBuilder({ widgets: WIDGET_MANIFEST, ... });
1183
+ * ```
1184
+ */
1185
+ widgets: WidgetEntry[];
1186
+ /**
1187
+ * Commerce client for fetching products/collections.
1188
+ * REQUIRED - must be provided by consumer.
1189
+ *
1190
+ * @example
1191
+ * ```typescript
1192
+ * import { getCommerceClient } from "@/lib/data-layer";
1193
+ * getPageBuilder({ commerceClient: getCommerceClient(), ... });
1194
+ * ```
1195
+ */
1196
+ commerceClient: ICommerceClient;
1197
+ /**
1198
+ * Theme loader for loading merchant themes.
1199
+ * REQUIRED - must be provided by consumer.
1200
+ *
1201
+ * @example
1202
+ * ```typescript
1203
+ * const themeLoader = {
1204
+ * loadTheme: async (merchant) => {
1205
+ * const mod = await import(`@/themes/${merchant}/theme.json`);
1206
+ * return { id: mod.default.id, name: mod.default.name, ... };
1207
+ * }
1208
+ * };
1209
+ * ```
1210
+ */
1211
+ themeLoader: IThemeLoader;
1212
+ /**
1213
+ * Template loader for loading page templates.
1214
+ * REQUIRED - must be provided by consumer.
1215
+ *
1216
+ * @example
1217
+ * ```typescript
1218
+ * const templateLoader = {
1219
+ * loadTemplate: async (merchant, template, variant) => {
1220
+ * const mod = await import(`@/themes/${merchant}/templates/${template}/${variant}`);
1221
+ * return mod.template;
1222
+ * },
1223
+ * loadVariantRegistry: async (merchant) => {
1224
+ * try {
1225
+ * return await import(`@/themes/${merchant}/templates/variant-registry`);
1226
+ * } catch { return null; }
1227
+ * }
1228
+ * };
1229
+ * ```
1230
+ */
1231
+ templateLoader: ITemplateLoader;
1232
+ /**
1233
+ * Custom section renderer function or component.
1234
+ * OPTIONAL - defaults to DefaultSectionWrapper.
1235
+ *
1236
+ * @example
1237
+ * ```typescript
1238
+ * import { SectionWrapper } from "@/ui/layout/SectionWrapper";
1239
+ *
1240
+ * // Wrap component as SectionRenderer function
1241
+ * const sectionRenderer = (section, children, context) =>
1242
+ * React.createElement(SectionWrapper, { section, styles: context.styles, children });
1243
+ * ```
1244
+ */
1245
+ sectionRenderer?: SectionRenderer;
1246
+ /**
1247
+ * Default locale for translations.
1248
+ * OPTIONAL - defaults to "en".
1249
+ */
1250
+ defaultLocale?: string;
1251
+ }
1252
+ /**
1253
+ * Creates a new file-system based page builder instance
1254
+ *
1255
+ * Use this when you need a fresh instance (e.g., testing).
1256
+ * For most cases, use `getPageBuilder()` instead.
1257
+ *
1258
+ * @throws Error if required options are missing
1259
+ */
1260
+ declare function createFileSystemPageBuilder(options: FileSystemPresetOptions): PageBuilder;
1261
+ /**
1262
+ * Gets the singleton page builder instance
1263
+ *
1264
+ * This is the recommended way to get a page builder in production.
1265
+ * The instance is created on first call and reused thereafter.
1266
+ *
1267
+ * NOTE: All dependencies must be provided on first call.
1268
+ * Subsequent calls can omit options (singleton is returned).
1269
+ *
1270
+ * @throws Error if required options are missing on first call
1271
+ *
1272
+ * @example
1273
+ * ```typescript
1274
+ * // First call - provide all dependencies
1275
+ * const pageBuilder = getPageBuilder({
1276
+ * widgets: WIDGET_MANIFEST,
1277
+ * commerceClient: getCommerceClient(),
1278
+ * themeLoader: myThemeLoader,
1279
+ * templateLoader: myTemplateLoader,
1280
+ * });
1281
+ *
1282
+ * // Subsequent calls - singleton returned
1283
+ * const same = getPageBuilder(); // Returns same instance
1284
+ * ```
1285
+ */
1286
+ declare function getPageBuilder(options?: FileSystemPresetOptions): PageBuilder;
1287
+ /**
1288
+ * Resets the singleton instance
1289
+ *
1290
+ * Useful for testing or when you need to reinitialize with different options.
1291
+ */
1292
+ declare function resetPageBuilder(): void;
1293
+ /**
1294
+ * Creates a section renderer from a React component
1295
+ *
1296
+ * Utility to wrap a SectionWrapper component as a SectionRenderer function.
1297
+ *
1298
+ * @example
1299
+ * ```typescript
1300
+ * import { SectionWrapper } from "@/ui/layout/SectionWrapper";
1301
+ *
1302
+ * getPageBuilder({
1303
+ * sectionRenderer: createSectionRendererFromComponent(SectionWrapper),
1304
+ * ...
1305
+ * });
1306
+ * ```
1307
+ */
1308
+ declare function createSectionRendererFromComponent(Component: React.ComponentType<{
1309
+ section: SectionConfig;
1310
+ styles: Record<string, any>;
1311
+ children: React.ReactNode[];
1312
+ }>): SectionRenderer;
1313
+ /**
1314
+ * Creates a commerce client adapter
1315
+ *
1316
+ * Wraps an existing client to ensure it matches the ICommerceClient interface.
1317
+ *
1318
+ * @example
1319
+ * ```typescript
1320
+ * import { shopifyClient } from "@/lib/shopify";
1321
+ *
1322
+ * getPageBuilder({
1323
+ * commerceClient: createCommerceClientAdapter(shopifyClient),
1324
+ * ...
1325
+ * });
1326
+ * ```
1327
+ */
1328
+ declare function createCommerceClientAdapter(client: {
1329
+ getProduct: (params: any) => Promise<any>;
1330
+ getProducts: (params: any) => Promise<any>;
1331
+ getProductRecommendations: (id: string) => Promise<any>;
1332
+ getCollection: (params: any) => Promise<any>;
1333
+ getCollections: (params: any) => Promise<any>;
1334
+ getCollectionWithFilters?: (params: any) => Promise<any>;
1335
+ getCollectionsByHandler?: (params: any) => Promise<any>;
1336
+ }): ICommerceClient;
1337
+
1338
+ export { ASPECT_RATIO_OPTIONS, type AspectRatioOption, type Breakpoint, type BreakpointConfig, CARD_STYLE_OPTIONS, type CardStyleOption, DATA_SOURCE_TYPES, DEFAULT_BREAKPOINTS, DEFAULT_LOCALE, type DataSourceConfig, type DataSourceType, DefaultSectionWrapper, type FileSystemPresetOptions, type ICommerceClient, type ITemplateLoader, type IThemeLoader, type IWidgetRegistry, type Locale, type PageBuilder, type PageBuilderOptions, type PageConfig, PageConfigHelpers, type RenderPageParams, type ResponsiveSpacing, type RouteContext, SECTION_ALIGNMENT_OPTIONS, SECTION_LAYOUT_OPTIONS, SECTION_TYPES, type SectionAlignmentOption, type SectionConfig, type SectionLayoutOption, type SectionRegistry, type SectionRenderContext, type SectionRenderer, type SectionSchema, type SectionSettings, type SectionType, type Spacing, TEXT_ALIGNMENT_OPTIONS, type Template, type TemplateVariantRegistry, type TextAlignmentOption, type Theme, type ThemeConfig, type ThemeRole, type ValidationResult, type VariantRegistryResult, type ViewportInfo, type WidgetConfig, type WidgetEntry, type WidgetProps, WidgetRegistry, type WidgetResponsiveConfig, type WidgetSchema, type WidgetSchemaRegistry, createCommerceClientAdapter, createFileSystemPageBuilder, createPageBuilder, createSectionRendererFromComponent, getPageBuilder, resetPageBuilder };