@storepecker/editor-bridge 1.0.1 → 1.1.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/dist/index.d.mts +113 -18
- package/dist/index.d.ts +113 -18
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -94,6 +94,7 @@ interface ColorSchemeConfig {
|
|
|
94
94
|
interface HeroConfig {
|
|
95
95
|
cta: string;
|
|
96
96
|
title: string;
|
|
97
|
+
description: string;
|
|
97
98
|
ctaLink: string;
|
|
98
99
|
showCTA: boolean;
|
|
99
100
|
heroImage: string;
|
|
@@ -109,11 +110,11 @@ interface SliderSlide {
|
|
|
109
110
|
id: string;
|
|
110
111
|
cta: string;
|
|
111
112
|
title: string;
|
|
113
|
+
description: string;
|
|
112
114
|
ctaLink: string;
|
|
113
115
|
bannerImage: string;
|
|
114
|
-
bannerImageMobile
|
|
115
|
-
|
|
116
|
-
showContents: boolean;
|
|
116
|
+
bannerImageMobile: string;
|
|
117
|
+
showContents?: boolean;
|
|
117
118
|
}
|
|
118
119
|
interface FooterConfig {
|
|
119
120
|
showSocialLinks: boolean;
|
|
@@ -140,19 +141,110 @@ interface FontConfig {
|
|
|
140
141
|
label?: string;
|
|
141
142
|
value?: string;
|
|
142
143
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
* Each type has different additional fields — we use [key: string]: any
|
|
147
|
-
* because section types are extensible and vary by theme.
|
|
148
|
-
*/
|
|
149
|
-
interface SectionItem {
|
|
144
|
+
type FilterType = 'category' | 'badge' | 'title';
|
|
145
|
+
type FilterOption = 'select' | 'equals' | 'contain' | 'startWith' | 'endWith';
|
|
146
|
+
interface SectionFilters {
|
|
150
147
|
id: string;
|
|
151
|
-
type:
|
|
148
|
+
type: FilterType;
|
|
149
|
+
label: string;
|
|
150
|
+
condition: FilterOption;
|
|
151
|
+
value: string | string[];
|
|
152
|
+
}
|
|
153
|
+
interface ProductCollection {
|
|
154
|
+
type: 'product-collection';
|
|
155
|
+
title?: string;
|
|
156
|
+
filters?: SectionFilters[];
|
|
157
|
+
id: string;
|
|
158
|
+
row_count: number;
|
|
159
|
+
enabled?: boolean;
|
|
160
|
+
}
|
|
161
|
+
interface CategorySection {
|
|
162
|
+
type: 'categories';
|
|
163
|
+
title?: string;
|
|
164
|
+
id?: string;
|
|
165
|
+
categories?: any[];
|
|
166
|
+
selectedCategories?: string[];
|
|
167
|
+
enabled?: boolean;
|
|
168
|
+
}
|
|
169
|
+
interface Banner {
|
|
170
|
+
type: 'banner';
|
|
171
|
+
title: string;
|
|
172
|
+
description?: string;
|
|
173
|
+
bannerImage: string;
|
|
174
|
+
ctaText?: string;
|
|
175
|
+
ctaLink?: string;
|
|
176
|
+
id: string;
|
|
177
|
+
bannerLink: string;
|
|
178
|
+
showContents: boolean;
|
|
179
|
+
mobileBannerImage: string;
|
|
180
|
+
enabled?: boolean;
|
|
181
|
+
}
|
|
182
|
+
interface SubCategorySection {
|
|
183
|
+
type: 'sub-categories';
|
|
184
|
+
id: number;
|
|
185
|
+
title: string;
|
|
186
|
+
category?: any;
|
|
187
|
+
enabled?: boolean;
|
|
188
|
+
}
|
|
189
|
+
interface PreFooterContent {
|
|
190
|
+
id: string;
|
|
191
|
+
image: string;
|
|
192
|
+
title: string;
|
|
193
|
+
description: string;
|
|
194
|
+
}
|
|
195
|
+
interface PreFooter {
|
|
196
|
+
type: 'pre-footer';
|
|
197
|
+
id: string;
|
|
198
|
+
contents: PreFooterContent[];
|
|
199
|
+
enabled?: boolean;
|
|
200
|
+
}
|
|
201
|
+
interface CategoryHighlights {
|
|
202
|
+
type: 'category-highlights';
|
|
152
203
|
title?: string;
|
|
204
|
+
id?: string;
|
|
205
|
+
categories: any[];
|
|
153
206
|
enabled?: boolean;
|
|
154
|
-
[key: string]: any;
|
|
155
207
|
}
|
|
208
|
+
interface StoreReview {
|
|
209
|
+
type: 'store-review';
|
|
210
|
+
id: string;
|
|
211
|
+
title: string;
|
|
212
|
+
filter: string;
|
|
213
|
+
reviewsCount: number;
|
|
214
|
+
starColor: string;
|
|
215
|
+
autoPlayEnabled: boolean;
|
|
216
|
+
enabled?: boolean;
|
|
217
|
+
}
|
|
218
|
+
interface ProductHighlight {
|
|
219
|
+
type: 'product-highlight';
|
|
220
|
+
id: string;
|
|
221
|
+
title: string;
|
|
222
|
+
productSlug: string;
|
|
223
|
+
enabled?: boolean;
|
|
224
|
+
}
|
|
225
|
+
interface ImageWithText {
|
|
226
|
+
type: 'image-with-text';
|
|
227
|
+
id: string;
|
|
228
|
+
title: string;
|
|
229
|
+
content: string;
|
|
230
|
+
image: string;
|
|
231
|
+
showCta: boolean;
|
|
232
|
+
ctaText: string;
|
|
233
|
+
ctaLink: string;
|
|
234
|
+
enabled?: boolean;
|
|
235
|
+
}
|
|
236
|
+
interface Collections {
|
|
237
|
+
type: 'collections';
|
|
238
|
+
id: string;
|
|
239
|
+
title: string;
|
|
240
|
+
slug: string;
|
|
241
|
+
items: string[];
|
|
242
|
+
enabled?: boolean;
|
|
243
|
+
}
|
|
244
|
+
type SectionType = 'product-collection' | 'categories' | 'banner' | 'sub-categories' | 'pre-footer' | 'category-highlights' | 'store-review' | 'product-highlight' | 'image-with-text' | 'collections';
|
|
245
|
+
type Section = ProductCollection | CategorySection | Banner | PreFooter | StoreReview | CategoryHighlights | SubCategorySection | ProductHighlight | ImageWithText | Collections;
|
|
246
|
+
/** @deprecated Use `Section` instead */
|
|
247
|
+
type SectionItem = Section;
|
|
156
248
|
|
|
157
249
|
interface EditorProviderProps {
|
|
158
250
|
/**
|
|
@@ -165,6 +257,9 @@ interface EditorProviderProps {
|
|
|
165
257
|
* Default: "*" (accepts all — set NEXT_PUBLIC_EDITOR_ORIGIN in production!)
|
|
166
258
|
*/
|
|
167
259
|
editorOrigin?: string;
|
|
260
|
+
callBacks?: {
|
|
261
|
+
onChanges?: (config: LandingPageConfig) => void;
|
|
262
|
+
};
|
|
168
263
|
/**
|
|
169
264
|
* Optional: custom CSS variable mapping. Override if your theme uses
|
|
170
265
|
* different CSS property names than the default Starter Theme.
|
|
@@ -193,7 +288,7 @@ interface EditorProviderProps {
|
|
|
193
288
|
* @param props.cssVarOverrides - Optional map to override default CSS variable name mappings.
|
|
194
289
|
* @param props.children - Child components that consume editor context via hooks.
|
|
195
290
|
*/
|
|
196
|
-
declare function EditorProvider({ initialConfig, editorOrigin, cssVarOverrides, children, }: EditorProviderProps): react_jsx_runtime.JSX.Element;
|
|
291
|
+
declare function EditorProvider({ initialConfig, editorOrigin, cssVarOverrides, children, callBacks, }: EditorProviderProps): react_jsx_runtime.JSX.Element;
|
|
197
292
|
|
|
198
293
|
/**
|
|
199
294
|
* Shape of the value provided by EditorContext.
|
|
@@ -241,7 +336,7 @@ declare function useHeroConfig(): HeroConfig | null;
|
|
|
241
336
|
* Memoized to prevent unnecessary re-renders when sections haven't changed.
|
|
242
337
|
* Returns an empty array when used outside of EditorProvider.
|
|
243
338
|
*/
|
|
244
|
-
declare function useSections():
|
|
339
|
+
declare function useSections(): Section[];
|
|
245
340
|
|
|
246
341
|
/**
|
|
247
342
|
* Finds and returns a single section by its unique ID from the sections array.
|
|
@@ -250,7 +345,7 @@ declare function useSections(): SectionItem[];
|
|
|
250
345
|
*
|
|
251
346
|
* @param sectionId - The unique ID of the section to find (e.g., "categories-7kvobkg2g").
|
|
252
347
|
*/
|
|
253
|
-
declare function useSectionById(sectionId: string):
|
|
348
|
+
declare function useSectionById(sectionId: string): Section | undefined;
|
|
254
349
|
|
|
255
350
|
/**
|
|
256
351
|
* Returns the navbar configuration (logo position, cart/wishlist toggles, ribbon bar, nav elements).
|
|
@@ -401,7 +496,7 @@ type EditorMessage = {
|
|
|
401
496
|
} | {
|
|
402
497
|
type: 'editor:section-add';
|
|
403
498
|
payload: {
|
|
404
|
-
section:
|
|
499
|
+
section: Section;
|
|
405
500
|
position: number;
|
|
406
501
|
};
|
|
407
502
|
} | {
|
|
@@ -419,7 +514,7 @@ type EditorMessage = {
|
|
|
419
514
|
type: 'editor:section-update';
|
|
420
515
|
payload: {
|
|
421
516
|
sectionId: string;
|
|
422
|
-
data: Partial<
|
|
517
|
+
data: Partial<Section>;
|
|
423
518
|
};
|
|
424
519
|
} | {
|
|
425
520
|
type: 'editor:navbar-update';
|
|
@@ -553,4 +648,4 @@ declare const CSS_VAR_MAP: Record<string, string>;
|
|
|
553
648
|
*/
|
|
554
649
|
declare function syncCSSVars(colorScheme: ColorSchemeConfig, fontStyles: FontStylesConfig, overrides?: Record<string, string>): void;
|
|
555
650
|
|
|
556
|
-
export { CSS_VAR_MAP, type ColorSchemeConfig, EditorContext, type EditorContextValue, type EditorMessage, EditorProvider, type EditorProviderProps, type FontConfig, type FontStylesConfig, type FooterConfig, type HeroConfig, type LandingPageConfig, type MetaData, type NavElement, type NavbarConfig, type RibbonBarConfig, type SectionItem, type SectionPosition, SectionWrapper, type SectionWrapperProps, type SliderSlide, type SocialLinksConfig, type StoreMessage, type ThemeInfo, syncCSSVars, useBranding, useColorScheme, useEditorMode, useFontStyles, useFooterConfig, useHeroConfig, useLandingConfig, useNavbarConfig, useSectionById, useSections, useSocialLinks };
|
|
651
|
+
export { type Banner, CSS_VAR_MAP, type CategoryHighlights, type CategorySection, type Collections, type ColorSchemeConfig, EditorContext, type EditorContextValue, type EditorMessage, EditorProvider, type EditorProviderProps, type FilterOption, type FilterType, type FontConfig, type FontStylesConfig, type FooterConfig, type HeroConfig, type ImageWithText, type LandingPageConfig, type MetaData, type NavElement, type NavbarConfig, type PreFooter, type PreFooterContent, type ProductCollection, type ProductHighlight, type RibbonBarConfig, type Section, type SectionFilters, type SectionItem, type SectionPosition, type SectionType, SectionWrapper, type SectionWrapperProps, type SliderSlide, type SocialLinksConfig, type StoreMessage, type StoreReview, type SubCategorySection, type ThemeInfo, syncCSSVars, useBranding, useColorScheme, useEditorMode, useFontStyles, useFooterConfig, useHeroConfig, useLandingConfig, useNavbarConfig, useSectionById, useSections, useSocialLinks };
|
package/dist/index.d.ts
CHANGED
|
@@ -94,6 +94,7 @@ interface ColorSchemeConfig {
|
|
|
94
94
|
interface HeroConfig {
|
|
95
95
|
cta: string;
|
|
96
96
|
title: string;
|
|
97
|
+
description: string;
|
|
97
98
|
ctaLink: string;
|
|
98
99
|
showCTA: boolean;
|
|
99
100
|
heroImage: string;
|
|
@@ -109,11 +110,11 @@ interface SliderSlide {
|
|
|
109
110
|
id: string;
|
|
110
111
|
cta: string;
|
|
111
112
|
title: string;
|
|
113
|
+
description: string;
|
|
112
114
|
ctaLink: string;
|
|
113
115
|
bannerImage: string;
|
|
114
|
-
bannerImageMobile
|
|
115
|
-
|
|
116
|
-
showContents: boolean;
|
|
116
|
+
bannerImageMobile: string;
|
|
117
|
+
showContents?: boolean;
|
|
117
118
|
}
|
|
118
119
|
interface FooterConfig {
|
|
119
120
|
showSocialLinks: boolean;
|
|
@@ -140,19 +141,110 @@ interface FontConfig {
|
|
|
140
141
|
label?: string;
|
|
141
142
|
value?: string;
|
|
142
143
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
* Each type has different additional fields — we use [key: string]: any
|
|
147
|
-
* because section types are extensible and vary by theme.
|
|
148
|
-
*/
|
|
149
|
-
interface SectionItem {
|
|
144
|
+
type FilterType = 'category' | 'badge' | 'title';
|
|
145
|
+
type FilterOption = 'select' | 'equals' | 'contain' | 'startWith' | 'endWith';
|
|
146
|
+
interface SectionFilters {
|
|
150
147
|
id: string;
|
|
151
|
-
type:
|
|
148
|
+
type: FilterType;
|
|
149
|
+
label: string;
|
|
150
|
+
condition: FilterOption;
|
|
151
|
+
value: string | string[];
|
|
152
|
+
}
|
|
153
|
+
interface ProductCollection {
|
|
154
|
+
type: 'product-collection';
|
|
155
|
+
title?: string;
|
|
156
|
+
filters?: SectionFilters[];
|
|
157
|
+
id: string;
|
|
158
|
+
row_count: number;
|
|
159
|
+
enabled?: boolean;
|
|
160
|
+
}
|
|
161
|
+
interface CategorySection {
|
|
162
|
+
type: 'categories';
|
|
163
|
+
title?: string;
|
|
164
|
+
id?: string;
|
|
165
|
+
categories?: any[];
|
|
166
|
+
selectedCategories?: string[];
|
|
167
|
+
enabled?: boolean;
|
|
168
|
+
}
|
|
169
|
+
interface Banner {
|
|
170
|
+
type: 'banner';
|
|
171
|
+
title: string;
|
|
172
|
+
description?: string;
|
|
173
|
+
bannerImage: string;
|
|
174
|
+
ctaText?: string;
|
|
175
|
+
ctaLink?: string;
|
|
176
|
+
id: string;
|
|
177
|
+
bannerLink: string;
|
|
178
|
+
showContents: boolean;
|
|
179
|
+
mobileBannerImage: string;
|
|
180
|
+
enabled?: boolean;
|
|
181
|
+
}
|
|
182
|
+
interface SubCategorySection {
|
|
183
|
+
type: 'sub-categories';
|
|
184
|
+
id: number;
|
|
185
|
+
title: string;
|
|
186
|
+
category?: any;
|
|
187
|
+
enabled?: boolean;
|
|
188
|
+
}
|
|
189
|
+
interface PreFooterContent {
|
|
190
|
+
id: string;
|
|
191
|
+
image: string;
|
|
192
|
+
title: string;
|
|
193
|
+
description: string;
|
|
194
|
+
}
|
|
195
|
+
interface PreFooter {
|
|
196
|
+
type: 'pre-footer';
|
|
197
|
+
id: string;
|
|
198
|
+
contents: PreFooterContent[];
|
|
199
|
+
enabled?: boolean;
|
|
200
|
+
}
|
|
201
|
+
interface CategoryHighlights {
|
|
202
|
+
type: 'category-highlights';
|
|
152
203
|
title?: string;
|
|
204
|
+
id?: string;
|
|
205
|
+
categories: any[];
|
|
153
206
|
enabled?: boolean;
|
|
154
|
-
[key: string]: any;
|
|
155
207
|
}
|
|
208
|
+
interface StoreReview {
|
|
209
|
+
type: 'store-review';
|
|
210
|
+
id: string;
|
|
211
|
+
title: string;
|
|
212
|
+
filter: string;
|
|
213
|
+
reviewsCount: number;
|
|
214
|
+
starColor: string;
|
|
215
|
+
autoPlayEnabled: boolean;
|
|
216
|
+
enabled?: boolean;
|
|
217
|
+
}
|
|
218
|
+
interface ProductHighlight {
|
|
219
|
+
type: 'product-highlight';
|
|
220
|
+
id: string;
|
|
221
|
+
title: string;
|
|
222
|
+
productSlug: string;
|
|
223
|
+
enabled?: boolean;
|
|
224
|
+
}
|
|
225
|
+
interface ImageWithText {
|
|
226
|
+
type: 'image-with-text';
|
|
227
|
+
id: string;
|
|
228
|
+
title: string;
|
|
229
|
+
content: string;
|
|
230
|
+
image: string;
|
|
231
|
+
showCta: boolean;
|
|
232
|
+
ctaText: string;
|
|
233
|
+
ctaLink: string;
|
|
234
|
+
enabled?: boolean;
|
|
235
|
+
}
|
|
236
|
+
interface Collections {
|
|
237
|
+
type: 'collections';
|
|
238
|
+
id: string;
|
|
239
|
+
title: string;
|
|
240
|
+
slug: string;
|
|
241
|
+
items: string[];
|
|
242
|
+
enabled?: boolean;
|
|
243
|
+
}
|
|
244
|
+
type SectionType = 'product-collection' | 'categories' | 'banner' | 'sub-categories' | 'pre-footer' | 'category-highlights' | 'store-review' | 'product-highlight' | 'image-with-text' | 'collections';
|
|
245
|
+
type Section = ProductCollection | CategorySection | Banner | PreFooter | StoreReview | CategoryHighlights | SubCategorySection | ProductHighlight | ImageWithText | Collections;
|
|
246
|
+
/** @deprecated Use `Section` instead */
|
|
247
|
+
type SectionItem = Section;
|
|
156
248
|
|
|
157
249
|
interface EditorProviderProps {
|
|
158
250
|
/**
|
|
@@ -165,6 +257,9 @@ interface EditorProviderProps {
|
|
|
165
257
|
* Default: "*" (accepts all — set NEXT_PUBLIC_EDITOR_ORIGIN in production!)
|
|
166
258
|
*/
|
|
167
259
|
editorOrigin?: string;
|
|
260
|
+
callBacks?: {
|
|
261
|
+
onChanges?: (config: LandingPageConfig) => void;
|
|
262
|
+
};
|
|
168
263
|
/**
|
|
169
264
|
* Optional: custom CSS variable mapping. Override if your theme uses
|
|
170
265
|
* different CSS property names than the default Starter Theme.
|
|
@@ -193,7 +288,7 @@ interface EditorProviderProps {
|
|
|
193
288
|
* @param props.cssVarOverrides - Optional map to override default CSS variable name mappings.
|
|
194
289
|
* @param props.children - Child components that consume editor context via hooks.
|
|
195
290
|
*/
|
|
196
|
-
declare function EditorProvider({ initialConfig, editorOrigin, cssVarOverrides, children, }: EditorProviderProps): react_jsx_runtime.JSX.Element;
|
|
291
|
+
declare function EditorProvider({ initialConfig, editorOrigin, cssVarOverrides, children, callBacks, }: EditorProviderProps): react_jsx_runtime.JSX.Element;
|
|
197
292
|
|
|
198
293
|
/**
|
|
199
294
|
* Shape of the value provided by EditorContext.
|
|
@@ -241,7 +336,7 @@ declare function useHeroConfig(): HeroConfig | null;
|
|
|
241
336
|
* Memoized to prevent unnecessary re-renders when sections haven't changed.
|
|
242
337
|
* Returns an empty array when used outside of EditorProvider.
|
|
243
338
|
*/
|
|
244
|
-
declare function useSections():
|
|
339
|
+
declare function useSections(): Section[];
|
|
245
340
|
|
|
246
341
|
/**
|
|
247
342
|
* Finds and returns a single section by its unique ID from the sections array.
|
|
@@ -250,7 +345,7 @@ declare function useSections(): SectionItem[];
|
|
|
250
345
|
*
|
|
251
346
|
* @param sectionId - The unique ID of the section to find (e.g., "categories-7kvobkg2g").
|
|
252
347
|
*/
|
|
253
|
-
declare function useSectionById(sectionId: string):
|
|
348
|
+
declare function useSectionById(sectionId: string): Section | undefined;
|
|
254
349
|
|
|
255
350
|
/**
|
|
256
351
|
* Returns the navbar configuration (logo position, cart/wishlist toggles, ribbon bar, nav elements).
|
|
@@ -401,7 +496,7 @@ type EditorMessage = {
|
|
|
401
496
|
} | {
|
|
402
497
|
type: 'editor:section-add';
|
|
403
498
|
payload: {
|
|
404
|
-
section:
|
|
499
|
+
section: Section;
|
|
405
500
|
position: number;
|
|
406
501
|
};
|
|
407
502
|
} | {
|
|
@@ -419,7 +514,7 @@ type EditorMessage = {
|
|
|
419
514
|
type: 'editor:section-update';
|
|
420
515
|
payload: {
|
|
421
516
|
sectionId: string;
|
|
422
|
-
data: Partial<
|
|
517
|
+
data: Partial<Section>;
|
|
423
518
|
};
|
|
424
519
|
} | {
|
|
425
520
|
type: 'editor:navbar-update';
|
|
@@ -553,4 +648,4 @@ declare const CSS_VAR_MAP: Record<string, string>;
|
|
|
553
648
|
*/
|
|
554
649
|
declare function syncCSSVars(colorScheme: ColorSchemeConfig, fontStyles: FontStylesConfig, overrides?: Record<string, string>): void;
|
|
555
650
|
|
|
556
|
-
export { CSS_VAR_MAP, type ColorSchemeConfig, EditorContext, type EditorContextValue, type EditorMessage, EditorProvider, type EditorProviderProps, type FontConfig, type FontStylesConfig, type FooterConfig, type HeroConfig, type LandingPageConfig, type MetaData, type NavElement, type NavbarConfig, type RibbonBarConfig, type SectionItem, type SectionPosition, SectionWrapper, type SectionWrapperProps, type SliderSlide, type SocialLinksConfig, type StoreMessage, type ThemeInfo, syncCSSVars, useBranding, useColorScheme, useEditorMode, useFontStyles, useFooterConfig, useHeroConfig, useLandingConfig, useNavbarConfig, useSectionById, useSections, useSocialLinks };
|
|
651
|
+
export { type Banner, CSS_VAR_MAP, type CategoryHighlights, type CategorySection, type Collections, type ColorSchemeConfig, EditorContext, type EditorContextValue, type EditorMessage, EditorProvider, type EditorProviderProps, type FilterOption, type FilterType, type FontConfig, type FontStylesConfig, type FooterConfig, type HeroConfig, type ImageWithText, type LandingPageConfig, type MetaData, type NavElement, type NavbarConfig, type PreFooter, type PreFooterContent, type ProductCollection, type ProductHighlight, type RibbonBarConfig, type Section, type SectionFilters, type SectionItem, type SectionPosition, type SectionType, SectionWrapper, type SectionWrapperProps, type SliderSlide, type SocialLinksConfig, type StoreMessage, type StoreReview, type SubCategorySection, type ThemeInfo, syncCSSVars, useBranding, useColorScheme, useEditorMode, useFontStyles, useFooterConfig, useHeroConfig, useLandingConfig, useNavbarConfig, useSectionById, useSections, useSocialLinks };
|
package/dist/index.js
CHANGED
|
@@ -289,6 +289,7 @@ function syncCSSVars(colorScheme, fontStyles, overrides) {
|
|
|
289
289
|
const root = document.documentElement;
|
|
290
290
|
const varMap = overrides ? { ...CSS_VAR_MAP, ...overrides } : CSS_VAR_MAP;
|
|
291
291
|
for (const [configKey, cssVar] of Object.entries(varMap)) {
|
|
292
|
+
if (!colorScheme) return;
|
|
292
293
|
const value = colorScheme[configKey];
|
|
293
294
|
if (value !== void 0 && value !== null && value !== "") {
|
|
294
295
|
root.style.setProperty(cssVar, value);
|
|
@@ -320,7 +321,8 @@ function EditorProvider({
|
|
|
320
321
|
initialConfig,
|
|
321
322
|
editorOrigin = "*",
|
|
322
323
|
cssVarOverrides,
|
|
323
|
-
children
|
|
324
|
+
children,
|
|
325
|
+
callBacks
|
|
324
326
|
}) {
|
|
325
327
|
const [isEditorMode, setIsEditorMode] = (0, import_react2.useState)(false);
|
|
326
328
|
const [config, dispatch] = (0, import_react2.useReducer)(configReducer, initialConfig);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/provider/EditorProvider.tsx","../src/provider/EditorContext.ts","../src/provider/config-reducer.ts","../src/css/css-var-sync.ts","../src/hooks/useEditorMode.ts","../src/hooks/useLandingConfig.ts","../src/hooks/useHeroConfig.ts","../src/hooks/useSections.ts","../src/hooks/useSectionById.ts","../src/hooks/useNavbarConfig.ts","../src/hooks/useFooterConfig.ts","../src/hooks/useColorScheme.ts","../src/hooks/useFontStyles.ts","../src/hooks/useBranding.ts","../src/hooks/useSocialLinks.ts","../src/components/SectionWrapper.tsx"],"sourcesContent":["// Provider\nexport { EditorProvider } from './provider/EditorProvider';\nexport type { EditorProviderProps } from './provider/EditorProvider';\nexport { EditorContext } from './provider/EditorContext';\nexport type { EditorContextValue } from './provider/EditorContext';\n\n// Hooks\nexport { useEditorMode } from './hooks/useEditorMode';\nexport { useLandingConfig } from './hooks/useLandingConfig';\nexport { useHeroConfig } from './hooks/useHeroConfig';\nexport { useSections } from './hooks/useSections';\nexport { useSectionById } from './hooks/useSectionById';\nexport { useNavbarConfig } from './hooks/useNavbarConfig';\nexport { useFooterConfig } from './hooks/useFooterConfig';\nexport { useColorScheme } from './hooks/useColorScheme';\nexport { useFontStyles } from './hooks/useFontStyles';\nexport { useBranding } from './hooks/useBranding';\nexport { useSocialLinks } from './hooks/useSocialLinks';\n\n// Components\nexport { SectionWrapper } from './components/SectionWrapper';\nexport type { SectionWrapperProps } from './components/SectionWrapper';\n\n// Types\nexport type {\n LandingPageConfig,\n ThemeInfo,\n HeroConfig,\n SectionItem,\n NavbarConfig,\n RibbonBarConfig,\n NavElement,\n FooterConfig,\n ColorSchemeConfig,\n FontStylesConfig,\n FontConfig,\n SocialLinksConfig,\n SliderSlide,\n} from './types/config';\nexport type { MetaData } from './types/meta';\nexport type {\n EditorMessage,\n StoreMessage,\n SectionPosition,\n} from './types/messages';\n\n// CSS utilities\nexport { CSS_VAR_MAP, syncCSSVars } from './css/css-var-sync';\n","'use client';\n\nimport React, { useReducer, useEffect, useRef, useState, useMemo } from 'react';\nimport { LandingPageConfig } from '../types/config';\nimport { EditorMessage, StoreMessage, SectionPosition } from '../types/messages';\nimport { EditorContext, EditorContextValue } from './EditorContext';\nimport { configReducer, toReducerAction } from './config-reducer';\nimport { syncCSSVars } from '../css/css-var-sync';\n\nexport interface EditorProviderProps {\n /**\n * The config fetched by the Server Component from GET /store/store_settings/.\n * Must be the EXACT JSON shape — no transformation needed.\n */\n initialConfig: LandingPageConfig;\n\n /**\n * Allowed origin for postMessage. Set to the editor SPA domain in production.\n * Default: \"*\" (accepts all — set NEXT_PUBLIC_EDITOR_ORIGIN in production!)\n */\n editorOrigin?: string;\n\n /**\n * Optional: custom CSS variable mapping. Override if your theme uses\n * different CSS property names than the default Starter Theme.\n * Map keys are color_scheme field names → values are CSS property names.\n * Example: { primary: '--brand-color', secondary: '--accent-color' }\n */\n cssVarOverrides?: Record<string, string>;\n\n children: React.ReactNode;\n}\n\n/**\n * Core provider component that enables Visual Editor Mode in Snapstore themes.\n *\n * In normal mode (customer visiting the store), this provider is dormant — it passes\n * the server-fetched initialConfig through context unchanged with zero runtime overhead.\n *\n * In editor mode (?editor=true + loaded inside an iframe), it:\n * 1. Activates editor mode and adds 'editor-mode-active' class to <body>\n * 2. Listens for postMessage events from the parent editor SPA\n * 3. Dispatches config changes through the reducer for immutable state updates\n * 4. Syncs CSS custom properties on <html> when colors/fonts change\n * 5. Reports section DOM positions to the editor for overlay alignment\n * 6. Injects editor-specific CSS (hover outlines, disabled interactions)\n *\n * @param props.initialConfig - The full LandingPageConfig from GET /store/landing_page/.\n * @param props.editorOrigin - Allowed postMessage origin. Defaults to \"*\"; set in production.\n * @param props.cssVarOverrides - Optional map to override default CSS variable name mappings.\n * @param props.children - Child components that consume editor context via hooks.\n */\nexport function EditorProvider({\n initialConfig,\n editorOrigin = '*',\n cssVarOverrides,\n children,\n}: EditorProviderProps) {\n const [isEditorMode, setIsEditorMode] = useState(false);\n const [config, dispatch] = useReducer(configReducer, initialConfig);\n const positionTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const prevColorRef = useRef(initialConfig.color_scheme);\n const prevFontRef = useRef(initialConfig.font_styles);\n\n // ── 1. Detect editor mode ──\n useEffect(() => {\n if (typeof window === 'undefined') return;\n const params = new URLSearchParams(window.location.search);\n const inIframe = window.self !== window.top;\n if (inIframe && params.get('editor') === 'true') {\n setIsEditorMode(true);\n document.body.classList.add('editor-mode-active');\n }\n return () => {\n document.body.classList.remove('editor-mode-active');\n };\n }, []);\n\n // ── 2. Listen for postMessages ──\n useEffect(() => {\n if (!isEditorMode) return;\n\n const handler = (event: MessageEvent) => {\n if (editorOrigin !== '*' && event.origin !== editorOrigin) return;\n const msg = event.data as EditorMessage;\n if (!msg?.type?.startsWith('editor:')) return;\n\n // Navigation is handled outside reducer (side effect)\n if (msg.type === 'editor:navigate') {\n const url = new URL(msg.payload.url, window.location.origin);\n url.searchParams.set('editor', 'true');\n window.location.href = url.toString();\n return;\n }\n\n // Highlight is a DOM operation, not a state change\n if (msg.type === 'editor:highlight-section') {\n document.querySelectorAll('[data-section-id]').forEach(el => {\n el.classList.toggle(\n 'editor-section-highlight',\n el.getAttribute('data-section-id') === msg.payload.sectionId\n );\n });\n return;\n }\n\n // Everything else goes through the reducer\n const action = toReducerAction(msg);\n if (action) dispatch(action);\n };\n\n window.addEventListener('message', handler);\n return () => window.removeEventListener('message', handler);\n }, [isEditorMode, editorOrigin]);\n\n // ── 3. Send store:ready ──\n useEffect(() => {\n if (!isEditorMode) return;\n const timer = setTimeout(() => {\n sendToEditor({\n type: 'store:ready',\n payload: { sections: getSectionPositions() },\n });\n }, 600);\n return () => clearTimeout(timer);\n }, [isEditorMode]);\n\n // ── 4. Sync CSS vars when color_scheme or font_styles change ──\n useEffect(() => {\n if (!isEditorMode) return;\n if (\n config.color_scheme !== prevColorRef.current ||\n config.font_styles !== prevFontRef.current\n ) {\n syncCSSVars(config.color_scheme, config.font_styles, cssVarOverrides);\n prevColorRef.current = config.color_scheme;\n prevFontRef.current = config.font_styles;\n }\n }, [isEditorMode, config.color_scheme, config.font_styles, cssVarOverrides]);\n\n // ── 5. Report section positions after re-render ──\n useEffect(() => {\n if (!isEditorMode) return;\n if (positionTimerRef.current) clearTimeout(positionTimerRef.current);\n positionTimerRef.current = setTimeout(() => {\n sendToEditor({\n type: 'store:sections-updated',\n payload: { sections: getSectionPositions() },\n });\n }, 300);\n }, [config.sections, config.hero, isEditorMode]);\n\n // ── Context value ──\n const value = useMemo<EditorContextValue>(\n () => ({ isEditorMode, config }),\n [isEditorMode, config]\n );\n\n return (\n <EditorContext.Provider value={value}>\n {isEditorMode && <EditorStylesInline />}\n {children}\n </EditorContext.Provider>\n );\n}\n\n// ── Helpers ──\n\n/**\n * Sends a message from the store iframe to the parent editor SPA via postMessage.\n * No-ops silently if not running in an iframe or if window is undefined (SSR).\n *\n * @param message - The StoreMessage to send (e.g., store:ready, store:section-clicked).\n */\nfunction sendToEditor(message: StoreMessage) {\n if (typeof window === 'undefined' || window.self === window.top) return;\n window.parent.postMessage(message, '*');\n}\n\n/**\n * Queries the DOM for all elements with a `data-section-id` attribute (rendered by SectionWrapper)\n * and returns their current bounding rectangles. The editor SPA uses these positions to align\n * its overlay UI (selection outlines, drag handles) with the preview iframe content.\n *\n * @returns An array of SectionPosition objects with id, type, and bounding rect for each section.\n */\nfunction getSectionPositions(): SectionPosition[] {\n return Array.from(document.querySelectorAll('[data-section-id]')).map(el => ({\n id: el.getAttribute('data-section-id')!,\n type: el.getAttribute('data-section-type') || '',\n rect: el.getBoundingClientRect(),\n }));\n}\n\n/**\n * Renders inline <style> tag with editor-mode-only CSS rules. Only mounted when editor mode is active.\n * These styles:\n * 1. Add hover/highlight outlines on section wrappers for visual feedback\n * 2. Dim disabled sections (opacity 0.35) so merchants can see they're toggled off\n * 3. Disable pointer events on all interactive elements (links, buttons, forms, inputs)\n * to prevent accidental navigation while editing\n * 4. Re-enable pointer events on editor click overlays so section clicks still register\n */\nfunction EditorStylesInline() {\n return (\n <style>{`\n [data-section-id] {\n position: relative;\n transition: outline 0.15s ease;\n }\n [data-section-id]:hover {\n outline: 2px solid rgba(59, 130, 246, 0.5);\n outline-offset: -2px;\n cursor: pointer;\n }\n .editor-section-highlight {\n outline: 2px solid #3b82f6 !important;\n outline-offset: -2px;\n }\n .editor-section-disabled {\n opacity: 0.35;\n }\n .editor-mode-active a,\n .editor-mode-active button:not([data-editor-control]),\n .editor-mode-active input,\n .editor-mode-active select,\n .editor-mode-active form,\n .editor-mode-active textarea {\n pointer-events: none !important;\n }\n [data-section-id] > .editor-click-overlay {\n pointer-events: auto !important;\n }\n `}</style>\n );\n}\n","'use client';\n\nimport { createContext } from 'react';\nimport { LandingPageConfig } from '../types/config';\n\n/**\n * Shape of the value provided by EditorContext.\n * - isEditorMode: Whether the store is running inside the editor iframe with ?editor=true.\n * - config: The current LandingPageConfig — either the original server-fetched config\n * (normal mode) or a live-updating copy managed by the config reducer (editor mode).\n */\nexport interface EditorContextValue {\n isEditorMode: boolean;\n config: LandingPageConfig;\n}\n\n/**\n * React Context that holds the editor state. Consumed by all useXxxConfig hooks.\n * Defaults to null when no EditorProvider is present in the component tree.\n */\nexport const EditorContext = createContext<EditorContextValue | null>(null);\n","import {\n LandingPageConfig,\n SectionItem,\n HeroConfig,\n SliderSlide,\n NavElement,\n RibbonBarConfig,\n ColorSchemeConfig,\n FooterConfig,\n FontStylesConfig,\n SocialLinksConfig,\n} from '../types/config';\nimport { EditorMessage } from '../types/messages';\n\n// ── Action types ──\n\nexport type EditorAction =\n | { type: 'FULL_REPLACE'; config: LandingPageConfig }\n | { type: 'UPDATE_PATH'; path: string; value: any }\n | { type: 'HERO_UPDATE'; data: Partial<HeroConfig> }\n | { type: 'HERO_SLIDE_ADD'; slide: SliderSlide; position: number }\n | { type: 'HERO_SLIDE_REMOVE'; slideId: string }\n | { type: 'HERO_SLIDES_REORDER'; slideIds: string[] }\n | { type: 'HERO_SLIDE_UPDATE'; slideId: string; data: Partial<SliderSlide> }\n | { type: 'SECTIONS_REORDER'; sectionIds: string[] }\n | { type: 'SECTION_ADD'; section: SectionItem; position: number }\n | { type: 'SECTION_REMOVE'; sectionId: string }\n | { type: 'SECTION_TOGGLE'; sectionId: string; enabled: boolean }\n | { type: 'SECTION_UPDATE'; sectionId: string; data: Partial<SectionItem> }\n | { type: 'NAVBAR_UPDATE'; data: Partial<LandingPageConfig['navbar']> }\n | { type: 'NAVBAR_RIBBON_UPDATE'; data: Partial<RibbonBarConfig> }\n | { type: 'NAVBAR_RIBBON_MSG_ADD'; message: { link: string; message: string }; position: number }\n | { type: 'NAVBAR_RIBBON_MSG_REMOVE'; index: number }\n | { type: 'NAVBAR_RIBBON_MSGS_REORDER'; messages: Array<{ link: string; message: string }> }\n | { type: 'NAVBAR_ELEMENT_UPDATE'; key: string; data: Partial<NavElement> }\n | { type: 'NAVBAR_ELEMENT_ADD'; element: NavElement; position: number }\n | { type: 'NAVBAR_ELEMENT_REMOVE'; key: string }\n | { type: 'NAVBAR_ELEMENTS_REORDER'; elements: NavElement[] }\n | { type: 'FOOTER_UPDATE'; data: Partial<FooterConfig> }\n | { type: 'COLOR_SCHEME_UPDATE'; data: Partial<ColorSchemeConfig> }\n | { type: 'FONT_STYLES_UPDATE'; data: { body?: Partial<FontStylesConfig['body']>; heading?: Partial<FontStylesConfig['heading']> } }\n | { type: 'SOCIAL_LINKS_UPDATE'; data: Partial<SocialLinksConfig> }\n | { type: 'BRANDING_UPDATE'; data: Partial<Pick<LandingPageConfig, 'logo' | 'secondary_logo' | 'favicon' | 'store_name' | 'store_description'>> }\n | { type: 'ADVANCED_UPDATE'; data: Partial<Pick<LandingPageConfig, 'custom_css' | 'custom_js' | 'start_head_tag' | 'end_head_tag' | 'start_body_tag' | 'end_body_tag' | 'google_tag_manager_id' | 'facebook_pixel_id'>> };\n\n// ── Message → Action mapper ──\n\n/**\n * Converts an incoming EditorMessage (from postMessage) into a reducer-compatible EditorAction.\n * Maps each `editor:*` message type to its corresponding internal action type.\n * Returns null for unrecognized message types, which are silently ignored.\n *\n * @param msg - The postMessage event data received from the editor SPA.\n * @returns The corresponding EditorAction to dispatch, or null if the message type is unknown.\n */\nexport function toReducerAction(msg: EditorMessage): EditorAction | null {\n switch (msg.type) {\n case 'editor:init':\n case 'editor:full-replace':\n return { type: 'FULL_REPLACE', config: msg.payload.config };\n case 'editor:update':\n return { type: 'UPDATE_PATH', path: msg.payload.path, value: msg.payload.value };\n case 'editor:hero-update':\n return { type: 'HERO_UPDATE', data: msg.payload };\n case 'editor:hero-slide-add':\n return { type: 'HERO_SLIDE_ADD', slide: msg.payload.slide, position: msg.payload.position };\n case 'editor:hero-slide-remove':\n return { type: 'HERO_SLIDE_REMOVE', slideId: msg.payload.slideId };\n case 'editor:hero-slides-reorder':\n return { type: 'HERO_SLIDES_REORDER', slideIds: msg.payload.slideIds };\n case 'editor:hero-slide-update':\n return { type: 'HERO_SLIDE_UPDATE', slideId: msg.payload.slideId, data: msg.payload.data };\n case 'editor:sections-reorder':\n return { type: 'SECTIONS_REORDER', sectionIds: msg.payload.sectionIds };\n case 'editor:section-add':\n return { type: 'SECTION_ADD', section: msg.payload.section, position: msg.payload.position };\n case 'editor:section-remove':\n return { type: 'SECTION_REMOVE', sectionId: msg.payload.sectionId };\n case 'editor:section-toggle':\n return { type: 'SECTION_TOGGLE', sectionId: msg.payload.sectionId, enabled: msg.payload.enabled };\n case 'editor:section-update':\n return { type: 'SECTION_UPDATE', sectionId: msg.payload.sectionId, data: msg.payload.data };\n case 'editor:navbar-update':\n return { type: 'NAVBAR_UPDATE', data: msg.payload };\n case 'editor:navbar-ribbon-update':\n return { type: 'NAVBAR_RIBBON_UPDATE', data: msg.payload };\n case 'editor:navbar-ribbon-message-add':\n return { type: 'NAVBAR_RIBBON_MSG_ADD', message: msg.payload.message, position: msg.payload.position };\n case 'editor:navbar-ribbon-message-remove':\n return { type: 'NAVBAR_RIBBON_MSG_REMOVE', index: msg.payload.index };\n case 'editor:navbar-ribbon-messages-reorder':\n return { type: 'NAVBAR_RIBBON_MSGS_REORDER', messages: msg.payload.messages };\n case 'editor:navbar-element-update':\n return { type: 'NAVBAR_ELEMENT_UPDATE', key: msg.payload.key, data: msg.payload.data };\n case 'editor:navbar-element-add':\n return { type: 'NAVBAR_ELEMENT_ADD', element: msg.payload.element, position: msg.payload.position };\n case 'editor:navbar-element-remove':\n return { type: 'NAVBAR_ELEMENT_REMOVE', key: msg.payload.key };\n case 'editor:navbar-elements-reorder':\n return { type: 'NAVBAR_ELEMENTS_REORDER', elements: msg.payload.elements };\n case 'editor:footer-update':\n return { type: 'FOOTER_UPDATE', data: msg.payload };\n case 'editor:color-scheme-update':\n return { type: 'COLOR_SCHEME_UPDATE', data: msg.payload };\n case 'editor:font-styles-update':\n return { type: 'FONT_STYLES_UPDATE', data: msg.payload };\n case 'editor:social-links-update':\n return { type: 'SOCIAL_LINKS_UPDATE', data: msg.payload };\n case 'editor:branding-update':\n return { type: 'BRANDING_UPDATE', data: msg.payload };\n case 'editor:advanced-update':\n return { type: 'ADVANCED_UPDATE', data: msg.payload };\n default:\n return null;\n }\n}\n\n// ── Reducer ──\n\n/**\n * Pure reducer that produces the next LandingPageConfig state from the current state and an action.\n * Handles all 25 action types covering hero, sections, navbar, footer, colors, fonts, branding,\n * social links, and advanced settings. All updates are immutable — returns a new object reference\n * on change, or the same reference if the action is unknown.\n *\n * @param state - The current LandingPageConfig state.\n * @param action - The EditorAction describing the state transition.\n * @returns A new LandingPageConfig with the action applied, or the same state if action is unknown.\n */\nexport function configReducer(state: LandingPageConfig, action: EditorAction): LandingPageConfig {\n switch (action.type) {\n case 'FULL_REPLACE':\n return action.config;\n\n case 'UPDATE_PATH':\n return setByPath(state, action.path, action.value);\n\n // ── Hero ──\n\n case 'HERO_UPDATE':\n return { ...state, hero: { ...state.hero, ...action.data } };\n\n case 'HERO_SLIDE_ADD': {\n const slides = [...state.hero.sliderSettings];\n slides.splice(action.position, 0, action.slide);\n return { ...state, hero: { ...state.hero, sliderSettings: slides } };\n }\n\n case 'HERO_SLIDE_REMOVE':\n return {\n ...state,\n hero: {\n ...state.hero,\n sliderSettings: state.hero.sliderSettings.filter(s => s.id !== action.slideId),\n },\n };\n\n case 'HERO_SLIDES_REORDER': {\n const reordered = action.slideIds\n .map(id => state.hero.sliderSettings.find(s => s.id === id))\n .filter(Boolean) as SliderSlide[];\n return { ...state, hero: { ...state.hero, sliderSettings: reordered } };\n }\n\n case 'HERO_SLIDE_UPDATE':\n return {\n ...state,\n hero: {\n ...state.hero,\n sliderSettings: state.hero.sliderSettings.map(s =>\n s.id === action.slideId ? { ...s, ...action.data } : s\n ),\n },\n };\n\n // ── Sections ──\n\n case 'SECTIONS_REORDER': {\n const reordered = action.sectionIds\n .map(id => state.sections.find(s => s.id === id))\n .filter(Boolean) as SectionItem[];\n return { ...state, sections: reordered };\n }\n\n case 'SECTION_ADD': {\n const sections = [...state.sections];\n sections.splice(action.position, 0, action.section);\n return { ...state, sections };\n }\n\n case 'SECTION_REMOVE':\n return { ...state, sections: state.sections.filter(s => s.id !== action.sectionId) };\n\n case 'SECTION_TOGGLE':\n return {\n ...state,\n sections: state.sections.map(s =>\n s.id === action.sectionId ? { ...s, enabled: action.enabled } : s\n ),\n };\n\n case 'SECTION_UPDATE':\n return {\n ...state,\n sections: state.sections.map(s =>\n s.id === action.sectionId ? { ...s, ...action.data } : s\n ),\n };\n\n // ── Navbar ──\n\n case 'NAVBAR_UPDATE': {\n const { ribbonbar, navElements, ...rest } = action.data;\n let navbar = { ...state.navbar, ...rest };\n if (ribbonbar) navbar = { ...navbar, ribbonbar: { ...navbar.ribbonbar, ...ribbonbar } };\n if (navElements) navbar = { ...navbar, navElements };\n return { ...state, navbar };\n }\n\n case 'NAVBAR_RIBBON_UPDATE':\n return {\n ...state,\n navbar: {\n ...state.navbar,\n ribbonbar: { ...state.navbar.ribbonbar, ...action.data },\n },\n };\n\n case 'NAVBAR_RIBBON_MSG_ADD': {\n const messages = [...state.navbar.ribbonbar.messages];\n messages.splice(action.position, 0, action.message);\n return {\n ...state,\n navbar: {\n ...state.navbar,\n ribbonbar: { ...state.navbar.ribbonbar, messages },\n },\n };\n }\n\n case 'NAVBAR_RIBBON_MSG_REMOVE': {\n const messages = state.navbar.ribbonbar.messages.filter((_, i) => i !== action.index);\n return {\n ...state,\n navbar: {\n ...state.navbar,\n ribbonbar: { ...state.navbar.ribbonbar, messages },\n },\n };\n }\n\n case 'NAVBAR_RIBBON_MSGS_REORDER':\n return {\n ...state,\n navbar: {\n ...state.navbar,\n ribbonbar: { ...state.navbar.ribbonbar, messages: action.messages },\n },\n };\n\n case 'NAVBAR_ELEMENT_UPDATE':\n return {\n ...state,\n navbar: {\n ...state.navbar,\n navElements: state.navbar.navElements.map(el =>\n el.key === action.key ? { ...el, ...action.data } : el\n ),\n },\n };\n\n case 'NAVBAR_ELEMENT_ADD': {\n const navElements = [...state.navbar.navElements];\n navElements.splice(action.position, 0, action.element);\n return { ...state, navbar: { ...state.navbar, navElements } };\n }\n\n case 'NAVBAR_ELEMENT_REMOVE':\n return {\n ...state,\n navbar: {\n ...state.navbar,\n navElements: state.navbar.navElements.filter(el => el.key !== action.key),\n },\n };\n\n case 'NAVBAR_ELEMENTS_REORDER':\n return { ...state, navbar: { ...state.navbar, navElements: action.elements } };\n\n // ── Top-level ──\n\n case 'FOOTER_UPDATE':\n return { ...state, footer: { ...state.footer, ...action.data } };\n\n case 'COLOR_SCHEME_UPDATE':\n return { ...state, color_scheme: { ...state.color_scheme, ...action.data } };\n\n case 'FONT_STYLES_UPDATE': {\n const font_styles = { ...state.font_styles };\n if (action.data.body) font_styles.body = { ...font_styles.body, ...action.data.body };\n if (action.data.heading) font_styles.heading = { ...font_styles.heading, ...action.data.heading };\n return { ...state, font_styles };\n }\n\n case 'SOCIAL_LINKS_UPDATE':\n return { ...state, social_links: { ...state.social_links, ...action.data } };\n\n case 'BRANDING_UPDATE':\n return { ...state, ...action.data };\n\n case 'ADVANCED_UPDATE':\n return { ...state, ...action.data };\n\n default:\n return state;\n }\n}\n\n// ── Helpers ──\n\n/**\n * Immutably sets a value at a dot-notation path within a nested object.\n * Creates shallow copies at each level of nesting to preserve immutability.\n * If intermediate keys don't exist, empty objects are created.\n *\n * @param obj - The source object to update.\n * @param path - Dot-notation path (e.g., \"hero.title\" or \"navbar.ribbonbar.animation\").\n * @param value - The value to set at the specified path.\n * @returns A new object with the value set at the given path.\n *\n * @example\n * setByPath({ hero: { title: 'Old' } }, 'hero.title', 'New')\n * // => { hero: { title: 'New' } }\n */\nfunction setByPath(obj: any, path: string, value: any): any {\n const keys = path.split('.');\n if (keys.length === 1) return { ...obj, [keys[0]]: value };\n const [head, ...tail] = keys;\n return { ...obj, [head]: setByPath(obj[head] ?? {}, tail.join('.'), value) };\n}\n","import { ColorSchemeConfig, FontStylesConfig } from '../types/config';\n\n/**\n * Default mapping: color_scheme field name → CSS custom property name.\n * These match what app/layout.tsx injects on <html style=\"...\">.\n *\n * VERIFY against the actual layout.tsx in your theme!\n * If your theme uses --brand-primary instead of --primary, pass\n * cssVarOverrides to EditorProvider.\n */\nexport const CSS_VAR_MAP: Record<string, string> = {\n primary: '--primary',\n secondary: '--secondary',\n btnText: '--btn-text',\n textPrimary: '--text-primary',\n textSecondary: '--text-secondary',\n bodyBackground: '--bg-primary',\n bodyBackground1: '--bg-primary-smoke',\n bodyBackgroundSecondary: '--bg-secondary-color',\n bodyBackgroundDark: '--bg-dark',\n borderBackground: '--bg-border',\n headerbg: '--header-bg',\n textColor: '--text-color',\n footerBgColor: '--footer-bg',\n footerTextColor: '--footer-text',\n};\n\n/**\n * Updates CSS custom properties on document.documentElement (<html>).\n * Called by EditorProvider when color_scheme or font_styles change.\n *\n * This overwrites the same vars that layout.tsx set on initial SSR,\n * so all SCSS that references var(--primary) etc. updates immediately.\n */\nexport function syncCSSVars(\n colorScheme: ColorSchemeConfig,\n fontStyles: FontStylesConfig,\n overrides?: Record<string, string>\n) {\n const root = document.documentElement;\n const varMap = overrides ? { ...CSS_VAR_MAP, ...overrides } : CSS_VAR_MAP;\n\n // Sync colors\n for (const [configKey, cssVar] of Object.entries(varMap)) {\n const value = (colorScheme as Record<string, any>)[configKey];\n if (value !== undefined && value !== null && value !== '') {\n root.style.setProperty(cssVar, value);\n }\n }\n\n // Sync fonts\n if (fontStyles?.heading) {\n root.style.setProperty('--heading-font', `'${fontStyles.heading.font_family}'`);\n root.style.setProperty('--heading-weight', String(fontStyles.heading.font_weight));\n loadGoogleFont(fontStyles.heading.font_url);\n }\n if (fontStyles?.body) {\n root.style.setProperty('--body-font', `'${fontStyles.body.font_family}'`);\n root.style.setProperty('--body-weight', String(fontStyles.body.font_weight));\n loadGoogleFont(fontStyles.body.font_url);\n }\n}\n\n/** Load a Google Font by injecting a <link> tag. Deduplicates. */\nfunction loadGoogleFont(url: string) {\n if (!url) return;\n if (document.querySelector(`link[href=\"${url}\"]`)) return;\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n document.head.appendChild(link);\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns whether the store is currently running in editor mode.\n * Editor mode is active when the page is loaded inside an iframe with ?editor=true.\n * Returns { isEditorMode: false } when used outside of EditorProvider.\n */\nexport function useEditorMode(): { isEditorMode: boolean } {\n const ctx = useContext(EditorContext);\n return { isEditorMode: ctx?.isEditorMode ?? false };\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\nimport { LandingPageConfig } from '../types/config';\n\n/**\n * Returns the full LandingPageConfig object from EditorContext.\n * In normal mode, this is the original server-fetched config.\n * In editor mode, this is the live-updating copy that reflects changes from the editor SPA.\n * Returns null when used outside of EditorProvider.\n */\nexport function useLandingConfig(): LandingPageConfig | null {\n return useContext(EditorContext)?.config ?? null;\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\nimport { HeroConfig } from '../types/config';\n\n/**\n * Returns the hero banner configuration (title, CTA, images, slider settings).\n * Updates live in editor mode when the editor SPA sends hero changes.\n * Returns null when used outside of EditorProvider.\n */\nexport function useHeroConfig(): HeroConfig | null {\n return useContext(EditorContext)?.config?.hero ?? null;\n}\n","'use client';\n\nimport { useContext, useMemo } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\nimport { SectionItem } from '../types/config';\n\n/**\n * Returns the ordered array of landing page sections from the config.\n * Reflects live reordering, additions, removals, and toggles from the editor SPA.\n * Memoized to prevent unnecessary re-renders when sections haven't changed.\n * Returns an empty array when used outside of EditorProvider.\n */\nexport function useSections(): SectionItem[] {\n const ctx = useContext(EditorContext);\n return useMemo(() => ctx?.config?.sections ?? [], [ctx?.config?.sections]);\n}\n","'use client';\n\nimport { useContext, useMemo } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\nimport { SectionItem } from '../types/config';\n\n/**\n * Finds and returns a single section by its unique ID from the sections array.\n * Memoized to avoid re-computing on every render unless the sections array changes.\n * Returns undefined if no section with the given ID exists.\n *\n * @param sectionId - The unique ID of the section to find (e.g., \"categories-7kvobkg2g\").\n */\nexport function useSectionById(sectionId: string): SectionItem | undefined {\n const ctx = useContext(EditorContext);\n return useMemo(\n () => ctx?.config?.sections.find(s => s.id === sectionId),\n [ctx?.config?.sections, sectionId]\n );\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns the navbar configuration (logo position, cart/wishlist toggles, ribbon bar, nav elements).\n * Updates live in editor mode when the editor SPA sends navbar changes.\n * Returns null when used outside of EditorProvider.\n */\nexport function useNavbarConfig() {\n return useContext(EditorContext)?.config?.navbar ?? null;\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns the footer configuration (social links visibility, contact details, branding toggles).\n * Updates live in editor mode when the editor SPA sends footer changes.\n * Returns null when used outside of EditorProvider.\n */\nexport function useFooterConfig() {\n return useContext(EditorContext)?.config?.footer ?? null;\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns the color scheme configuration (primary, secondary, background, text, footer colors).\n * When these values change in editor mode, EditorProvider also syncs CSS custom properties\n * on <html> for instant visual updates across all SCSS-styled components.\n * Returns null when used outside of EditorProvider.\n */\nexport function useColorScheme() {\n return useContext(EditorContext)?.config?.color_scheme ?? null;\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns the font styles configuration (body and heading font family, weight, and Google Font URL).\n * When fonts change in editor mode, EditorProvider syncs CSS custom properties and dynamically\n * loads the new Google Font via <link> tag injection.\n * Returns null when used outside of EditorProvider.\n */\nexport function useFontStyles() {\n return useContext(EditorContext)?.config?.font_styles ?? null;\n}\n","'use client';\n\nimport { useContext, useMemo } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns branding-related fields (logo, secondary_logo, favicon, store_name, store_description).\n * Memoized to only re-compute when one of these specific fields changes, avoiding unnecessary\n * re-renders when other parts of the config update.\n * Returns null when used outside of EditorProvider.\n */\nexport function useBranding() {\n const ctx = useContext(EditorContext);\n return useMemo(() => {\n if (!ctx?.config) return null;\n const c = ctx.config;\n return {\n logo: c.logo,\n secondary_logo: c.secondary_logo,\n favicon: c.favicon,\n store_name: c.store_name,\n store_description: c.store_description,\n };\n }, [\n ctx?.config?.logo,\n ctx?.config?.secondary_logo,\n ctx?.config?.favicon,\n ctx?.config?.store_name,\n ctx?.config?.store_description,\n ]);\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns social media link URLs (twitter, youtube, facebook, instagram).\n * Updates live in editor mode when the editor SPA sends social link changes.\n * Returns null when used outside of EditorProvider.\n */\nexport function useSocialLinks() {\n return useContext(EditorContext)?.config?.social_links ?? null;\n}\n","'use client';\n\nimport React from 'react';\nimport { useEditorMode } from '../hooks/useEditorMode';\n\nexport interface SectionWrapperProps {\n sectionId: string;\n sectionType: string;\n enabled?: boolean;\n className?: string;\n children: React.ReactNode;\n}\n\n/**\n * Wraps a landing page section with editor-aware behavior.\n *\n * In normal mode: renders children inside a <div> with data-section-id/data-section-type\n * attributes. If enabled=false, returns null (section is hidden from customers).\n *\n * In editor mode: always renders (even disabled sections, shown dimmed at 0.35 opacity).\n * Intercepts clicks and sends a 'store:section-clicked' postMessage to the parent editor SPA,\n * allowing the editor to open the settings panel for the clicked section.\n *\n * @param props.sectionId - Unique section ID from the API (e.g., \"categories-7kvobkg2g\").\n * @param props.sectionType - Section type string (e.g., \"categories\", \"banner\").\n * @param props.enabled - Whether the section is visible. Defaults to true. Disabled sections\n * are hidden in normal mode but shown dimmed in editor mode.\n * @param props.className - Optional additional CSS class names.\n * @param props.children - The actual section component to render inside the wrapper.\n */\nexport function SectionWrapper({\n sectionId,\n sectionType,\n enabled = true,\n className = '',\n children,\n}: SectionWrapperProps) {\n const { isEditorMode } = useEditorMode();\n\n if (!enabled && !isEditorMode) return null;\n\n const handleClick = isEditorMode\n ? (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n window.parent.postMessage(\n { type: 'store:section-clicked', payload: { sectionId } },\n '*'\n );\n }\n : undefined;\n\n return (\n <div\n data-section-id={sectionId}\n data-section-type={sectionType}\n className={`${!enabled && isEditorMode ? 'editor-section-disabled' : ''} ${className}`.trim()}\n onClick={handleClick}\n >\n {children}\n </div>\n );\n}\n"],"mappings":"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","names":["import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/provider/EditorProvider.tsx","../src/provider/EditorContext.ts","../src/provider/config-reducer.ts","../src/css/css-var-sync.ts","../src/hooks/useEditorMode.ts","../src/hooks/useLandingConfig.ts","../src/hooks/useHeroConfig.ts","../src/hooks/useSections.ts","../src/hooks/useSectionById.ts","../src/hooks/useNavbarConfig.ts","../src/hooks/useFooterConfig.ts","../src/hooks/useColorScheme.ts","../src/hooks/useFontStyles.ts","../src/hooks/useBranding.ts","../src/hooks/useSocialLinks.ts","../src/components/SectionWrapper.tsx"],"sourcesContent":["// Provider\nexport { EditorProvider } from './provider/EditorProvider';\nexport type { EditorProviderProps } from './provider/EditorProvider';\nexport { EditorContext } from './provider/EditorContext';\nexport type { EditorContextValue } from './provider/EditorContext';\n\n// Hooks\nexport { useEditorMode } from './hooks/useEditorMode';\nexport { useLandingConfig } from './hooks/useLandingConfig';\nexport { useHeroConfig } from './hooks/useHeroConfig';\nexport { useSections } from './hooks/useSections';\nexport { useSectionById } from './hooks/useSectionById';\nexport { useNavbarConfig } from './hooks/useNavbarConfig';\nexport { useFooterConfig } from './hooks/useFooterConfig';\nexport { useColorScheme } from './hooks/useColorScheme';\nexport { useFontStyles } from './hooks/useFontStyles';\nexport { useBranding } from './hooks/useBranding';\nexport { useSocialLinks } from './hooks/useSocialLinks';\n\n// Components\nexport { SectionWrapper } from './components/SectionWrapper';\nexport type { SectionWrapperProps } from './components/SectionWrapper';\n\n// Types\nexport type {\n LandingPageConfig,\n ThemeInfo,\n HeroConfig,\n Section,\n SectionItem,\n SectionType,\n ProductCollection,\n CategorySection,\n Banner,\n SubCategorySection,\n PreFooter,\n PreFooterContent,\n CategoryHighlights,\n StoreReview,\n ProductHighlight,\n ImageWithText,\n Collections,\n SectionFilters,\n FilterType,\n FilterOption,\n NavbarConfig,\n RibbonBarConfig,\n NavElement,\n FooterConfig,\n ColorSchemeConfig,\n FontStylesConfig,\n FontConfig,\n SocialLinksConfig,\n SliderSlide,\n} from './types/config';\nexport type { MetaData } from './types/meta';\nexport type {\n EditorMessage,\n StoreMessage,\n SectionPosition,\n} from './types/messages';\n\n// CSS utilities\nexport { CSS_VAR_MAP, syncCSSVars } from './css/css-var-sync';\n","'use client';\n\nimport React, { useReducer, useEffect, useRef, useState, useMemo } from 'react';\nimport { LandingPageConfig } from '../types/config';\nimport { EditorMessage, StoreMessage, SectionPosition } from '../types/messages';\nimport { EditorContext, EditorContextValue } from './EditorContext';\nimport { configReducer, toReducerAction } from './config-reducer';\nimport { syncCSSVars } from '../css/css-var-sync';\n\nexport interface EditorProviderProps {\n /**\n * The config fetched by the Server Component from GET /store/store_settings/.\n * Must be the EXACT JSON shape — no transformation needed.\n */\n initialConfig: LandingPageConfig;\n\n /**\n * Allowed origin for postMessage. Set to the editor SPA domain in production.\n * Default: \"*\" (accepts all — set NEXT_PUBLIC_EDITOR_ORIGIN in production!)\n */\n editorOrigin?: string;\n callBacks? : {\n onChanges?: (config: LandingPageConfig) => void;\n };\n\n /**\n * Optional: custom CSS variable mapping. Override if your theme uses\n * different CSS property names than the default Starter Theme.\n * Map keys are color_scheme field names → values are CSS property names.\n * Example: { primary: '--brand-color', secondary: '--accent-color' }\n */\n cssVarOverrides?: Record<string, string>;\n\n children: React.ReactNode;\n}\n\n/**\n * Core provider component that enables Visual Editor Mode in Snapstore themes.\n *\n * In normal mode (customer visiting the store), this provider is dormant — it passes\n * the server-fetched initialConfig through context unchanged with zero runtime overhead.\n *\n * In editor mode (?editor=true + loaded inside an iframe), it:\n * 1. Activates editor mode and adds 'editor-mode-active' class to <body>\n * 2. Listens for postMessage events from the parent editor SPA\n * 3. Dispatches config changes through the reducer for immutable state updates\n * 4. Syncs CSS custom properties on <html> when colors/fonts change\n * 5. Reports section DOM positions to the editor for overlay alignment\n * 6. Injects editor-specific CSS (hover outlines, disabled interactions)\n *\n * @param props.initialConfig - The full LandingPageConfig from GET /store/landing_page/.\n * @param props.editorOrigin - Allowed postMessage origin. Defaults to \"*\"; set in production.\n * @param props.cssVarOverrides - Optional map to override default CSS variable name mappings.\n * @param props.children - Child components that consume editor context via hooks.\n */\nexport function EditorProvider({\n initialConfig,\n editorOrigin = '*',\n cssVarOverrides,\n children,\n callBacks,\n}: EditorProviderProps) {\n const [isEditorMode, setIsEditorMode] = useState(false);\n const [config, dispatch] = useReducer(configReducer, initialConfig);\n const positionTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const prevColorRef = useRef(initialConfig.color_scheme);\n const prevFontRef = useRef(initialConfig.font_styles);\n\n // ── 1. Detect editor mode ──\n useEffect(() => {\n if (typeof window === 'undefined') return;\n const params = new URLSearchParams(window.location.search);\n const inIframe = window.self !== window.top;\n if (inIframe && params.get('editor') === 'true') {\n setIsEditorMode(true);\n document.body.classList.add('editor-mode-active');\n }\n return () => {\n document.body.classList.remove('editor-mode-active');\n };\n }, []);\n\n // ── 2. Listen for postMessages ──\n useEffect(() => {\n if (!isEditorMode) return;\n\n const handler = (event: MessageEvent) => {\n if (editorOrigin !== '*' && event.origin !== editorOrigin) return;\n const msg = event.data as EditorMessage;\n if (!msg?.type?.startsWith('editor:')) return;\n\n // Navigation is handled outside reducer (side effect)\n if (msg.type === 'editor:navigate') {\n const url = new URL(msg.payload.url, window.location.origin);\n url.searchParams.set('editor', 'true');\n window.location.href = url.toString();\n return;\n }\n\n // Highlight is a DOM operation, not a state change\n if (msg.type === 'editor:highlight-section') {\n document.querySelectorAll('[data-section-id]').forEach(el => {\n el.classList.toggle(\n 'editor-section-highlight',\n el.getAttribute('data-section-id') === msg.payload.sectionId\n );\n });\n return;\n }\n\n // Everything else goes through the reducer\n const action = toReducerAction(msg);\n if (action) dispatch(action);\n };\n\n window.addEventListener('message', handler);\n return () => window.removeEventListener('message', handler);\n }, [isEditorMode, editorOrigin]);\n\n // ── 3. Send store:ready ──\n useEffect(() => {\n if (!isEditorMode) return;\n const timer = setTimeout(() => {\n sendToEditor({\n type: 'store:ready',\n payload: { sections: getSectionPositions() },\n });\n }, 600);\n return () => clearTimeout(timer);\n }, [isEditorMode]);\n\n // ── 4. Sync CSS vars when color_scheme or font_styles change ──\n useEffect(() => {\n if (!isEditorMode) return;\n if (\n config.color_scheme !== prevColorRef.current ||\n config.font_styles !== prevFontRef.current\n ) {\n syncCSSVars(config.color_scheme, config.font_styles, cssVarOverrides);\n prevColorRef.current = config.color_scheme;\n prevFontRef.current = config.font_styles;\n }\n }, [isEditorMode, config.color_scheme, config.font_styles, cssVarOverrides]);\n\n // ── 5. Report section positions after re-render ──\n useEffect(() => {\n if (!isEditorMode) return;\n if (positionTimerRef.current) clearTimeout(positionTimerRef.current);\n positionTimerRef.current = setTimeout(() => {\n sendToEditor({\n type: 'store:sections-updated',\n payload: { sections: getSectionPositions() },\n });\n }, 300);\n }, [config.sections, config.hero, isEditorMode]);\n\n // ── Context value ──\n const value = useMemo<EditorContextValue>(\n () => ({ isEditorMode, config }),\n [isEditorMode, config]\n );\n\n return (\n <EditorContext.Provider value={value}>\n {isEditorMode && <EditorStylesInline />}\n {children}\n </EditorContext.Provider>\n );\n}\n\n// ── Helpers ──\n\n/**\n * Sends a message from the store iframe to the parent editor SPA via postMessage.\n * No-ops silently if not running in an iframe or if window is undefined (SSR).\n *\n * @param message - The StoreMessage to send (e.g., store:ready, store:section-clicked).\n */\nfunction sendToEditor(message: StoreMessage) {\n if (typeof window === 'undefined' || window.self === window.top) return;\n window.parent.postMessage(message, '*');\n}\n\n/**\n * Queries the DOM for all elements with a `data-section-id` attribute (rendered by SectionWrapper)\n * and returns their current bounding rectangles. The editor SPA uses these positions to align\n * its overlay UI (selection outlines, drag handles) with the preview iframe content.\n *\n * @returns An array of SectionPosition objects with id, type, and bounding rect for each section.\n */\nfunction getSectionPositions(): SectionPosition[] {\n return Array.from(document.querySelectorAll('[data-section-id]')).map(el => ({\n id: el.getAttribute('data-section-id')!,\n type: el.getAttribute('data-section-type') || '',\n rect: el.getBoundingClientRect(),\n }));\n}\n\n/**\n * Renders inline <style> tag with editor-mode-only CSS rules. Only mounted when editor mode is active.\n * These styles:\n * 1. Add hover/highlight outlines on section wrappers for visual feedback\n * 2. Dim disabled sections (opacity 0.35) so merchants can see they're toggled off\n * 3. Disable pointer events on all interactive elements (links, buttons, forms, inputs)\n * to prevent accidental navigation while editing\n * 4. Re-enable pointer events on editor click overlays so section clicks still register\n */\nfunction EditorStylesInline() {\n return (\n <style>{`\n [data-section-id] {\n position: relative;\n transition: outline 0.15s ease;\n }\n [data-section-id]:hover {\n outline: 2px solid rgba(59, 130, 246, 0.5);\n outline-offset: -2px;\n cursor: pointer;\n }\n .editor-section-highlight {\n outline: 2px solid #3b82f6 !important;\n outline-offset: -2px;\n }\n .editor-section-disabled {\n opacity: 0.35;\n }\n .editor-mode-active a,\n .editor-mode-active button:not([data-editor-control]),\n .editor-mode-active input,\n .editor-mode-active select,\n .editor-mode-active form,\n .editor-mode-active textarea {\n pointer-events: none !important;\n }\n [data-section-id] > .editor-click-overlay {\n pointer-events: auto !important;\n }\n `}</style>\n );\n}\n","'use client';\n\nimport { createContext } from 'react';\nimport { LandingPageConfig } from '../types/config';\n\n/**\n * Shape of the value provided by EditorContext.\n * - isEditorMode: Whether the store is running inside the editor iframe with ?editor=true.\n * - config: The current LandingPageConfig — either the original server-fetched config\n * (normal mode) or a live-updating copy managed by the config reducer (editor mode).\n */\nexport interface EditorContextValue {\n isEditorMode: boolean;\n config: LandingPageConfig;\n}\n\n/**\n * React Context that holds the editor state. Consumed by all useXxxConfig hooks.\n * Defaults to null when no EditorProvider is present in the component tree.\n */\nexport const EditorContext = createContext<EditorContextValue | null>(null);\n","import {\n LandingPageConfig,\n Section,\n HeroConfig,\n SliderSlide,\n NavElement,\n RibbonBarConfig,\n ColorSchemeConfig,\n FooterConfig,\n FontStylesConfig,\n SocialLinksConfig,\n} from '../types/config';\nimport { EditorMessage } from '../types/messages';\n\n// ── Action types ──\n\nexport type EditorAction =\n | { type: 'FULL_REPLACE'; config: LandingPageConfig }\n | { type: 'UPDATE_PATH'; path: string; value: any }\n | { type: 'HERO_UPDATE'; data: Partial<HeroConfig> }\n | { type: 'HERO_SLIDE_ADD'; slide: SliderSlide; position: number }\n | { type: 'HERO_SLIDE_REMOVE'; slideId: string }\n | { type: 'HERO_SLIDES_REORDER'; slideIds: string[] }\n | { type: 'HERO_SLIDE_UPDATE'; slideId: string; data: Partial<SliderSlide> }\n | { type: 'SECTIONS_REORDER'; sectionIds: string[] }\n | { type: 'SECTION_ADD'; section: Section; position: number }\n | { type: 'SECTION_REMOVE'; sectionId: string }\n | { type: 'SECTION_TOGGLE'; sectionId: string; enabled: boolean }\n | { type: 'SECTION_UPDATE'; sectionId: string; data: Partial<Section> }\n | { type: 'NAVBAR_UPDATE'; data: Partial<LandingPageConfig['navbar']> }\n | { type: 'NAVBAR_RIBBON_UPDATE'; data: Partial<RibbonBarConfig> }\n | { type: 'NAVBAR_RIBBON_MSG_ADD'; message: { link: string; message: string }; position: number }\n | { type: 'NAVBAR_RIBBON_MSG_REMOVE'; index: number }\n | { type: 'NAVBAR_RIBBON_MSGS_REORDER'; messages: Array<{ link: string; message: string }> }\n | { type: 'NAVBAR_ELEMENT_UPDATE'; key: string; data: Partial<NavElement> }\n | { type: 'NAVBAR_ELEMENT_ADD'; element: NavElement; position: number }\n | { type: 'NAVBAR_ELEMENT_REMOVE'; key: string }\n | { type: 'NAVBAR_ELEMENTS_REORDER'; elements: NavElement[] }\n | { type: 'FOOTER_UPDATE'; data: Partial<FooterConfig> }\n | { type: 'COLOR_SCHEME_UPDATE'; data: Partial<ColorSchemeConfig> }\n | { type: 'FONT_STYLES_UPDATE'; data: { body?: Partial<FontStylesConfig['body']>; heading?: Partial<FontStylesConfig['heading']> } }\n | { type: 'SOCIAL_LINKS_UPDATE'; data: Partial<SocialLinksConfig> }\n | { type: 'BRANDING_UPDATE'; data: Partial<Pick<LandingPageConfig, 'logo' | 'secondary_logo' | 'favicon' | 'store_name' | 'store_description'>> }\n | { type: 'ADVANCED_UPDATE'; data: Partial<Pick<LandingPageConfig, 'custom_css' | 'custom_js' | 'start_head_tag' | 'end_head_tag' | 'start_body_tag' | 'end_body_tag' | 'google_tag_manager_id' | 'facebook_pixel_id'>> };\n\n// ── Message → Action mapper ──\n\n/**\n * Converts an incoming EditorMessage (from postMessage) into a reducer-compatible EditorAction.\n * Maps each `editor:*` message type to its corresponding internal action type.\n * Returns null for unrecognized message types, which are silently ignored.\n *\n * @param msg - The postMessage event data received from the editor SPA.\n * @returns The corresponding EditorAction to dispatch, or null if the message type is unknown.\n */\nexport function toReducerAction(msg: EditorMessage): EditorAction | null {\n switch (msg.type) {\n case 'editor:init':\n case 'editor:full-replace':\n return { type: 'FULL_REPLACE', config: msg.payload.config };\n case 'editor:update':\n return { type: 'UPDATE_PATH', path: msg.payload.path, value: msg.payload.value };\n case 'editor:hero-update':\n return { type: 'HERO_UPDATE', data: msg.payload };\n case 'editor:hero-slide-add':\n return { type: 'HERO_SLIDE_ADD', slide: msg.payload.slide, position: msg.payload.position };\n case 'editor:hero-slide-remove':\n return { type: 'HERO_SLIDE_REMOVE', slideId: msg.payload.slideId };\n case 'editor:hero-slides-reorder':\n return { type: 'HERO_SLIDES_REORDER', slideIds: msg.payload.slideIds };\n case 'editor:hero-slide-update':\n return { type: 'HERO_SLIDE_UPDATE', slideId: msg.payload.slideId, data: msg.payload.data };\n case 'editor:sections-reorder':\n return { type: 'SECTIONS_REORDER', sectionIds: msg.payload.sectionIds };\n case 'editor:section-add':\n return { type: 'SECTION_ADD', section: msg.payload.section, position: msg.payload.position };\n case 'editor:section-remove':\n return { type: 'SECTION_REMOVE', sectionId: msg.payload.sectionId };\n case 'editor:section-toggle':\n return { type: 'SECTION_TOGGLE', sectionId: msg.payload.sectionId, enabled: msg.payload.enabled };\n case 'editor:section-update':\n return { type: 'SECTION_UPDATE', sectionId: msg.payload.sectionId, data: msg.payload.data };\n case 'editor:navbar-update':\n return { type: 'NAVBAR_UPDATE', data: msg.payload };\n case 'editor:navbar-ribbon-update':\n return { type: 'NAVBAR_RIBBON_UPDATE', data: msg.payload };\n case 'editor:navbar-ribbon-message-add':\n return { type: 'NAVBAR_RIBBON_MSG_ADD', message: msg.payload.message, position: msg.payload.position };\n case 'editor:navbar-ribbon-message-remove':\n return { type: 'NAVBAR_RIBBON_MSG_REMOVE', index: msg.payload.index };\n case 'editor:navbar-ribbon-messages-reorder':\n return { type: 'NAVBAR_RIBBON_MSGS_REORDER', messages: msg.payload.messages };\n case 'editor:navbar-element-update':\n return { type: 'NAVBAR_ELEMENT_UPDATE', key: msg.payload.key, data: msg.payload.data };\n case 'editor:navbar-element-add':\n return { type: 'NAVBAR_ELEMENT_ADD', element: msg.payload.element, position: msg.payload.position };\n case 'editor:navbar-element-remove':\n return { type: 'NAVBAR_ELEMENT_REMOVE', key: msg.payload.key };\n case 'editor:navbar-elements-reorder':\n return { type: 'NAVBAR_ELEMENTS_REORDER', elements: msg.payload.elements };\n case 'editor:footer-update':\n return { type: 'FOOTER_UPDATE', data: msg.payload };\n case 'editor:color-scheme-update':\n return { type: 'COLOR_SCHEME_UPDATE', data: msg.payload };\n case 'editor:font-styles-update':\n return { type: 'FONT_STYLES_UPDATE', data: msg.payload };\n case 'editor:social-links-update':\n return { type: 'SOCIAL_LINKS_UPDATE', data: msg.payload };\n case 'editor:branding-update':\n return { type: 'BRANDING_UPDATE', data: msg.payload };\n case 'editor:advanced-update':\n return { type: 'ADVANCED_UPDATE', data: msg.payload };\n default:\n return null;\n }\n}\n\n// ── Reducer ──\n\n/**\n * Pure reducer that produces the next LandingPageConfig state from the current state and an action.\n * Handles all 25 action types covering hero, sections, navbar, footer, colors, fonts, branding,\n * social links, and advanced settings. All updates are immutable — returns a new object reference\n * on change, or the same reference if the action is unknown.\n *\n * @param state - The current LandingPageConfig state.\n * @param action - The EditorAction describing the state transition.\n * @returns A new LandingPageConfig with the action applied, or the same state if action is unknown.\n */\nexport function configReducer(state: LandingPageConfig, action: EditorAction): LandingPageConfig {\n switch (action.type) {\n case 'FULL_REPLACE':\n return action.config;\n\n case 'UPDATE_PATH':\n return setByPath(state, action.path, action.value);\n\n // ── Hero ──\n\n case 'HERO_UPDATE':\n return { ...state, hero: { ...state.hero, ...action.data } };\n\n case 'HERO_SLIDE_ADD': {\n const slides = [...state.hero.sliderSettings];\n slides.splice(action.position, 0, action.slide);\n return { ...state, hero: { ...state.hero, sliderSettings: slides } };\n }\n\n case 'HERO_SLIDE_REMOVE':\n return {\n ...state,\n hero: {\n ...state.hero,\n sliderSettings: state.hero.sliderSettings.filter(s => s.id !== action.slideId),\n },\n };\n\n case 'HERO_SLIDES_REORDER': {\n const reordered = action.slideIds\n .map(id => state.hero.sliderSettings.find(s => s.id === id))\n .filter(Boolean) as SliderSlide[];\n return { ...state, hero: { ...state.hero, sliderSettings: reordered } };\n }\n\n case 'HERO_SLIDE_UPDATE':\n return {\n ...state,\n hero: {\n ...state.hero,\n sliderSettings: state.hero.sliderSettings.map(s =>\n s.id === action.slideId ? { ...s, ...action.data } : s\n ),\n },\n };\n\n // ── Sections ──\n\n case 'SECTIONS_REORDER': {\n const reordered = action.sectionIds\n .map(id => state.sections.find(s => s.id === id))\n .filter(Boolean) as Section[];\n return { ...state, sections: reordered };\n }\n\n case 'SECTION_ADD': {\n const sections = [...state.sections];\n sections.splice(action.position, 0, action.section);\n return { ...state, sections };\n }\n\n case 'SECTION_REMOVE':\n return { ...state, sections: state.sections.filter(s => s.id !== action.sectionId) };\n\n case 'SECTION_TOGGLE':\n return {\n ...state,\n sections: state.sections.map(s =>\n s.id === action.sectionId ? { ...s, enabled: action.enabled } as Section : s\n ),\n };\n\n case 'SECTION_UPDATE':\n return {\n ...state,\n sections: state.sections.map(s =>\n s.id === action.sectionId ? { ...s, ...action.data } as Section : s\n ),\n };\n\n // ── Navbar ──\n\n case 'NAVBAR_UPDATE': {\n const { ribbonbar, navElements, ...rest } = action.data;\n let navbar = { ...state.navbar, ...rest };\n if (ribbonbar) navbar = { ...navbar, ribbonbar: { ...navbar.ribbonbar, ...ribbonbar } };\n if (navElements) navbar = { ...navbar, navElements };\n return { ...state, navbar };\n }\n\n case 'NAVBAR_RIBBON_UPDATE':\n return {\n ...state,\n navbar: {\n ...state.navbar,\n ribbonbar: { ...state.navbar.ribbonbar, ...action.data },\n },\n };\n\n case 'NAVBAR_RIBBON_MSG_ADD': {\n const messages = [...state.navbar.ribbonbar.messages];\n messages.splice(action.position, 0, action.message);\n return {\n ...state,\n navbar: {\n ...state.navbar,\n ribbonbar: { ...state.navbar.ribbonbar, messages },\n },\n };\n }\n\n case 'NAVBAR_RIBBON_MSG_REMOVE': {\n const messages = state.navbar.ribbonbar.messages.filter((_, i) => i !== action.index);\n return {\n ...state,\n navbar: {\n ...state.navbar,\n ribbonbar: { ...state.navbar.ribbonbar, messages },\n },\n };\n }\n\n case 'NAVBAR_RIBBON_MSGS_REORDER':\n return {\n ...state,\n navbar: {\n ...state.navbar,\n ribbonbar: { ...state.navbar.ribbonbar, messages: action.messages },\n },\n };\n\n case 'NAVBAR_ELEMENT_UPDATE':\n return {\n ...state,\n navbar: {\n ...state.navbar,\n navElements: state.navbar.navElements.map(el =>\n el.key === action.key ? { ...el, ...action.data } : el\n ),\n },\n };\n\n case 'NAVBAR_ELEMENT_ADD': {\n const navElements = [...state.navbar.navElements];\n navElements.splice(action.position, 0, action.element);\n return { ...state, navbar: { ...state.navbar, navElements } };\n }\n\n case 'NAVBAR_ELEMENT_REMOVE':\n return {\n ...state,\n navbar: {\n ...state.navbar,\n navElements: state.navbar.navElements.filter(el => el.key !== action.key),\n },\n };\n\n case 'NAVBAR_ELEMENTS_REORDER':\n return { ...state, navbar: { ...state.navbar, navElements: action.elements } };\n\n // ── Top-level ──\n\n case 'FOOTER_UPDATE':\n return { ...state, footer: { ...state.footer, ...action.data } };\n\n case 'COLOR_SCHEME_UPDATE':\n return { ...state, color_scheme: { ...state.color_scheme, ...action.data } };\n\n case 'FONT_STYLES_UPDATE': {\n const font_styles = { ...state.font_styles };\n if (action.data.body) font_styles.body = { ...font_styles.body, ...action.data.body };\n if (action.data.heading) font_styles.heading = { ...font_styles.heading, ...action.data.heading };\n return { ...state, font_styles };\n }\n\n case 'SOCIAL_LINKS_UPDATE':\n return { ...state, social_links: { ...state.social_links, ...action.data } };\n\n case 'BRANDING_UPDATE':\n return { ...state, ...action.data };\n\n case 'ADVANCED_UPDATE':\n return { ...state, ...action.data };\n\n default:\n return state;\n }\n}\n\n// ── Helpers ──\n\n/**\n * Immutably sets a value at a dot-notation path within a nested object.\n * Creates shallow copies at each level of nesting to preserve immutability.\n * If intermediate keys don't exist, empty objects are created.\n *\n * @param obj - The source object to update.\n * @param path - Dot-notation path (e.g., \"hero.title\" or \"navbar.ribbonbar.animation\").\n * @param value - The value to set at the specified path.\n * @returns A new object with the value set at the given path.\n *\n * @example\n * setByPath({ hero: { title: 'Old' } }, 'hero.title', 'New')\n * // => { hero: { title: 'New' } }\n */\nfunction setByPath(obj: any, path: string, value: any): any {\n const keys = path.split('.');\n if (keys.length === 1) return { ...obj, [keys[0]]: value };\n const [head, ...tail] = keys;\n return { ...obj, [head]: setByPath(obj[head] ?? {}, tail.join('.'), value) };\n}\n","import { ColorSchemeConfig, FontStylesConfig } from '../types/config';\n\n/**\n * Default mapping: color_scheme field name → CSS custom property name.\n * These match what app/layout.tsx injects on <html style=\"...\">.\n *\n * VERIFY against the actual layout.tsx in your theme!\n * If your theme uses --brand-primary instead of --primary, pass\n * cssVarOverrides to EditorProvider.\n */\nexport const CSS_VAR_MAP: Record<string, string> = {\n primary: '--primary',\n secondary: '--secondary',\n btnText: '--btn-text',\n textPrimary: '--text-primary',\n textSecondary: '--text-secondary',\n bodyBackground: '--bg-primary',\n bodyBackground1: '--bg-primary-smoke',\n bodyBackgroundSecondary: '--bg-secondary-color',\n bodyBackgroundDark: '--bg-dark',\n borderBackground: '--bg-border',\n headerbg: '--header-bg',\n textColor: '--text-color',\n footerBgColor: '--footer-bg',\n footerTextColor: '--footer-text',\n};\n\n/**\n * Updates CSS custom properties on document.documentElement (<html>).\n * Called by EditorProvider when color_scheme or font_styles change.\n *\n * This overwrites the same vars that layout.tsx set on initial SSR,\n * so all SCSS that references var(--primary) etc. updates immediately.\n */\nexport function syncCSSVars(\n colorScheme: ColorSchemeConfig,\n fontStyles: FontStylesConfig,\n overrides?: Record<string, string>\n) {\n const root = document.documentElement;\n const varMap = overrides ? { ...CSS_VAR_MAP, ...overrides } : CSS_VAR_MAP;\n\n\n // Sync colors\n for (const [configKey, cssVar] of Object.entries(varMap)) {\n if(!colorScheme) return;\n const value = (colorScheme as Record<string, any>)[configKey];\n if (value !== undefined && value !== null && value !== '') {\n root.style.setProperty(cssVar, value);\n }\n }\n\n // Sync fonts\n if (fontStyles?.heading) {\n root.style.setProperty('--heading-font', `'${fontStyles.heading.font_family}'`);\n root.style.setProperty('--heading-weight', String(fontStyles.heading.font_weight));\n loadGoogleFont(fontStyles.heading.font_url);\n }\n if (fontStyles?.body) {\n root.style.setProperty('--body-font', `'${fontStyles.body.font_family}'`);\n root.style.setProperty('--body-weight', String(fontStyles.body.font_weight));\n loadGoogleFont(fontStyles.body.font_url);\n }\n}\n\n/** Load a Google Font by injecting a <link> tag. Deduplicates. */\nfunction loadGoogleFont(url: string) {\n if (!url) return;\n if (document.querySelector(`link[href=\"${url}\"]`)) return;\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n document.head.appendChild(link);\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns whether the store is currently running in editor mode.\n * Editor mode is active when the page is loaded inside an iframe with ?editor=true.\n * Returns { isEditorMode: false } when used outside of EditorProvider.\n */\nexport function useEditorMode(): { isEditorMode: boolean } {\n const ctx = useContext(EditorContext);\n return { isEditorMode: ctx?.isEditorMode ?? false };\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\nimport { LandingPageConfig } from '../types/config';\n\n/**\n * Returns the full LandingPageConfig object from EditorContext.\n * In normal mode, this is the original server-fetched config.\n * In editor mode, this is the live-updating copy that reflects changes from the editor SPA.\n * Returns null when used outside of EditorProvider.\n */\nexport function useLandingConfig(): LandingPageConfig | null {\n return useContext(EditorContext)?.config ?? null;\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\nimport { HeroConfig } from '../types/config';\n\n/**\n * Returns the hero banner configuration (title, CTA, images, slider settings).\n * Updates live in editor mode when the editor SPA sends hero changes.\n * Returns null when used outside of EditorProvider.\n */\nexport function useHeroConfig(): HeroConfig | null {\n return useContext(EditorContext)?.config?.hero ?? null;\n}\n","'use client';\n\nimport { useContext, useMemo } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\nimport { Section } from '../types/config';\n\n/**\n * Returns the ordered array of landing page sections from the config.\n * Reflects live reordering, additions, removals, and toggles from the editor SPA.\n * Memoized to prevent unnecessary re-renders when sections haven't changed.\n * Returns an empty array when used outside of EditorProvider.\n */\nexport function useSections(): Section[] {\n const ctx = useContext(EditorContext);\n return useMemo(() => ctx?.config?.sections ?? [], [ctx?.config?.sections]);\n}\n","'use client';\n\nimport { useContext, useMemo } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\nimport { Section } from '../types/config';\n\n/**\n * Finds and returns a single section by its unique ID from the sections array.\n * Memoized to avoid re-computing on every render unless the sections array changes.\n * Returns undefined if no section with the given ID exists.\n *\n * @param sectionId - The unique ID of the section to find (e.g., \"categories-7kvobkg2g\").\n */\nexport function useSectionById(sectionId: string): Section | undefined {\n const ctx = useContext(EditorContext);\n return useMemo(\n () => ctx?.config?.sections.find(s => s.id === sectionId),\n [ctx?.config?.sections, sectionId]\n );\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns the navbar configuration (logo position, cart/wishlist toggles, ribbon bar, nav elements).\n * Updates live in editor mode when the editor SPA sends navbar changes.\n * Returns null when used outside of EditorProvider.\n */\nexport function useNavbarConfig() {\n return useContext(EditorContext)?.config?.navbar ?? null;\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns the footer configuration (social links visibility, contact details, branding toggles).\n * Updates live in editor mode when the editor SPA sends footer changes.\n * Returns null when used outside of EditorProvider.\n */\nexport function useFooterConfig() {\n return useContext(EditorContext)?.config?.footer ?? null;\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns the color scheme configuration (primary, secondary, background, text, footer colors).\n * When these values change in editor mode, EditorProvider also syncs CSS custom properties\n * on <html> for instant visual updates across all SCSS-styled components.\n * Returns null when used outside of EditorProvider.\n */\nexport function useColorScheme() {\n return useContext(EditorContext)?.config?.color_scheme ?? null;\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns the font styles configuration (body and heading font family, weight, and Google Font URL).\n * When fonts change in editor mode, EditorProvider syncs CSS custom properties and dynamically\n * loads the new Google Font via <link> tag injection.\n * Returns null when used outside of EditorProvider.\n */\nexport function useFontStyles() {\n return useContext(EditorContext)?.config?.font_styles ?? null;\n}\n","'use client';\n\nimport { useContext, useMemo } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns branding-related fields (logo, secondary_logo, favicon, store_name, store_description).\n * Memoized to only re-compute when one of these specific fields changes, avoiding unnecessary\n * re-renders when other parts of the config update.\n * Returns null when used outside of EditorProvider.\n */\nexport function useBranding() {\n const ctx = useContext(EditorContext);\n return useMemo(() => {\n if (!ctx?.config) return null;\n const c = ctx.config;\n return {\n logo: c.logo,\n secondary_logo: c.secondary_logo,\n favicon: c.favicon,\n store_name: c.store_name,\n store_description: c.store_description,\n };\n }, [\n ctx?.config?.logo,\n ctx?.config?.secondary_logo,\n ctx?.config?.favicon,\n ctx?.config?.store_name,\n ctx?.config?.store_description,\n ]);\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns social media link URLs (twitter, youtube, facebook, instagram).\n * Updates live in editor mode when the editor SPA sends social link changes.\n * Returns null when used outside of EditorProvider.\n */\nexport function useSocialLinks() {\n return useContext(EditorContext)?.config?.social_links ?? null;\n}\n","'use client';\n\nimport React from 'react';\nimport { useEditorMode } from '../hooks/useEditorMode';\n\nexport interface SectionWrapperProps {\n sectionId: string;\n sectionType: string;\n enabled?: boolean;\n className?: string;\n children: React.ReactNode;\n}\n\n/**\n * Wraps a landing page section with editor-aware behavior.\n *\n * In normal mode: renders children inside a <div> with data-section-id/data-section-type\n * attributes. If enabled=false, returns null (section is hidden from customers).\n *\n * In editor mode: always renders (even disabled sections, shown dimmed at 0.35 opacity).\n * Intercepts clicks and sends a 'store:section-clicked' postMessage to the parent editor SPA,\n * allowing the editor to open the settings panel for the clicked section.\n *\n * @param props.sectionId - Unique section ID from the API (e.g., \"categories-7kvobkg2g\").\n * @param props.sectionType - Section type string (e.g., \"categories\", \"banner\").\n * @param props.enabled - Whether the section is visible. Defaults to true. Disabled sections\n * are hidden in normal mode but shown dimmed in editor mode.\n * @param props.className - Optional additional CSS class names.\n * @param props.children - The actual section component to render inside the wrapper.\n */\nexport function SectionWrapper({\n sectionId,\n sectionType,\n enabled = true,\n className = '',\n children,\n}: SectionWrapperProps) {\n const { isEditorMode } = useEditorMode();\n\n if (!enabled && !isEditorMode) return null;\n\n const handleClick = isEditorMode\n ? (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n window.parent.postMessage(\n { type: 'store:section-clicked', payload: { sectionId } },\n '*'\n );\n }\n : undefined;\n\n return (\n <div\n data-section-id={sectionId}\n data-section-type={sectionType}\n className={`${!enabled && isEditorMode ? 'editor-section-disabled' : ''} ${className}`.trim()}\n onClick={handleClick}\n >\n {children}\n </div>\n );\n}\n"],"mappings":"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","names":["import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_jsx_runtime"]}
|
package/dist/index.mjs
CHANGED
|
@@ -248,6 +248,7 @@ function syncCSSVars(colorScheme, fontStyles, overrides) {
|
|
|
248
248
|
const root = document.documentElement;
|
|
249
249
|
const varMap = overrides ? { ...CSS_VAR_MAP, ...overrides } : CSS_VAR_MAP;
|
|
250
250
|
for (const [configKey, cssVar] of Object.entries(varMap)) {
|
|
251
|
+
if (!colorScheme) return;
|
|
251
252
|
const value = colorScheme[configKey];
|
|
252
253
|
if (value !== void 0 && value !== null && value !== "") {
|
|
253
254
|
root.style.setProperty(cssVar, value);
|
|
@@ -279,7 +280,8 @@ function EditorProvider({
|
|
|
279
280
|
initialConfig,
|
|
280
281
|
editorOrigin = "*",
|
|
281
282
|
cssVarOverrides,
|
|
282
|
-
children
|
|
283
|
+
children,
|
|
284
|
+
callBacks
|
|
283
285
|
}) {
|
|
284
286
|
const [isEditorMode, setIsEditorMode] = useState(false);
|
|
285
287
|
const [config, dispatch] = useReducer(configReducer, initialConfig);
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider/EditorProvider.tsx","../src/provider/EditorContext.ts","../src/provider/config-reducer.ts","../src/css/css-var-sync.ts","../src/hooks/useEditorMode.ts","../src/hooks/useLandingConfig.ts","../src/hooks/useHeroConfig.ts","../src/hooks/useSections.ts","../src/hooks/useSectionById.ts","../src/hooks/useNavbarConfig.ts","../src/hooks/useFooterConfig.ts","../src/hooks/useColorScheme.ts","../src/hooks/useFontStyles.ts","../src/hooks/useBranding.ts","../src/hooks/useSocialLinks.ts","../src/components/SectionWrapper.tsx"],"sourcesContent":["'use client';\n\nimport React, { useReducer, useEffect, useRef, useState, useMemo } from 'react';\nimport { LandingPageConfig } from '../types/config';\nimport { EditorMessage, StoreMessage, SectionPosition } from '../types/messages';\nimport { EditorContext, EditorContextValue } from './EditorContext';\nimport { configReducer, toReducerAction } from './config-reducer';\nimport { syncCSSVars } from '../css/css-var-sync';\n\nexport interface EditorProviderProps {\n /**\n * The config fetched by the Server Component from GET /store/store_settings/.\n * Must be the EXACT JSON shape — no transformation needed.\n */\n initialConfig: LandingPageConfig;\n\n /**\n * Allowed origin for postMessage. Set to the editor SPA domain in production.\n * Default: \"*\" (accepts all — set NEXT_PUBLIC_EDITOR_ORIGIN in production!)\n */\n editorOrigin?: string;\n\n /**\n * Optional: custom CSS variable mapping. Override if your theme uses\n * different CSS property names than the default Starter Theme.\n * Map keys are color_scheme field names → values are CSS property names.\n * Example: { primary: '--brand-color', secondary: '--accent-color' }\n */\n cssVarOverrides?: Record<string, string>;\n\n children: React.ReactNode;\n}\n\n/**\n * Core provider component that enables Visual Editor Mode in Snapstore themes.\n *\n * In normal mode (customer visiting the store), this provider is dormant — it passes\n * the server-fetched initialConfig through context unchanged with zero runtime overhead.\n *\n * In editor mode (?editor=true + loaded inside an iframe), it:\n * 1. Activates editor mode and adds 'editor-mode-active' class to <body>\n * 2. Listens for postMessage events from the parent editor SPA\n * 3. Dispatches config changes through the reducer for immutable state updates\n * 4. Syncs CSS custom properties on <html> when colors/fonts change\n * 5. Reports section DOM positions to the editor for overlay alignment\n * 6. Injects editor-specific CSS (hover outlines, disabled interactions)\n *\n * @param props.initialConfig - The full LandingPageConfig from GET /store/landing_page/.\n * @param props.editorOrigin - Allowed postMessage origin. Defaults to \"*\"; set in production.\n * @param props.cssVarOverrides - Optional map to override default CSS variable name mappings.\n * @param props.children - Child components that consume editor context via hooks.\n */\nexport function EditorProvider({\n initialConfig,\n editorOrigin = '*',\n cssVarOverrides,\n children,\n}: EditorProviderProps) {\n const [isEditorMode, setIsEditorMode] = useState(false);\n const [config, dispatch] = useReducer(configReducer, initialConfig);\n const positionTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const prevColorRef = useRef(initialConfig.color_scheme);\n const prevFontRef = useRef(initialConfig.font_styles);\n\n // ── 1. Detect editor mode ──\n useEffect(() => {\n if (typeof window === 'undefined') return;\n const params = new URLSearchParams(window.location.search);\n const inIframe = window.self !== window.top;\n if (inIframe && params.get('editor') === 'true') {\n setIsEditorMode(true);\n document.body.classList.add('editor-mode-active');\n }\n return () => {\n document.body.classList.remove('editor-mode-active');\n };\n }, []);\n\n // ── 2. Listen for postMessages ──\n useEffect(() => {\n if (!isEditorMode) return;\n\n const handler = (event: MessageEvent) => {\n if (editorOrigin !== '*' && event.origin !== editorOrigin) return;\n const msg = event.data as EditorMessage;\n if (!msg?.type?.startsWith('editor:')) return;\n\n // Navigation is handled outside reducer (side effect)\n if (msg.type === 'editor:navigate') {\n const url = new URL(msg.payload.url, window.location.origin);\n url.searchParams.set('editor', 'true');\n window.location.href = url.toString();\n return;\n }\n\n // Highlight is a DOM operation, not a state change\n if (msg.type === 'editor:highlight-section') {\n document.querySelectorAll('[data-section-id]').forEach(el => {\n el.classList.toggle(\n 'editor-section-highlight',\n el.getAttribute('data-section-id') === msg.payload.sectionId\n );\n });\n return;\n }\n\n // Everything else goes through the reducer\n const action = toReducerAction(msg);\n if (action) dispatch(action);\n };\n\n window.addEventListener('message', handler);\n return () => window.removeEventListener('message', handler);\n }, [isEditorMode, editorOrigin]);\n\n // ── 3. Send store:ready ──\n useEffect(() => {\n if (!isEditorMode) return;\n const timer = setTimeout(() => {\n sendToEditor({\n type: 'store:ready',\n payload: { sections: getSectionPositions() },\n });\n }, 600);\n return () => clearTimeout(timer);\n }, [isEditorMode]);\n\n // ── 4. Sync CSS vars when color_scheme or font_styles change ──\n useEffect(() => {\n if (!isEditorMode) return;\n if (\n config.color_scheme !== prevColorRef.current ||\n config.font_styles !== prevFontRef.current\n ) {\n syncCSSVars(config.color_scheme, config.font_styles, cssVarOverrides);\n prevColorRef.current = config.color_scheme;\n prevFontRef.current = config.font_styles;\n }\n }, [isEditorMode, config.color_scheme, config.font_styles, cssVarOverrides]);\n\n // ── 5. Report section positions after re-render ──\n useEffect(() => {\n if (!isEditorMode) return;\n if (positionTimerRef.current) clearTimeout(positionTimerRef.current);\n positionTimerRef.current = setTimeout(() => {\n sendToEditor({\n type: 'store:sections-updated',\n payload: { sections: getSectionPositions() },\n });\n }, 300);\n }, [config.sections, config.hero, isEditorMode]);\n\n // ── Context value ──\n const value = useMemo<EditorContextValue>(\n () => ({ isEditorMode, config }),\n [isEditorMode, config]\n );\n\n return (\n <EditorContext.Provider value={value}>\n {isEditorMode && <EditorStylesInline />}\n {children}\n </EditorContext.Provider>\n );\n}\n\n// ── Helpers ──\n\n/**\n * Sends a message from the store iframe to the parent editor SPA via postMessage.\n * No-ops silently if not running in an iframe or if window is undefined (SSR).\n *\n * @param message - The StoreMessage to send (e.g., store:ready, store:section-clicked).\n */\nfunction sendToEditor(message: StoreMessage) {\n if (typeof window === 'undefined' || window.self === window.top) return;\n window.parent.postMessage(message, '*');\n}\n\n/**\n * Queries the DOM for all elements with a `data-section-id` attribute (rendered by SectionWrapper)\n * and returns their current bounding rectangles. The editor SPA uses these positions to align\n * its overlay UI (selection outlines, drag handles) with the preview iframe content.\n *\n * @returns An array of SectionPosition objects with id, type, and bounding rect for each section.\n */\nfunction getSectionPositions(): SectionPosition[] {\n return Array.from(document.querySelectorAll('[data-section-id]')).map(el => ({\n id: el.getAttribute('data-section-id')!,\n type: el.getAttribute('data-section-type') || '',\n rect: el.getBoundingClientRect(),\n }));\n}\n\n/**\n * Renders inline <style> tag with editor-mode-only CSS rules. Only mounted when editor mode is active.\n * These styles:\n * 1. Add hover/highlight outlines on section wrappers for visual feedback\n * 2. Dim disabled sections (opacity 0.35) so merchants can see they're toggled off\n * 3. Disable pointer events on all interactive elements (links, buttons, forms, inputs)\n * to prevent accidental navigation while editing\n * 4. Re-enable pointer events on editor click overlays so section clicks still register\n */\nfunction EditorStylesInline() {\n return (\n <style>{`\n [data-section-id] {\n position: relative;\n transition: outline 0.15s ease;\n }\n [data-section-id]:hover {\n outline: 2px solid rgba(59, 130, 246, 0.5);\n outline-offset: -2px;\n cursor: pointer;\n }\n .editor-section-highlight {\n outline: 2px solid #3b82f6 !important;\n outline-offset: -2px;\n }\n .editor-section-disabled {\n opacity: 0.35;\n }\n .editor-mode-active a,\n .editor-mode-active button:not([data-editor-control]),\n .editor-mode-active input,\n .editor-mode-active select,\n .editor-mode-active form,\n .editor-mode-active textarea {\n pointer-events: none !important;\n }\n [data-section-id] > .editor-click-overlay {\n pointer-events: auto !important;\n }\n `}</style>\n );\n}\n","'use client';\n\nimport { createContext } from 'react';\nimport { LandingPageConfig } from '../types/config';\n\n/**\n * Shape of the value provided by EditorContext.\n * - isEditorMode: Whether the store is running inside the editor iframe with ?editor=true.\n * - config: The current LandingPageConfig — either the original server-fetched config\n * (normal mode) or a live-updating copy managed by the config reducer (editor mode).\n */\nexport interface EditorContextValue {\n isEditorMode: boolean;\n config: LandingPageConfig;\n}\n\n/**\n * React Context that holds the editor state. Consumed by all useXxxConfig hooks.\n * Defaults to null when no EditorProvider is present in the component tree.\n */\nexport const EditorContext = createContext<EditorContextValue | null>(null);\n","import {\n LandingPageConfig,\n SectionItem,\n HeroConfig,\n SliderSlide,\n NavElement,\n RibbonBarConfig,\n ColorSchemeConfig,\n FooterConfig,\n FontStylesConfig,\n SocialLinksConfig,\n} from '../types/config';\nimport { EditorMessage } from '../types/messages';\n\n// ── Action types ──\n\nexport type EditorAction =\n | { type: 'FULL_REPLACE'; config: LandingPageConfig }\n | { type: 'UPDATE_PATH'; path: string; value: any }\n | { type: 'HERO_UPDATE'; data: Partial<HeroConfig> }\n | { type: 'HERO_SLIDE_ADD'; slide: SliderSlide; position: number }\n | { type: 'HERO_SLIDE_REMOVE'; slideId: string }\n | { type: 'HERO_SLIDES_REORDER'; slideIds: string[] }\n | { type: 'HERO_SLIDE_UPDATE'; slideId: string; data: Partial<SliderSlide> }\n | { type: 'SECTIONS_REORDER'; sectionIds: string[] }\n | { type: 'SECTION_ADD'; section: SectionItem; position: number }\n | { type: 'SECTION_REMOVE'; sectionId: string }\n | { type: 'SECTION_TOGGLE'; sectionId: string; enabled: boolean }\n | { type: 'SECTION_UPDATE'; sectionId: string; data: Partial<SectionItem> }\n | { type: 'NAVBAR_UPDATE'; data: Partial<LandingPageConfig['navbar']> }\n | { type: 'NAVBAR_RIBBON_UPDATE'; data: Partial<RibbonBarConfig> }\n | { type: 'NAVBAR_RIBBON_MSG_ADD'; message: { link: string; message: string }; position: number }\n | { type: 'NAVBAR_RIBBON_MSG_REMOVE'; index: number }\n | { type: 'NAVBAR_RIBBON_MSGS_REORDER'; messages: Array<{ link: string; message: string }> }\n | { type: 'NAVBAR_ELEMENT_UPDATE'; key: string; data: Partial<NavElement> }\n | { type: 'NAVBAR_ELEMENT_ADD'; element: NavElement; position: number }\n | { type: 'NAVBAR_ELEMENT_REMOVE'; key: string }\n | { type: 'NAVBAR_ELEMENTS_REORDER'; elements: NavElement[] }\n | { type: 'FOOTER_UPDATE'; data: Partial<FooterConfig> }\n | { type: 'COLOR_SCHEME_UPDATE'; data: Partial<ColorSchemeConfig> }\n | { type: 'FONT_STYLES_UPDATE'; data: { body?: Partial<FontStylesConfig['body']>; heading?: Partial<FontStylesConfig['heading']> } }\n | { type: 'SOCIAL_LINKS_UPDATE'; data: Partial<SocialLinksConfig> }\n | { type: 'BRANDING_UPDATE'; data: Partial<Pick<LandingPageConfig, 'logo' | 'secondary_logo' | 'favicon' | 'store_name' | 'store_description'>> }\n | { type: 'ADVANCED_UPDATE'; data: Partial<Pick<LandingPageConfig, 'custom_css' | 'custom_js' | 'start_head_tag' | 'end_head_tag' | 'start_body_tag' | 'end_body_tag' | 'google_tag_manager_id' | 'facebook_pixel_id'>> };\n\n// ── Message → Action mapper ──\n\n/**\n * Converts an incoming EditorMessage (from postMessage) into a reducer-compatible EditorAction.\n * Maps each `editor:*` message type to its corresponding internal action type.\n * Returns null for unrecognized message types, which are silently ignored.\n *\n * @param msg - The postMessage event data received from the editor SPA.\n * @returns The corresponding EditorAction to dispatch, or null if the message type is unknown.\n */\nexport function toReducerAction(msg: EditorMessage): EditorAction | null {\n switch (msg.type) {\n case 'editor:init':\n case 'editor:full-replace':\n return { type: 'FULL_REPLACE', config: msg.payload.config };\n case 'editor:update':\n return { type: 'UPDATE_PATH', path: msg.payload.path, value: msg.payload.value };\n case 'editor:hero-update':\n return { type: 'HERO_UPDATE', data: msg.payload };\n case 'editor:hero-slide-add':\n return { type: 'HERO_SLIDE_ADD', slide: msg.payload.slide, position: msg.payload.position };\n case 'editor:hero-slide-remove':\n return { type: 'HERO_SLIDE_REMOVE', slideId: msg.payload.slideId };\n case 'editor:hero-slides-reorder':\n return { type: 'HERO_SLIDES_REORDER', slideIds: msg.payload.slideIds };\n case 'editor:hero-slide-update':\n return { type: 'HERO_SLIDE_UPDATE', slideId: msg.payload.slideId, data: msg.payload.data };\n case 'editor:sections-reorder':\n return { type: 'SECTIONS_REORDER', sectionIds: msg.payload.sectionIds };\n case 'editor:section-add':\n return { type: 'SECTION_ADD', section: msg.payload.section, position: msg.payload.position };\n case 'editor:section-remove':\n return { type: 'SECTION_REMOVE', sectionId: msg.payload.sectionId };\n case 'editor:section-toggle':\n return { type: 'SECTION_TOGGLE', sectionId: msg.payload.sectionId, enabled: msg.payload.enabled };\n case 'editor:section-update':\n return { type: 'SECTION_UPDATE', sectionId: msg.payload.sectionId, data: msg.payload.data };\n case 'editor:navbar-update':\n return { type: 'NAVBAR_UPDATE', data: msg.payload };\n case 'editor:navbar-ribbon-update':\n return { type: 'NAVBAR_RIBBON_UPDATE', data: msg.payload };\n case 'editor:navbar-ribbon-message-add':\n return { type: 'NAVBAR_RIBBON_MSG_ADD', message: msg.payload.message, position: msg.payload.position };\n case 'editor:navbar-ribbon-message-remove':\n return { type: 'NAVBAR_RIBBON_MSG_REMOVE', index: msg.payload.index };\n case 'editor:navbar-ribbon-messages-reorder':\n return { type: 'NAVBAR_RIBBON_MSGS_REORDER', messages: msg.payload.messages };\n case 'editor:navbar-element-update':\n return { type: 'NAVBAR_ELEMENT_UPDATE', key: msg.payload.key, data: msg.payload.data };\n case 'editor:navbar-element-add':\n return { type: 'NAVBAR_ELEMENT_ADD', element: msg.payload.element, position: msg.payload.position };\n case 'editor:navbar-element-remove':\n return { type: 'NAVBAR_ELEMENT_REMOVE', key: msg.payload.key };\n case 'editor:navbar-elements-reorder':\n return { type: 'NAVBAR_ELEMENTS_REORDER', elements: msg.payload.elements };\n case 'editor:footer-update':\n return { type: 'FOOTER_UPDATE', data: msg.payload };\n case 'editor:color-scheme-update':\n return { type: 'COLOR_SCHEME_UPDATE', data: msg.payload };\n case 'editor:font-styles-update':\n return { type: 'FONT_STYLES_UPDATE', data: msg.payload };\n case 'editor:social-links-update':\n return { type: 'SOCIAL_LINKS_UPDATE', data: msg.payload };\n case 'editor:branding-update':\n return { type: 'BRANDING_UPDATE', data: msg.payload };\n case 'editor:advanced-update':\n return { type: 'ADVANCED_UPDATE', data: msg.payload };\n default:\n return null;\n }\n}\n\n// ── Reducer ──\n\n/**\n * Pure reducer that produces the next LandingPageConfig state from the current state and an action.\n * Handles all 25 action types covering hero, sections, navbar, footer, colors, fonts, branding,\n * social links, and advanced settings. All updates are immutable — returns a new object reference\n * on change, or the same reference if the action is unknown.\n *\n * @param state - The current LandingPageConfig state.\n * @param action - The EditorAction describing the state transition.\n * @returns A new LandingPageConfig with the action applied, or the same state if action is unknown.\n */\nexport function configReducer(state: LandingPageConfig, action: EditorAction): LandingPageConfig {\n switch (action.type) {\n case 'FULL_REPLACE':\n return action.config;\n\n case 'UPDATE_PATH':\n return setByPath(state, action.path, action.value);\n\n // ── Hero ──\n\n case 'HERO_UPDATE':\n return { ...state, hero: { ...state.hero, ...action.data } };\n\n case 'HERO_SLIDE_ADD': {\n const slides = [...state.hero.sliderSettings];\n slides.splice(action.position, 0, action.slide);\n return { ...state, hero: { ...state.hero, sliderSettings: slides } };\n }\n\n case 'HERO_SLIDE_REMOVE':\n return {\n ...state,\n hero: {\n ...state.hero,\n sliderSettings: state.hero.sliderSettings.filter(s => s.id !== action.slideId),\n },\n };\n\n case 'HERO_SLIDES_REORDER': {\n const reordered = action.slideIds\n .map(id => state.hero.sliderSettings.find(s => s.id === id))\n .filter(Boolean) as SliderSlide[];\n return { ...state, hero: { ...state.hero, sliderSettings: reordered } };\n }\n\n case 'HERO_SLIDE_UPDATE':\n return {\n ...state,\n hero: {\n ...state.hero,\n sliderSettings: state.hero.sliderSettings.map(s =>\n s.id === action.slideId ? { ...s, ...action.data } : s\n ),\n },\n };\n\n // ── Sections ──\n\n case 'SECTIONS_REORDER': {\n const reordered = action.sectionIds\n .map(id => state.sections.find(s => s.id === id))\n .filter(Boolean) as SectionItem[];\n return { ...state, sections: reordered };\n }\n\n case 'SECTION_ADD': {\n const sections = [...state.sections];\n sections.splice(action.position, 0, action.section);\n return { ...state, sections };\n }\n\n case 'SECTION_REMOVE':\n return { ...state, sections: state.sections.filter(s => s.id !== action.sectionId) };\n\n case 'SECTION_TOGGLE':\n return {\n ...state,\n sections: state.sections.map(s =>\n s.id === action.sectionId ? { ...s, enabled: action.enabled } : s\n ),\n };\n\n case 'SECTION_UPDATE':\n return {\n ...state,\n sections: state.sections.map(s =>\n s.id === action.sectionId ? { ...s, ...action.data } : s\n ),\n };\n\n // ── Navbar ──\n\n case 'NAVBAR_UPDATE': {\n const { ribbonbar, navElements, ...rest } = action.data;\n let navbar = { ...state.navbar, ...rest };\n if (ribbonbar) navbar = { ...navbar, ribbonbar: { ...navbar.ribbonbar, ...ribbonbar } };\n if (navElements) navbar = { ...navbar, navElements };\n return { ...state, navbar };\n }\n\n case 'NAVBAR_RIBBON_UPDATE':\n return {\n ...state,\n navbar: {\n ...state.navbar,\n ribbonbar: { ...state.navbar.ribbonbar, ...action.data },\n },\n };\n\n case 'NAVBAR_RIBBON_MSG_ADD': {\n const messages = [...state.navbar.ribbonbar.messages];\n messages.splice(action.position, 0, action.message);\n return {\n ...state,\n navbar: {\n ...state.navbar,\n ribbonbar: { ...state.navbar.ribbonbar, messages },\n },\n };\n }\n\n case 'NAVBAR_RIBBON_MSG_REMOVE': {\n const messages = state.navbar.ribbonbar.messages.filter((_, i) => i !== action.index);\n return {\n ...state,\n navbar: {\n ...state.navbar,\n ribbonbar: { ...state.navbar.ribbonbar, messages },\n },\n };\n }\n\n case 'NAVBAR_RIBBON_MSGS_REORDER':\n return {\n ...state,\n navbar: {\n ...state.navbar,\n ribbonbar: { ...state.navbar.ribbonbar, messages: action.messages },\n },\n };\n\n case 'NAVBAR_ELEMENT_UPDATE':\n return {\n ...state,\n navbar: {\n ...state.navbar,\n navElements: state.navbar.navElements.map(el =>\n el.key === action.key ? { ...el, ...action.data } : el\n ),\n },\n };\n\n case 'NAVBAR_ELEMENT_ADD': {\n const navElements = [...state.navbar.navElements];\n navElements.splice(action.position, 0, action.element);\n return { ...state, navbar: { ...state.navbar, navElements } };\n }\n\n case 'NAVBAR_ELEMENT_REMOVE':\n return {\n ...state,\n navbar: {\n ...state.navbar,\n navElements: state.navbar.navElements.filter(el => el.key !== action.key),\n },\n };\n\n case 'NAVBAR_ELEMENTS_REORDER':\n return { ...state, navbar: { ...state.navbar, navElements: action.elements } };\n\n // ── Top-level ──\n\n case 'FOOTER_UPDATE':\n return { ...state, footer: { ...state.footer, ...action.data } };\n\n case 'COLOR_SCHEME_UPDATE':\n return { ...state, color_scheme: { ...state.color_scheme, ...action.data } };\n\n case 'FONT_STYLES_UPDATE': {\n const font_styles = { ...state.font_styles };\n if (action.data.body) font_styles.body = { ...font_styles.body, ...action.data.body };\n if (action.data.heading) font_styles.heading = { ...font_styles.heading, ...action.data.heading };\n return { ...state, font_styles };\n }\n\n case 'SOCIAL_LINKS_UPDATE':\n return { ...state, social_links: { ...state.social_links, ...action.data } };\n\n case 'BRANDING_UPDATE':\n return { ...state, ...action.data };\n\n case 'ADVANCED_UPDATE':\n return { ...state, ...action.data };\n\n default:\n return state;\n }\n}\n\n// ── Helpers ──\n\n/**\n * Immutably sets a value at a dot-notation path within a nested object.\n * Creates shallow copies at each level of nesting to preserve immutability.\n * If intermediate keys don't exist, empty objects are created.\n *\n * @param obj - The source object to update.\n * @param path - Dot-notation path (e.g., \"hero.title\" or \"navbar.ribbonbar.animation\").\n * @param value - The value to set at the specified path.\n * @returns A new object with the value set at the given path.\n *\n * @example\n * setByPath({ hero: { title: 'Old' } }, 'hero.title', 'New')\n * // => { hero: { title: 'New' } }\n */\nfunction setByPath(obj: any, path: string, value: any): any {\n const keys = path.split('.');\n if (keys.length === 1) return { ...obj, [keys[0]]: value };\n const [head, ...tail] = keys;\n return { ...obj, [head]: setByPath(obj[head] ?? {}, tail.join('.'), value) };\n}\n","import { ColorSchemeConfig, FontStylesConfig } from '../types/config';\n\n/**\n * Default mapping: color_scheme field name → CSS custom property name.\n * These match what app/layout.tsx injects on <html style=\"...\">.\n *\n * VERIFY against the actual layout.tsx in your theme!\n * If your theme uses --brand-primary instead of --primary, pass\n * cssVarOverrides to EditorProvider.\n */\nexport const CSS_VAR_MAP: Record<string, string> = {\n primary: '--primary',\n secondary: '--secondary',\n btnText: '--btn-text',\n textPrimary: '--text-primary',\n textSecondary: '--text-secondary',\n bodyBackground: '--bg-primary',\n bodyBackground1: '--bg-primary-smoke',\n bodyBackgroundSecondary: '--bg-secondary-color',\n bodyBackgroundDark: '--bg-dark',\n borderBackground: '--bg-border',\n headerbg: '--header-bg',\n textColor: '--text-color',\n footerBgColor: '--footer-bg',\n footerTextColor: '--footer-text',\n};\n\n/**\n * Updates CSS custom properties on document.documentElement (<html>).\n * Called by EditorProvider when color_scheme or font_styles change.\n *\n * This overwrites the same vars that layout.tsx set on initial SSR,\n * so all SCSS that references var(--primary) etc. updates immediately.\n */\nexport function syncCSSVars(\n colorScheme: ColorSchemeConfig,\n fontStyles: FontStylesConfig,\n overrides?: Record<string, string>\n) {\n const root = document.documentElement;\n const varMap = overrides ? { ...CSS_VAR_MAP, ...overrides } : CSS_VAR_MAP;\n\n // Sync colors\n for (const [configKey, cssVar] of Object.entries(varMap)) {\n const value = (colorScheme as Record<string, any>)[configKey];\n if (value !== undefined && value !== null && value !== '') {\n root.style.setProperty(cssVar, value);\n }\n }\n\n // Sync fonts\n if (fontStyles?.heading) {\n root.style.setProperty('--heading-font', `'${fontStyles.heading.font_family}'`);\n root.style.setProperty('--heading-weight', String(fontStyles.heading.font_weight));\n loadGoogleFont(fontStyles.heading.font_url);\n }\n if (fontStyles?.body) {\n root.style.setProperty('--body-font', `'${fontStyles.body.font_family}'`);\n root.style.setProperty('--body-weight', String(fontStyles.body.font_weight));\n loadGoogleFont(fontStyles.body.font_url);\n }\n}\n\n/** Load a Google Font by injecting a <link> tag. Deduplicates. */\nfunction loadGoogleFont(url: string) {\n if (!url) return;\n if (document.querySelector(`link[href=\"${url}\"]`)) return;\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n document.head.appendChild(link);\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns whether the store is currently running in editor mode.\n * Editor mode is active when the page is loaded inside an iframe with ?editor=true.\n * Returns { isEditorMode: false } when used outside of EditorProvider.\n */\nexport function useEditorMode(): { isEditorMode: boolean } {\n const ctx = useContext(EditorContext);\n return { isEditorMode: ctx?.isEditorMode ?? false };\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\nimport { LandingPageConfig } from '../types/config';\n\n/**\n * Returns the full LandingPageConfig object from EditorContext.\n * In normal mode, this is the original server-fetched config.\n * In editor mode, this is the live-updating copy that reflects changes from the editor SPA.\n * Returns null when used outside of EditorProvider.\n */\nexport function useLandingConfig(): LandingPageConfig | null {\n return useContext(EditorContext)?.config ?? null;\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\nimport { HeroConfig } from '../types/config';\n\n/**\n * Returns the hero banner configuration (title, CTA, images, slider settings).\n * Updates live in editor mode when the editor SPA sends hero changes.\n * Returns null when used outside of EditorProvider.\n */\nexport function useHeroConfig(): HeroConfig | null {\n return useContext(EditorContext)?.config?.hero ?? null;\n}\n","'use client';\n\nimport { useContext, useMemo } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\nimport { SectionItem } from '../types/config';\n\n/**\n * Returns the ordered array of landing page sections from the config.\n * Reflects live reordering, additions, removals, and toggles from the editor SPA.\n * Memoized to prevent unnecessary re-renders when sections haven't changed.\n * Returns an empty array when used outside of EditorProvider.\n */\nexport function useSections(): SectionItem[] {\n const ctx = useContext(EditorContext);\n return useMemo(() => ctx?.config?.sections ?? [], [ctx?.config?.sections]);\n}\n","'use client';\n\nimport { useContext, useMemo } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\nimport { SectionItem } from '../types/config';\n\n/**\n * Finds and returns a single section by its unique ID from the sections array.\n * Memoized to avoid re-computing on every render unless the sections array changes.\n * Returns undefined if no section with the given ID exists.\n *\n * @param sectionId - The unique ID of the section to find (e.g., \"categories-7kvobkg2g\").\n */\nexport function useSectionById(sectionId: string): SectionItem | undefined {\n const ctx = useContext(EditorContext);\n return useMemo(\n () => ctx?.config?.sections.find(s => s.id === sectionId),\n [ctx?.config?.sections, sectionId]\n );\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns the navbar configuration (logo position, cart/wishlist toggles, ribbon bar, nav elements).\n * Updates live in editor mode when the editor SPA sends navbar changes.\n * Returns null when used outside of EditorProvider.\n */\nexport function useNavbarConfig() {\n return useContext(EditorContext)?.config?.navbar ?? null;\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns the footer configuration (social links visibility, contact details, branding toggles).\n * Updates live in editor mode when the editor SPA sends footer changes.\n * Returns null when used outside of EditorProvider.\n */\nexport function useFooterConfig() {\n return useContext(EditorContext)?.config?.footer ?? null;\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns the color scheme configuration (primary, secondary, background, text, footer colors).\n * When these values change in editor mode, EditorProvider also syncs CSS custom properties\n * on <html> for instant visual updates across all SCSS-styled components.\n * Returns null when used outside of EditorProvider.\n */\nexport function useColorScheme() {\n return useContext(EditorContext)?.config?.color_scheme ?? null;\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns the font styles configuration (body and heading font family, weight, and Google Font URL).\n * When fonts change in editor mode, EditorProvider syncs CSS custom properties and dynamically\n * loads the new Google Font via <link> tag injection.\n * Returns null when used outside of EditorProvider.\n */\nexport function useFontStyles() {\n return useContext(EditorContext)?.config?.font_styles ?? null;\n}\n","'use client';\n\nimport { useContext, useMemo } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns branding-related fields (logo, secondary_logo, favicon, store_name, store_description).\n * Memoized to only re-compute when one of these specific fields changes, avoiding unnecessary\n * re-renders when other parts of the config update.\n * Returns null when used outside of EditorProvider.\n */\nexport function useBranding() {\n const ctx = useContext(EditorContext);\n return useMemo(() => {\n if (!ctx?.config) return null;\n const c = ctx.config;\n return {\n logo: c.logo,\n secondary_logo: c.secondary_logo,\n favicon: c.favicon,\n store_name: c.store_name,\n store_description: c.store_description,\n };\n }, [\n ctx?.config?.logo,\n ctx?.config?.secondary_logo,\n ctx?.config?.favicon,\n ctx?.config?.store_name,\n ctx?.config?.store_description,\n ]);\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns social media link URLs (twitter, youtube, facebook, instagram).\n * Updates live in editor mode when the editor SPA sends social link changes.\n * Returns null when used outside of EditorProvider.\n */\nexport function useSocialLinks() {\n return useContext(EditorContext)?.config?.social_links ?? null;\n}\n","'use client';\n\nimport React from 'react';\nimport { useEditorMode } from '../hooks/useEditorMode';\n\nexport interface SectionWrapperProps {\n sectionId: string;\n sectionType: string;\n enabled?: boolean;\n className?: string;\n children: React.ReactNode;\n}\n\n/**\n * Wraps a landing page section with editor-aware behavior.\n *\n * In normal mode: renders children inside a <div> with data-section-id/data-section-type\n * attributes. If enabled=false, returns null (section is hidden from customers).\n *\n * In editor mode: always renders (even disabled sections, shown dimmed at 0.35 opacity).\n * Intercepts clicks and sends a 'store:section-clicked' postMessage to the parent editor SPA,\n * allowing the editor to open the settings panel for the clicked section.\n *\n * @param props.sectionId - Unique section ID from the API (e.g., \"categories-7kvobkg2g\").\n * @param props.sectionType - Section type string (e.g., \"categories\", \"banner\").\n * @param props.enabled - Whether the section is visible. Defaults to true. Disabled sections\n * are hidden in normal mode but shown dimmed in editor mode.\n * @param props.className - Optional additional CSS class names.\n * @param props.children - The actual section component to render inside the wrapper.\n */\nexport function SectionWrapper({\n sectionId,\n sectionType,\n enabled = true,\n className = '',\n children,\n}: SectionWrapperProps) {\n const { isEditorMode } = useEditorMode();\n\n if (!enabled && !isEditorMode) return null;\n\n const handleClick = isEditorMode\n ? (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n window.parent.postMessage(\n { type: 'store:section-clicked', payload: { sectionId } },\n '*'\n );\n }\n : undefined;\n\n return (\n <div\n data-section-id={sectionId}\n data-section-type={sectionType}\n className={`${!enabled && isEditorMode ? 'editor-section-disabled' : ''} ${className}`.trim()}\n onClick={handleClick}\n >\n {children}\n </div>\n );\n}\n"],"mappings":"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","names":["useContext","useContext","useContext","useContext","useContext","useMemo","useContext","useMemo","useContext","useMemo","useContext","useMemo","useContext","useContext","useContext","useContext","useContext","useContext","useContext","useContext","useContext","useMemo","useContext","useMemo","useContext","useContext","jsx"]}
|
|
1
|
+
{"version":3,"sources":["../src/provider/EditorProvider.tsx","../src/provider/EditorContext.ts","../src/provider/config-reducer.ts","../src/css/css-var-sync.ts","../src/hooks/useEditorMode.ts","../src/hooks/useLandingConfig.ts","../src/hooks/useHeroConfig.ts","../src/hooks/useSections.ts","../src/hooks/useSectionById.ts","../src/hooks/useNavbarConfig.ts","../src/hooks/useFooterConfig.ts","../src/hooks/useColorScheme.ts","../src/hooks/useFontStyles.ts","../src/hooks/useBranding.ts","../src/hooks/useSocialLinks.ts","../src/components/SectionWrapper.tsx"],"sourcesContent":["'use client';\n\nimport React, { useReducer, useEffect, useRef, useState, useMemo } from 'react';\nimport { LandingPageConfig } from '../types/config';\nimport { EditorMessage, StoreMessage, SectionPosition } from '../types/messages';\nimport { EditorContext, EditorContextValue } from './EditorContext';\nimport { configReducer, toReducerAction } from './config-reducer';\nimport { syncCSSVars } from '../css/css-var-sync';\n\nexport interface EditorProviderProps {\n /**\n * The config fetched by the Server Component from GET /store/store_settings/.\n * Must be the EXACT JSON shape — no transformation needed.\n */\n initialConfig: LandingPageConfig;\n\n /**\n * Allowed origin for postMessage. Set to the editor SPA domain in production.\n * Default: \"*\" (accepts all — set NEXT_PUBLIC_EDITOR_ORIGIN in production!)\n */\n editorOrigin?: string;\n callBacks? : {\n onChanges?: (config: LandingPageConfig) => void;\n };\n\n /**\n * Optional: custom CSS variable mapping. Override if your theme uses\n * different CSS property names than the default Starter Theme.\n * Map keys are color_scheme field names → values are CSS property names.\n * Example: { primary: '--brand-color', secondary: '--accent-color' }\n */\n cssVarOverrides?: Record<string, string>;\n\n children: React.ReactNode;\n}\n\n/**\n * Core provider component that enables Visual Editor Mode in Snapstore themes.\n *\n * In normal mode (customer visiting the store), this provider is dormant — it passes\n * the server-fetched initialConfig through context unchanged with zero runtime overhead.\n *\n * In editor mode (?editor=true + loaded inside an iframe), it:\n * 1. Activates editor mode and adds 'editor-mode-active' class to <body>\n * 2. Listens for postMessage events from the parent editor SPA\n * 3. Dispatches config changes through the reducer for immutable state updates\n * 4. Syncs CSS custom properties on <html> when colors/fonts change\n * 5. Reports section DOM positions to the editor for overlay alignment\n * 6. Injects editor-specific CSS (hover outlines, disabled interactions)\n *\n * @param props.initialConfig - The full LandingPageConfig from GET /store/landing_page/.\n * @param props.editorOrigin - Allowed postMessage origin. Defaults to \"*\"; set in production.\n * @param props.cssVarOverrides - Optional map to override default CSS variable name mappings.\n * @param props.children - Child components that consume editor context via hooks.\n */\nexport function EditorProvider({\n initialConfig,\n editorOrigin = '*',\n cssVarOverrides,\n children,\n callBacks,\n}: EditorProviderProps) {\n const [isEditorMode, setIsEditorMode] = useState(false);\n const [config, dispatch] = useReducer(configReducer, initialConfig);\n const positionTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const prevColorRef = useRef(initialConfig.color_scheme);\n const prevFontRef = useRef(initialConfig.font_styles);\n\n // ── 1. Detect editor mode ──\n useEffect(() => {\n if (typeof window === 'undefined') return;\n const params = new URLSearchParams(window.location.search);\n const inIframe = window.self !== window.top;\n if (inIframe && params.get('editor') === 'true') {\n setIsEditorMode(true);\n document.body.classList.add('editor-mode-active');\n }\n return () => {\n document.body.classList.remove('editor-mode-active');\n };\n }, []);\n\n // ── 2. Listen for postMessages ──\n useEffect(() => {\n if (!isEditorMode) return;\n\n const handler = (event: MessageEvent) => {\n if (editorOrigin !== '*' && event.origin !== editorOrigin) return;\n const msg = event.data as EditorMessage;\n if (!msg?.type?.startsWith('editor:')) return;\n\n // Navigation is handled outside reducer (side effect)\n if (msg.type === 'editor:navigate') {\n const url = new URL(msg.payload.url, window.location.origin);\n url.searchParams.set('editor', 'true');\n window.location.href = url.toString();\n return;\n }\n\n // Highlight is a DOM operation, not a state change\n if (msg.type === 'editor:highlight-section') {\n document.querySelectorAll('[data-section-id]').forEach(el => {\n el.classList.toggle(\n 'editor-section-highlight',\n el.getAttribute('data-section-id') === msg.payload.sectionId\n );\n });\n return;\n }\n\n // Everything else goes through the reducer\n const action = toReducerAction(msg);\n if (action) dispatch(action);\n };\n\n window.addEventListener('message', handler);\n return () => window.removeEventListener('message', handler);\n }, [isEditorMode, editorOrigin]);\n\n // ── 3. Send store:ready ──\n useEffect(() => {\n if (!isEditorMode) return;\n const timer = setTimeout(() => {\n sendToEditor({\n type: 'store:ready',\n payload: { sections: getSectionPositions() },\n });\n }, 600);\n return () => clearTimeout(timer);\n }, [isEditorMode]);\n\n // ── 4. Sync CSS vars when color_scheme or font_styles change ──\n useEffect(() => {\n if (!isEditorMode) return;\n if (\n config.color_scheme !== prevColorRef.current ||\n config.font_styles !== prevFontRef.current\n ) {\n syncCSSVars(config.color_scheme, config.font_styles, cssVarOverrides);\n prevColorRef.current = config.color_scheme;\n prevFontRef.current = config.font_styles;\n }\n }, [isEditorMode, config.color_scheme, config.font_styles, cssVarOverrides]);\n\n // ── 5. Report section positions after re-render ──\n useEffect(() => {\n if (!isEditorMode) return;\n if (positionTimerRef.current) clearTimeout(positionTimerRef.current);\n positionTimerRef.current = setTimeout(() => {\n sendToEditor({\n type: 'store:sections-updated',\n payload: { sections: getSectionPositions() },\n });\n }, 300);\n }, [config.sections, config.hero, isEditorMode]);\n\n // ── Context value ──\n const value = useMemo<EditorContextValue>(\n () => ({ isEditorMode, config }),\n [isEditorMode, config]\n );\n\n return (\n <EditorContext.Provider value={value}>\n {isEditorMode && <EditorStylesInline />}\n {children}\n </EditorContext.Provider>\n );\n}\n\n// ── Helpers ──\n\n/**\n * Sends a message from the store iframe to the parent editor SPA via postMessage.\n * No-ops silently if not running in an iframe or if window is undefined (SSR).\n *\n * @param message - The StoreMessage to send (e.g., store:ready, store:section-clicked).\n */\nfunction sendToEditor(message: StoreMessage) {\n if (typeof window === 'undefined' || window.self === window.top) return;\n window.parent.postMessage(message, '*');\n}\n\n/**\n * Queries the DOM for all elements with a `data-section-id` attribute (rendered by SectionWrapper)\n * and returns their current bounding rectangles. The editor SPA uses these positions to align\n * its overlay UI (selection outlines, drag handles) with the preview iframe content.\n *\n * @returns An array of SectionPosition objects with id, type, and bounding rect for each section.\n */\nfunction getSectionPositions(): SectionPosition[] {\n return Array.from(document.querySelectorAll('[data-section-id]')).map(el => ({\n id: el.getAttribute('data-section-id')!,\n type: el.getAttribute('data-section-type') || '',\n rect: el.getBoundingClientRect(),\n }));\n}\n\n/**\n * Renders inline <style> tag with editor-mode-only CSS rules. Only mounted when editor mode is active.\n * These styles:\n * 1. Add hover/highlight outlines on section wrappers for visual feedback\n * 2. Dim disabled sections (opacity 0.35) so merchants can see they're toggled off\n * 3. Disable pointer events on all interactive elements (links, buttons, forms, inputs)\n * to prevent accidental navigation while editing\n * 4. Re-enable pointer events on editor click overlays so section clicks still register\n */\nfunction EditorStylesInline() {\n return (\n <style>{`\n [data-section-id] {\n position: relative;\n transition: outline 0.15s ease;\n }\n [data-section-id]:hover {\n outline: 2px solid rgba(59, 130, 246, 0.5);\n outline-offset: -2px;\n cursor: pointer;\n }\n .editor-section-highlight {\n outline: 2px solid #3b82f6 !important;\n outline-offset: -2px;\n }\n .editor-section-disabled {\n opacity: 0.35;\n }\n .editor-mode-active a,\n .editor-mode-active button:not([data-editor-control]),\n .editor-mode-active input,\n .editor-mode-active select,\n .editor-mode-active form,\n .editor-mode-active textarea {\n pointer-events: none !important;\n }\n [data-section-id] > .editor-click-overlay {\n pointer-events: auto !important;\n }\n `}</style>\n );\n}\n","'use client';\n\nimport { createContext } from 'react';\nimport { LandingPageConfig } from '../types/config';\n\n/**\n * Shape of the value provided by EditorContext.\n * - isEditorMode: Whether the store is running inside the editor iframe with ?editor=true.\n * - config: The current LandingPageConfig — either the original server-fetched config\n * (normal mode) or a live-updating copy managed by the config reducer (editor mode).\n */\nexport interface EditorContextValue {\n isEditorMode: boolean;\n config: LandingPageConfig;\n}\n\n/**\n * React Context that holds the editor state. Consumed by all useXxxConfig hooks.\n * Defaults to null when no EditorProvider is present in the component tree.\n */\nexport const EditorContext = createContext<EditorContextValue | null>(null);\n","import {\n LandingPageConfig,\n Section,\n HeroConfig,\n SliderSlide,\n NavElement,\n RibbonBarConfig,\n ColorSchemeConfig,\n FooterConfig,\n FontStylesConfig,\n SocialLinksConfig,\n} from '../types/config';\nimport { EditorMessage } from '../types/messages';\n\n// ── Action types ──\n\nexport type EditorAction =\n | { type: 'FULL_REPLACE'; config: LandingPageConfig }\n | { type: 'UPDATE_PATH'; path: string; value: any }\n | { type: 'HERO_UPDATE'; data: Partial<HeroConfig> }\n | { type: 'HERO_SLIDE_ADD'; slide: SliderSlide; position: number }\n | { type: 'HERO_SLIDE_REMOVE'; slideId: string }\n | { type: 'HERO_SLIDES_REORDER'; slideIds: string[] }\n | { type: 'HERO_SLIDE_UPDATE'; slideId: string; data: Partial<SliderSlide> }\n | { type: 'SECTIONS_REORDER'; sectionIds: string[] }\n | { type: 'SECTION_ADD'; section: Section; position: number }\n | { type: 'SECTION_REMOVE'; sectionId: string }\n | { type: 'SECTION_TOGGLE'; sectionId: string; enabled: boolean }\n | { type: 'SECTION_UPDATE'; sectionId: string; data: Partial<Section> }\n | { type: 'NAVBAR_UPDATE'; data: Partial<LandingPageConfig['navbar']> }\n | { type: 'NAVBAR_RIBBON_UPDATE'; data: Partial<RibbonBarConfig> }\n | { type: 'NAVBAR_RIBBON_MSG_ADD'; message: { link: string; message: string }; position: number }\n | { type: 'NAVBAR_RIBBON_MSG_REMOVE'; index: number }\n | { type: 'NAVBAR_RIBBON_MSGS_REORDER'; messages: Array<{ link: string; message: string }> }\n | { type: 'NAVBAR_ELEMENT_UPDATE'; key: string; data: Partial<NavElement> }\n | { type: 'NAVBAR_ELEMENT_ADD'; element: NavElement; position: number }\n | { type: 'NAVBAR_ELEMENT_REMOVE'; key: string }\n | { type: 'NAVBAR_ELEMENTS_REORDER'; elements: NavElement[] }\n | { type: 'FOOTER_UPDATE'; data: Partial<FooterConfig> }\n | { type: 'COLOR_SCHEME_UPDATE'; data: Partial<ColorSchemeConfig> }\n | { type: 'FONT_STYLES_UPDATE'; data: { body?: Partial<FontStylesConfig['body']>; heading?: Partial<FontStylesConfig['heading']> } }\n | { type: 'SOCIAL_LINKS_UPDATE'; data: Partial<SocialLinksConfig> }\n | { type: 'BRANDING_UPDATE'; data: Partial<Pick<LandingPageConfig, 'logo' | 'secondary_logo' | 'favicon' | 'store_name' | 'store_description'>> }\n | { type: 'ADVANCED_UPDATE'; data: Partial<Pick<LandingPageConfig, 'custom_css' | 'custom_js' | 'start_head_tag' | 'end_head_tag' | 'start_body_tag' | 'end_body_tag' | 'google_tag_manager_id' | 'facebook_pixel_id'>> };\n\n// ── Message → Action mapper ──\n\n/**\n * Converts an incoming EditorMessage (from postMessage) into a reducer-compatible EditorAction.\n * Maps each `editor:*` message type to its corresponding internal action type.\n * Returns null for unrecognized message types, which are silently ignored.\n *\n * @param msg - The postMessage event data received from the editor SPA.\n * @returns The corresponding EditorAction to dispatch, or null if the message type is unknown.\n */\nexport function toReducerAction(msg: EditorMessage): EditorAction | null {\n switch (msg.type) {\n case 'editor:init':\n case 'editor:full-replace':\n return { type: 'FULL_REPLACE', config: msg.payload.config };\n case 'editor:update':\n return { type: 'UPDATE_PATH', path: msg.payload.path, value: msg.payload.value };\n case 'editor:hero-update':\n return { type: 'HERO_UPDATE', data: msg.payload };\n case 'editor:hero-slide-add':\n return { type: 'HERO_SLIDE_ADD', slide: msg.payload.slide, position: msg.payload.position };\n case 'editor:hero-slide-remove':\n return { type: 'HERO_SLIDE_REMOVE', slideId: msg.payload.slideId };\n case 'editor:hero-slides-reorder':\n return { type: 'HERO_SLIDES_REORDER', slideIds: msg.payload.slideIds };\n case 'editor:hero-slide-update':\n return { type: 'HERO_SLIDE_UPDATE', slideId: msg.payload.slideId, data: msg.payload.data };\n case 'editor:sections-reorder':\n return { type: 'SECTIONS_REORDER', sectionIds: msg.payload.sectionIds };\n case 'editor:section-add':\n return { type: 'SECTION_ADD', section: msg.payload.section, position: msg.payload.position };\n case 'editor:section-remove':\n return { type: 'SECTION_REMOVE', sectionId: msg.payload.sectionId };\n case 'editor:section-toggle':\n return { type: 'SECTION_TOGGLE', sectionId: msg.payload.sectionId, enabled: msg.payload.enabled };\n case 'editor:section-update':\n return { type: 'SECTION_UPDATE', sectionId: msg.payload.sectionId, data: msg.payload.data };\n case 'editor:navbar-update':\n return { type: 'NAVBAR_UPDATE', data: msg.payload };\n case 'editor:navbar-ribbon-update':\n return { type: 'NAVBAR_RIBBON_UPDATE', data: msg.payload };\n case 'editor:navbar-ribbon-message-add':\n return { type: 'NAVBAR_RIBBON_MSG_ADD', message: msg.payload.message, position: msg.payload.position };\n case 'editor:navbar-ribbon-message-remove':\n return { type: 'NAVBAR_RIBBON_MSG_REMOVE', index: msg.payload.index };\n case 'editor:navbar-ribbon-messages-reorder':\n return { type: 'NAVBAR_RIBBON_MSGS_REORDER', messages: msg.payload.messages };\n case 'editor:navbar-element-update':\n return { type: 'NAVBAR_ELEMENT_UPDATE', key: msg.payload.key, data: msg.payload.data };\n case 'editor:navbar-element-add':\n return { type: 'NAVBAR_ELEMENT_ADD', element: msg.payload.element, position: msg.payload.position };\n case 'editor:navbar-element-remove':\n return { type: 'NAVBAR_ELEMENT_REMOVE', key: msg.payload.key };\n case 'editor:navbar-elements-reorder':\n return { type: 'NAVBAR_ELEMENTS_REORDER', elements: msg.payload.elements };\n case 'editor:footer-update':\n return { type: 'FOOTER_UPDATE', data: msg.payload };\n case 'editor:color-scheme-update':\n return { type: 'COLOR_SCHEME_UPDATE', data: msg.payload };\n case 'editor:font-styles-update':\n return { type: 'FONT_STYLES_UPDATE', data: msg.payload };\n case 'editor:social-links-update':\n return { type: 'SOCIAL_LINKS_UPDATE', data: msg.payload };\n case 'editor:branding-update':\n return { type: 'BRANDING_UPDATE', data: msg.payload };\n case 'editor:advanced-update':\n return { type: 'ADVANCED_UPDATE', data: msg.payload };\n default:\n return null;\n }\n}\n\n// ── Reducer ──\n\n/**\n * Pure reducer that produces the next LandingPageConfig state from the current state and an action.\n * Handles all 25 action types covering hero, sections, navbar, footer, colors, fonts, branding,\n * social links, and advanced settings. All updates are immutable — returns a new object reference\n * on change, or the same reference if the action is unknown.\n *\n * @param state - The current LandingPageConfig state.\n * @param action - The EditorAction describing the state transition.\n * @returns A new LandingPageConfig with the action applied, or the same state if action is unknown.\n */\nexport function configReducer(state: LandingPageConfig, action: EditorAction): LandingPageConfig {\n switch (action.type) {\n case 'FULL_REPLACE':\n return action.config;\n\n case 'UPDATE_PATH':\n return setByPath(state, action.path, action.value);\n\n // ── Hero ──\n\n case 'HERO_UPDATE':\n return { ...state, hero: { ...state.hero, ...action.data } };\n\n case 'HERO_SLIDE_ADD': {\n const slides = [...state.hero.sliderSettings];\n slides.splice(action.position, 0, action.slide);\n return { ...state, hero: { ...state.hero, sliderSettings: slides } };\n }\n\n case 'HERO_SLIDE_REMOVE':\n return {\n ...state,\n hero: {\n ...state.hero,\n sliderSettings: state.hero.sliderSettings.filter(s => s.id !== action.slideId),\n },\n };\n\n case 'HERO_SLIDES_REORDER': {\n const reordered = action.slideIds\n .map(id => state.hero.sliderSettings.find(s => s.id === id))\n .filter(Boolean) as SliderSlide[];\n return { ...state, hero: { ...state.hero, sliderSettings: reordered } };\n }\n\n case 'HERO_SLIDE_UPDATE':\n return {\n ...state,\n hero: {\n ...state.hero,\n sliderSettings: state.hero.sliderSettings.map(s =>\n s.id === action.slideId ? { ...s, ...action.data } : s\n ),\n },\n };\n\n // ── Sections ──\n\n case 'SECTIONS_REORDER': {\n const reordered = action.sectionIds\n .map(id => state.sections.find(s => s.id === id))\n .filter(Boolean) as Section[];\n return { ...state, sections: reordered };\n }\n\n case 'SECTION_ADD': {\n const sections = [...state.sections];\n sections.splice(action.position, 0, action.section);\n return { ...state, sections };\n }\n\n case 'SECTION_REMOVE':\n return { ...state, sections: state.sections.filter(s => s.id !== action.sectionId) };\n\n case 'SECTION_TOGGLE':\n return {\n ...state,\n sections: state.sections.map(s =>\n s.id === action.sectionId ? { ...s, enabled: action.enabled } as Section : s\n ),\n };\n\n case 'SECTION_UPDATE':\n return {\n ...state,\n sections: state.sections.map(s =>\n s.id === action.sectionId ? { ...s, ...action.data } as Section : s\n ),\n };\n\n // ── Navbar ──\n\n case 'NAVBAR_UPDATE': {\n const { ribbonbar, navElements, ...rest } = action.data;\n let navbar = { ...state.navbar, ...rest };\n if (ribbonbar) navbar = { ...navbar, ribbonbar: { ...navbar.ribbonbar, ...ribbonbar } };\n if (navElements) navbar = { ...navbar, navElements };\n return { ...state, navbar };\n }\n\n case 'NAVBAR_RIBBON_UPDATE':\n return {\n ...state,\n navbar: {\n ...state.navbar,\n ribbonbar: { ...state.navbar.ribbonbar, ...action.data },\n },\n };\n\n case 'NAVBAR_RIBBON_MSG_ADD': {\n const messages = [...state.navbar.ribbonbar.messages];\n messages.splice(action.position, 0, action.message);\n return {\n ...state,\n navbar: {\n ...state.navbar,\n ribbonbar: { ...state.navbar.ribbonbar, messages },\n },\n };\n }\n\n case 'NAVBAR_RIBBON_MSG_REMOVE': {\n const messages = state.navbar.ribbonbar.messages.filter((_, i) => i !== action.index);\n return {\n ...state,\n navbar: {\n ...state.navbar,\n ribbonbar: { ...state.navbar.ribbonbar, messages },\n },\n };\n }\n\n case 'NAVBAR_RIBBON_MSGS_REORDER':\n return {\n ...state,\n navbar: {\n ...state.navbar,\n ribbonbar: { ...state.navbar.ribbonbar, messages: action.messages },\n },\n };\n\n case 'NAVBAR_ELEMENT_UPDATE':\n return {\n ...state,\n navbar: {\n ...state.navbar,\n navElements: state.navbar.navElements.map(el =>\n el.key === action.key ? { ...el, ...action.data } : el\n ),\n },\n };\n\n case 'NAVBAR_ELEMENT_ADD': {\n const navElements = [...state.navbar.navElements];\n navElements.splice(action.position, 0, action.element);\n return { ...state, navbar: { ...state.navbar, navElements } };\n }\n\n case 'NAVBAR_ELEMENT_REMOVE':\n return {\n ...state,\n navbar: {\n ...state.navbar,\n navElements: state.navbar.navElements.filter(el => el.key !== action.key),\n },\n };\n\n case 'NAVBAR_ELEMENTS_REORDER':\n return { ...state, navbar: { ...state.navbar, navElements: action.elements } };\n\n // ── Top-level ──\n\n case 'FOOTER_UPDATE':\n return { ...state, footer: { ...state.footer, ...action.data } };\n\n case 'COLOR_SCHEME_UPDATE':\n return { ...state, color_scheme: { ...state.color_scheme, ...action.data } };\n\n case 'FONT_STYLES_UPDATE': {\n const font_styles = { ...state.font_styles };\n if (action.data.body) font_styles.body = { ...font_styles.body, ...action.data.body };\n if (action.data.heading) font_styles.heading = { ...font_styles.heading, ...action.data.heading };\n return { ...state, font_styles };\n }\n\n case 'SOCIAL_LINKS_UPDATE':\n return { ...state, social_links: { ...state.social_links, ...action.data } };\n\n case 'BRANDING_UPDATE':\n return { ...state, ...action.data };\n\n case 'ADVANCED_UPDATE':\n return { ...state, ...action.data };\n\n default:\n return state;\n }\n}\n\n// ── Helpers ──\n\n/**\n * Immutably sets a value at a dot-notation path within a nested object.\n * Creates shallow copies at each level of nesting to preserve immutability.\n * If intermediate keys don't exist, empty objects are created.\n *\n * @param obj - The source object to update.\n * @param path - Dot-notation path (e.g., \"hero.title\" or \"navbar.ribbonbar.animation\").\n * @param value - The value to set at the specified path.\n * @returns A new object with the value set at the given path.\n *\n * @example\n * setByPath({ hero: { title: 'Old' } }, 'hero.title', 'New')\n * // => { hero: { title: 'New' } }\n */\nfunction setByPath(obj: any, path: string, value: any): any {\n const keys = path.split('.');\n if (keys.length === 1) return { ...obj, [keys[0]]: value };\n const [head, ...tail] = keys;\n return { ...obj, [head]: setByPath(obj[head] ?? {}, tail.join('.'), value) };\n}\n","import { ColorSchemeConfig, FontStylesConfig } from '../types/config';\n\n/**\n * Default mapping: color_scheme field name → CSS custom property name.\n * These match what app/layout.tsx injects on <html style=\"...\">.\n *\n * VERIFY against the actual layout.tsx in your theme!\n * If your theme uses --brand-primary instead of --primary, pass\n * cssVarOverrides to EditorProvider.\n */\nexport const CSS_VAR_MAP: Record<string, string> = {\n primary: '--primary',\n secondary: '--secondary',\n btnText: '--btn-text',\n textPrimary: '--text-primary',\n textSecondary: '--text-secondary',\n bodyBackground: '--bg-primary',\n bodyBackground1: '--bg-primary-smoke',\n bodyBackgroundSecondary: '--bg-secondary-color',\n bodyBackgroundDark: '--bg-dark',\n borderBackground: '--bg-border',\n headerbg: '--header-bg',\n textColor: '--text-color',\n footerBgColor: '--footer-bg',\n footerTextColor: '--footer-text',\n};\n\n/**\n * Updates CSS custom properties on document.documentElement (<html>).\n * Called by EditorProvider when color_scheme or font_styles change.\n *\n * This overwrites the same vars that layout.tsx set on initial SSR,\n * so all SCSS that references var(--primary) etc. updates immediately.\n */\nexport function syncCSSVars(\n colorScheme: ColorSchemeConfig,\n fontStyles: FontStylesConfig,\n overrides?: Record<string, string>\n) {\n const root = document.documentElement;\n const varMap = overrides ? { ...CSS_VAR_MAP, ...overrides } : CSS_VAR_MAP;\n\n\n // Sync colors\n for (const [configKey, cssVar] of Object.entries(varMap)) {\n if(!colorScheme) return;\n const value = (colorScheme as Record<string, any>)[configKey];\n if (value !== undefined && value !== null && value !== '') {\n root.style.setProperty(cssVar, value);\n }\n }\n\n // Sync fonts\n if (fontStyles?.heading) {\n root.style.setProperty('--heading-font', `'${fontStyles.heading.font_family}'`);\n root.style.setProperty('--heading-weight', String(fontStyles.heading.font_weight));\n loadGoogleFont(fontStyles.heading.font_url);\n }\n if (fontStyles?.body) {\n root.style.setProperty('--body-font', `'${fontStyles.body.font_family}'`);\n root.style.setProperty('--body-weight', String(fontStyles.body.font_weight));\n loadGoogleFont(fontStyles.body.font_url);\n }\n}\n\n/** Load a Google Font by injecting a <link> tag. Deduplicates. */\nfunction loadGoogleFont(url: string) {\n if (!url) return;\n if (document.querySelector(`link[href=\"${url}\"]`)) return;\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n document.head.appendChild(link);\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns whether the store is currently running in editor mode.\n * Editor mode is active when the page is loaded inside an iframe with ?editor=true.\n * Returns { isEditorMode: false } when used outside of EditorProvider.\n */\nexport function useEditorMode(): { isEditorMode: boolean } {\n const ctx = useContext(EditorContext);\n return { isEditorMode: ctx?.isEditorMode ?? false };\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\nimport { LandingPageConfig } from '../types/config';\n\n/**\n * Returns the full LandingPageConfig object from EditorContext.\n * In normal mode, this is the original server-fetched config.\n * In editor mode, this is the live-updating copy that reflects changes from the editor SPA.\n * Returns null when used outside of EditorProvider.\n */\nexport function useLandingConfig(): LandingPageConfig | null {\n return useContext(EditorContext)?.config ?? null;\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\nimport { HeroConfig } from '../types/config';\n\n/**\n * Returns the hero banner configuration (title, CTA, images, slider settings).\n * Updates live in editor mode when the editor SPA sends hero changes.\n * Returns null when used outside of EditorProvider.\n */\nexport function useHeroConfig(): HeroConfig | null {\n return useContext(EditorContext)?.config?.hero ?? null;\n}\n","'use client';\n\nimport { useContext, useMemo } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\nimport { Section } from '../types/config';\n\n/**\n * Returns the ordered array of landing page sections from the config.\n * Reflects live reordering, additions, removals, and toggles from the editor SPA.\n * Memoized to prevent unnecessary re-renders when sections haven't changed.\n * Returns an empty array when used outside of EditorProvider.\n */\nexport function useSections(): Section[] {\n const ctx = useContext(EditorContext);\n return useMemo(() => ctx?.config?.sections ?? [], [ctx?.config?.sections]);\n}\n","'use client';\n\nimport { useContext, useMemo } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\nimport { Section } from '../types/config';\n\n/**\n * Finds and returns a single section by its unique ID from the sections array.\n * Memoized to avoid re-computing on every render unless the sections array changes.\n * Returns undefined if no section with the given ID exists.\n *\n * @param sectionId - The unique ID of the section to find (e.g., \"categories-7kvobkg2g\").\n */\nexport function useSectionById(sectionId: string): Section | undefined {\n const ctx = useContext(EditorContext);\n return useMemo(\n () => ctx?.config?.sections.find(s => s.id === sectionId),\n [ctx?.config?.sections, sectionId]\n );\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns the navbar configuration (logo position, cart/wishlist toggles, ribbon bar, nav elements).\n * Updates live in editor mode when the editor SPA sends navbar changes.\n * Returns null when used outside of EditorProvider.\n */\nexport function useNavbarConfig() {\n return useContext(EditorContext)?.config?.navbar ?? null;\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns the footer configuration (social links visibility, contact details, branding toggles).\n * Updates live in editor mode when the editor SPA sends footer changes.\n * Returns null when used outside of EditorProvider.\n */\nexport function useFooterConfig() {\n return useContext(EditorContext)?.config?.footer ?? null;\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns the color scheme configuration (primary, secondary, background, text, footer colors).\n * When these values change in editor mode, EditorProvider also syncs CSS custom properties\n * on <html> for instant visual updates across all SCSS-styled components.\n * Returns null when used outside of EditorProvider.\n */\nexport function useColorScheme() {\n return useContext(EditorContext)?.config?.color_scheme ?? null;\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns the font styles configuration (body and heading font family, weight, and Google Font URL).\n * When fonts change in editor mode, EditorProvider syncs CSS custom properties and dynamically\n * loads the new Google Font via <link> tag injection.\n * Returns null when used outside of EditorProvider.\n */\nexport function useFontStyles() {\n return useContext(EditorContext)?.config?.font_styles ?? null;\n}\n","'use client';\n\nimport { useContext, useMemo } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns branding-related fields (logo, secondary_logo, favicon, store_name, store_description).\n * Memoized to only re-compute when one of these specific fields changes, avoiding unnecessary\n * re-renders when other parts of the config update.\n * Returns null when used outside of EditorProvider.\n */\nexport function useBranding() {\n const ctx = useContext(EditorContext);\n return useMemo(() => {\n if (!ctx?.config) return null;\n const c = ctx.config;\n return {\n logo: c.logo,\n secondary_logo: c.secondary_logo,\n favicon: c.favicon,\n store_name: c.store_name,\n store_description: c.store_description,\n };\n }, [\n ctx?.config?.logo,\n ctx?.config?.secondary_logo,\n ctx?.config?.favicon,\n ctx?.config?.store_name,\n ctx?.config?.store_description,\n ]);\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { EditorContext } from '../provider/EditorContext';\n\n/**\n * Returns social media link URLs (twitter, youtube, facebook, instagram).\n * Updates live in editor mode when the editor SPA sends social link changes.\n * Returns null when used outside of EditorProvider.\n */\nexport function useSocialLinks() {\n return useContext(EditorContext)?.config?.social_links ?? null;\n}\n","'use client';\n\nimport React from 'react';\nimport { useEditorMode } from '../hooks/useEditorMode';\n\nexport interface SectionWrapperProps {\n sectionId: string;\n sectionType: string;\n enabled?: boolean;\n className?: string;\n children: React.ReactNode;\n}\n\n/**\n * Wraps a landing page section with editor-aware behavior.\n *\n * In normal mode: renders children inside a <div> with data-section-id/data-section-type\n * attributes. If enabled=false, returns null (section is hidden from customers).\n *\n * In editor mode: always renders (even disabled sections, shown dimmed at 0.35 opacity).\n * Intercepts clicks and sends a 'store:section-clicked' postMessage to the parent editor SPA,\n * allowing the editor to open the settings panel for the clicked section.\n *\n * @param props.sectionId - Unique section ID from the API (e.g., \"categories-7kvobkg2g\").\n * @param props.sectionType - Section type string (e.g., \"categories\", \"banner\").\n * @param props.enabled - Whether the section is visible. Defaults to true. Disabled sections\n * are hidden in normal mode but shown dimmed in editor mode.\n * @param props.className - Optional additional CSS class names.\n * @param props.children - The actual section component to render inside the wrapper.\n */\nexport function SectionWrapper({\n sectionId,\n sectionType,\n enabled = true,\n className = '',\n children,\n}: SectionWrapperProps) {\n const { isEditorMode } = useEditorMode();\n\n if (!enabled && !isEditorMode) return null;\n\n const handleClick = isEditorMode\n ? (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n window.parent.postMessage(\n { type: 'store:section-clicked', payload: { sectionId } },\n '*'\n );\n }\n : undefined;\n\n return (\n <div\n data-section-id={sectionId}\n data-section-type={sectionType}\n className={`${!enabled && isEditorMode ? 'editor-section-disabled' : ''} ${className}`.trim()}\n onClick={handleClick}\n >\n {children}\n </div>\n );\n}\n"],"mappings":"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","names":["useContext","useContext","useContext","useContext","useContext","useMemo","useContext","useMemo","useContext","useMemo","useContext","useMemo","useContext","useContext","useContext","useContext","useContext","useContext","useContext","useContext","useContext","useMemo","useContext","useMemo","useContext","useContext","jsx"]}
|