@storepecker/editor-bridge 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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?: string;
115
- description?: string;
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
- * A section in the landing page sections[] array.
145
- * The `type` field determines which component renders it.
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: string;
148
+ type: FilterType;
149
+ label: string;
150
+ condition: FilterOption;
151
+ value: string | string[];
152
+ }
153
+ interface ProductCollection {
154
+ type: 'product-collection';
152
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';
203
+ title?: string;
204
+ id?: string;
205
+ categories: any[];
206
+ enabled?: boolean;
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[];
153
242
  enabled?: boolean;
154
- [key: string]: any;
155
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
  /**
@@ -241,7 +333,7 @@ declare function useHeroConfig(): HeroConfig | null;
241
333
  * Memoized to prevent unnecessary re-renders when sections haven't changed.
242
334
  * Returns an empty array when used outside of EditorProvider.
243
335
  */
244
- declare function useSections(): SectionItem[];
336
+ declare function useSections(): Section[];
245
337
 
246
338
  /**
247
339
  * Finds and returns a single section by its unique ID from the sections array.
@@ -250,7 +342,7 @@ declare function useSections(): SectionItem[];
250
342
  *
251
343
  * @param sectionId - The unique ID of the section to find (e.g., "categories-7kvobkg2g").
252
344
  */
253
- declare function useSectionById(sectionId: string): SectionItem | undefined;
345
+ declare function useSectionById(sectionId: string): Section | undefined;
254
346
 
255
347
  /**
256
348
  * Returns the navbar configuration (logo position, cart/wishlist toggles, ribbon bar, nav elements).
@@ -401,7 +493,7 @@ type EditorMessage = {
401
493
  } | {
402
494
  type: 'editor:section-add';
403
495
  payload: {
404
- section: SectionItem;
496
+ section: Section;
405
497
  position: number;
406
498
  };
407
499
  } | {
@@ -419,7 +511,7 @@ type EditorMessage = {
419
511
  type: 'editor:section-update';
420
512
  payload: {
421
513
  sectionId: string;
422
- data: Partial<SectionItem>;
514
+ data: Partial<Section>;
423
515
  };
424
516
  } | {
425
517
  type: 'editor:navbar-update';
@@ -553,4 +645,4 @@ declare const CSS_VAR_MAP: Record<string, string>;
553
645
  */
554
646
  declare function syncCSSVars(colorScheme: ColorSchemeConfig, fontStyles: FontStylesConfig, overrides?: Record<string, string>): void;
555
647
 
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 };
648
+ 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?: string;
115
- description?: string;
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
- * A section in the landing page sections[] array.
145
- * The `type` field determines which component renders it.
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: string;
148
+ type: FilterType;
149
+ label: string;
150
+ condition: FilterOption;
151
+ value: string | string[];
152
+ }
153
+ interface ProductCollection {
154
+ type: 'product-collection';
152
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';
203
+ title?: string;
204
+ id?: string;
205
+ categories: any[];
206
+ enabled?: boolean;
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[];
153
242
  enabled?: boolean;
154
- [key: string]: any;
155
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
  /**
@@ -241,7 +333,7 @@ declare function useHeroConfig(): HeroConfig | null;
241
333
  * Memoized to prevent unnecessary re-renders when sections haven't changed.
242
334
  * Returns an empty array when used outside of EditorProvider.
243
335
  */
244
- declare function useSections(): SectionItem[];
336
+ declare function useSections(): Section[];
245
337
 
246
338
  /**
247
339
  * Finds and returns a single section by its unique ID from the sections array.
@@ -250,7 +342,7 @@ declare function useSections(): SectionItem[];
250
342
  *
251
343
  * @param sectionId - The unique ID of the section to find (e.g., "categories-7kvobkg2g").
252
344
  */
253
- declare function useSectionById(sectionId: string): SectionItem | undefined;
345
+ declare function useSectionById(sectionId: string): Section | undefined;
254
346
 
255
347
  /**
256
348
  * Returns the navbar configuration (logo position, cart/wishlist toggles, ribbon bar, nav elements).
@@ -401,7 +493,7 @@ type EditorMessage = {
401
493
  } | {
402
494
  type: 'editor:section-add';
403
495
  payload: {
404
- section: SectionItem;
496
+ section: Section;
405
497
  position: number;
406
498
  };
407
499
  } | {
@@ -419,7 +511,7 @@ type EditorMessage = {
419
511
  type: 'editor:section-update';
420
512
  payload: {
421
513
  sectionId: string;
422
- data: Partial<SectionItem>;
514
+ data: Partial<Section>;
423
515
  };
424
516
  } | {
425
517
  type: 'editor:navbar-update';
@@ -553,4 +645,4 @@ declare const CSS_VAR_MAP: Record<string, string>;
553
645
  */
554
646
  declare function syncCSSVars(colorScheme: ColorSchemeConfig, fontStyles: FontStylesConfig, overrides?: Record<string, string>): void;
555
647
 
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 };
648
+ 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.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\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 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 // 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 { 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"]}
@@ -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\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 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 // 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 { 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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storepecker/editor-bridge",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "Visual editor bridge for Snapstore themes",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",