@akinon/projectzero 2.0.0-beta.19 → 2.0.0-beta.20
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/CHANGELOG.md +9 -7
- package/app-template/CHANGELOG.md +251 -204
- package/app-template/akinon.json +1 -1
- package/app-template/package.json +28 -28
- package/app-template/public/amex.svg +12 -0
- package/app-template/public/apple-pay.svg +16 -0
- package/app-template/public/assets/images/product-placeholder-1.jpg +0 -0
- package/app-template/public/assets/images/product-placeholder-2.jpg +0 -0
- package/app-template/public/assets/images/product-placeholder-3.jpg +0 -0
- package/app-template/public/assets/images/product-placeholder-4.jpg +0 -0
- package/app-template/public/google-pay.svg +16 -0
- package/app-template/public/locales/en/account.json +6 -3
- package/app-template/public/locales/en/auth.json +6 -7
- package/app-template/public/locales/en/basket.json +6 -6
- package/app-template/public/locales/en/blog.json +7 -0
- package/app-template/public/locales/en/category.json +3 -1
- package/app-template/public/locales/en/checkout.json +5 -4
- package/app-template/public/locales/en/common.json +11 -2
- package/app-template/public/locales/en/forgot_password.json +6 -7
- package/app-template/public/locales/en/product.json +4 -3
- package/app-template/public/locales/tr/account.json +6 -3
- package/app-template/public/locales/tr/auth.json +16 -17
- package/app-template/public/locales/tr/basket.json +4 -4
- package/app-template/public/locales/tr/blog.json +7 -0
- package/app-template/public/locales/tr/category.json +3 -1
- package/app-template/public/locales/tr/checkout.json +39 -38
- package/app-template/public/locales/tr/common.json +10 -1
- package/app-template/public/locales/tr/forgot_password.json +12 -13
- package/app-template/public/locales/tr/product.json +1 -0
- package/app-template/public/logo.svg +3 -27
- package/app-template/public/mastercard.svg +14 -0
- package/app-template/public/promotion-banner.jpg +0 -0
- package/app-template/public/shop-pay.svg +12 -0
- package/app-template/public/visa.svg +12 -0
- package/app-template/src/app/[commerce]/[locale]/[currency]/blog/[slug]/page.tsx +118 -0
- package/app-template/src/app/[commerce]/[locale]/[currency]/pages/[slug]/page.tsx +15 -0
- package/app-template/src/app/api/theme-settings/route.ts +12 -0
- package/app-template/src/assets/fonts/pz-icon.css +211 -49
- package/app-template/src/assets/fonts/pz-icon.eot +0 -0
- package/app-template/src/assets/fonts/pz-icon.html +486 -0
- package/app-template/src/assets/fonts/pz-icon.scss +373 -49
- package/app-template/src/assets/fonts/pz-icon.svg +215 -53
- package/app-template/src/assets/fonts/pz-icon.ttf +0 -0
- package/app-template/src/assets/fonts/pz-icon.woff +0 -0
- package/app-template/src/assets/fonts/pz-icon.woff2 +0 -0
- package/app-template/src/assets/globals.scss +4 -0
- package/app-template/src/assets/icons/arrow-right.svg +3 -0
- package/app-template/src/assets/icons/cart.svg +4 -12
- package/app-template/src/assets/icons/check.svg +2 -18
- package/app-template/src/assets/icons/chevron-down.svg +2 -7
- package/app-template/src/assets/icons/delete.svg +3 -0
- package/app-template/src/assets/icons/facebook.svg +2 -8
- package/app-template/src/assets/icons/fav-off.svg +5 -0
- package/app-template/src/assets/icons/fav-on.svg +5 -0
- package/app-template/src/assets/icons/filter-and-sort.svg +3 -0
- package/app-template/src/assets/icons/heart.svg +3 -0
- package/app-template/src/assets/icons/instagram.svg +2 -13
- package/app-template/src/assets/icons/materials.svg +3 -0
- package/app-template/src/assets/icons/person.svg +4 -0
- package/app-template/src/assets/icons/pinterest.svg +5 -11
- package/app-template/src/assets/icons/ruler.svg +3 -0
- package/app-template/src/assets/icons/search.svg +8 -11
- package/app-template/src/assets/icons/share.svg +2 -9
- package/app-template/src/assets/icons/snapchat.svg +3 -0
- package/app-template/src/assets/icons/tiktok.svg +3 -0
- package/app-template/src/assets/icons/tumblr.svg +6 -0
- package/app-template/src/assets/icons/twitter.svg +2 -10
- package/app-template/src/assets/icons/vimeo.svg +3 -0
- package/app-template/src/assets/icons/youtube.svg +3 -0
- package/app-template/src/assets/icons/zoom.svg +8 -0
- package/app-template/src/components/accordion.tsx +33 -11
- package/app-template/src/components/action-tooltip.tsx +160 -0
- package/app-template/src/components/currency-select.tsx +149 -4
- package/app-template/src/components/icon.tsx +5 -6
- package/app-template/src/components/index.ts +4 -1
- package/app-template/src/components/language-select.tsx +88 -2
- package/app-template/src/components/pagination.tsx +132 -20
- package/app-template/src/components/quantity-input.tsx +63 -0
- package/app-template/src/components/quantity-selector.tsx +203 -0
- package/app-template/src/components/route-handler.tsx +50 -0
- package/app-template/src/components/select.tsx +89 -69
- package/app-template/src/components/types/index.ts +26 -0
- package/app-template/src/components/widget-content.tsx +323 -0
- package/app-template/src/data/server/theme.ts +70 -0
- package/app-template/src/hooks/use-fav-button.tsx +5 -2
- package/app-template/src/hooks/use-product-cart.ts +11 -8
- package/app-template/src/hooks/use-theme-settings.ts +42 -0
- package/app-template/src/lib/fonts.ts +149 -0
- package/app-template/src/settings.js +2 -2
- package/app-template/src/types/hookform-resolvers-yup.d.ts +28 -0
- package/app-template/src/types/widget.ts +169 -0
- package/app-template/src/utils/formatDate.ts +48 -0
- package/app-template/src/utils/styles.ts +71 -0
- package/app-template/src/views/account/contact-form.tsx +147 -130
- package/app-template/src/views/basket/basket-item.tsx +691 -107
- package/app-template/src/views/basket/basket-summary-context.tsx +560 -0
- package/app-template/src/views/basket/designer-context.tsx +617 -0
- package/app-template/src/views/basket/index.ts +2 -0
- package/app-template/src/views/basket/summary.tsx +496 -75
- package/app-template/src/views/breadcrumb/breadcrumb-client.tsx +190 -0
- package/app-template/src/views/breadcrumb/breadcrumb-registrar.tsx +286 -0
- package/app-template/src/views/breadcrumb/constants.ts +15 -0
- package/app-template/src/views/breadcrumb/index.tsx +127 -0
- package/app-template/src/views/breadcrumb.tsx +13 -38
- package/app-template/src/views/category/category-banner.tsx +4 -23
- package/app-template/src/views/category/category-header.tsx +289 -66
- package/app-template/src/views/category/category-info.tsx +173 -24
- package/app-template/src/views/category/filters/filter-item.tsx +138 -42
- package/app-template/src/views/category/filters/index.tsx +208 -48
- package/app-template/src/views/category/layout.tsx +7 -4
- package/app-template/src/views/category/native-widget-context.tsx +257 -0
- package/app-template/src/views/category/product-list-registrar.tsx +665 -0
- package/app-template/src/views/checkout/auth.tsx +64 -40
- package/app-template/src/views/checkout/checkout-address-registrar.tsx +254 -0
- package/app-template/src/views/checkout/checkout-buttons-registrar.tsx +183 -0
- package/app-template/src/views/checkout/checkout-delivery-method-registrar.tsx +259 -0
- package/app-template/src/views/checkout/checkout-payment-options-registrar.tsx +253 -0
- package/app-template/src/views/checkout/checkout-summary-registrar.tsx +183 -0
- package/app-template/src/views/checkout/constants.ts +5 -0
- package/app-template/src/views/checkout/index.tsx +5 -0
- package/app-template/src/views/checkout/layout/header.tsx +9 -5
- package/app-template/src/views/checkout/steps/payment/index.tsx +5 -2
- package/app-template/src/views/checkout/steps/payment/options/credit-card/index.tsx +72 -1
- package/app-template/src/views/checkout/steps/payment/options/masterpass-rest.tsx +15 -0
- package/app-template/src/views/checkout/steps/payment/options/saved-card.tsx +18 -0
- package/app-template/src/views/checkout/steps/payment/payment-option-buttons.tsx +171 -40
- package/app-template/src/views/checkout/steps/shipping/address-box.tsx +74 -12
- package/app-template/src/views/checkout/steps/shipping/addresses.tsx +128 -45
- package/app-template/src/views/checkout/steps/shipping/shipping-options.tsx +232 -27
- package/app-template/src/views/checkout/summary.tsx +303 -29
- package/app-template/src/views/footer/footer-app-banner-context.tsx +326 -0
- package/app-template/src/views/footer/footer-bottom-context.tsx +215 -0
- package/app-template/src/views/footer/footer-bottom-wrapper.tsx +74 -0
- package/app-template/src/views/footer/footer-layout-constants.ts +35 -0
- package/app-template/src/views/footer/footer-layout-registrar.tsx +342 -0
- package/app-template/src/views/footer/footer-layout-switcher.tsx +110 -0
- package/app-template/src/views/footer/footer-menu-context.tsx +211 -0
- package/app-template/src/views/footer/footer-native-widgets.tsx +60 -0
- package/app-template/src/views/footer/footer-social-context.tsx +254 -0
- package/app-template/src/views/footer/footer-subscription-context.tsx +210 -0
- package/app-template/src/views/footer/footer-utils.ts +43 -0
- package/app-template/src/views/footer/footer-value-props-context.tsx +326 -0
- package/app-template/src/views/footer/logo-settings.ts +183 -0
- package/app-template/src/views/footer/native-widget-config.ts +262 -0
- package/app-template/src/views/footer/subscription-settings.ts +122 -0
- package/app-template/src/views/footer/use-footer-logo.ts +162 -0
- package/app-template/src/views/footer.tsx +415 -13
- package/app-template/src/views/guest-login/index.tsx +62 -58
- package/app-template/src/views/header/action-menu.tsx +277 -45
- package/app-template/src/views/header/band.tsx +6 -21
- package/app-template/src/views/header/designer-context.tsx +261 -0
- package/app-template/src/views/header/header-announcement-registrar.tsx +267 -0
- package/app-template/src/views/header/header-client-wrapper.tsx +496 -0
- package/app-template/src/views/header/header-content.tsx +1026 -0
- package/app-template/src/views/header/header-currency-registrar.tsx +348 -0
- package/app-template/src/views/header/header-icons-context.tsx +262 -0
- package/app-template/src/views/header/header-language-registrar.tsx +348 -0
- package/app-template/src/views/header/header-layout-context.tsx +143 -0
- package/app-template/src/views/header/header-layout-registrar.tsx +658 -0
- package/app-template/src/views/header/header-logo-context.tsx +228 -0
- package/app-template/src/views/header/header-logo.tsx +118 -0
- package/app-template/src/views/header/header-mini-basket-context.tsx +524 -0
- package/app-template/src/views/header/header-search-registrar.tsx +511 -0
- package/app-template/src/views/header/header-text-slider-registrar.tsx +382 -0
- package/app-template/src/views/header/index.tsx +109 -47
- package/app-template/src/views/header/inline-search.tsx +262 -0
- package/app-template/src/views/header/mini-basket.tsx +819 -44
- package/app-template/src/views/header/mobile-hamburger-button.tsx +5 -8
- package/app-template/src/views/header/mobile-menu.tsx +12 -0
- package/app-template/src/views/header/navbar-menu-context.tsx +219 -0
- package/app-template/src/views/header/navbar.tsx +178 -111
- package/app-template/src/views/header/search/index.tsx +71 -32
- package/app-template/src/views/header/search/results.tsx +127 -65
- package/app-template/src/views/header/search/search-input.tsx +61 -0
- package/app-template/src/views/header/server-settings-parser.ts +1105 -0
- package/app-template/src/views/header/use-header-icons.ts +241 -0
- package/app-template/src/views/header/use-header-logo.ts +213 -0
- package/app-template/src/views/header/use-navbar-menu.ts +179 -0
- package/app-template/src/views/login/index.tsx +54 -46
- package/app-template/src/views/product/accordion-section.tsx +61 -0
- package/app-template/src/views/product/accordion-wrapper.tsx +135 -43
- package/app-template/src/views/product/custom-button-group.tsx +69 -0
- package/app-template/src/views/product/favorites-button-section.tsx +69 -0
- package/app-template/src/views/product/find-in-store-section.tsx +60 -0
- package/app-template/src/views/product/index.ts +1 -0
- package/app-template/src/views/product/layout.tsx +6 -5
- package/app-template/src/views/product/misc-buttons.tsx +339 -25
- package/app-template/src/views/product/price-wrapper.tsx +3 -29
- package/app-template/src/views/product/product-actions.tsx +137 -8
- package/app-template/src/views/product/product-info-section.tsx +140 -0
- package/app-template/src/views/product/product-info.tsx +69 -31
- package/app-template/src/views/product/product-share.tsx +13 -8
- package/app-template/src/views/product/product-variants.tsx +2 -2
- package/app-template/src/views/product/quantity-section.tsx +73 -0
- package/app-template/src/views/product/sale-tag.tsx +10 -0
- package/app-template/src/views/product/share-section.tsx +357 -0
- package/app-template/src/views/product/slider.tsx +117 -79
- package/app-template/src/views/product/variant.tsx +69 -41
- package/app-template/src/views/product/variants-section.tsx +126 -0
- package/app-template/src/views/product-detail/constants.ts +272 -0
- package/app-template/src/views/product-detail/index.ts +10 -0
- package/app-template/src/views/product-detail/product-detail-registrar.tsx +616 -0
- package/app-template/src/views/product-item/index.tsx +119 -46
- package/app-template/src/views/register/index.tsx +14 -25
- package/app-template/src/views/share/index.tsx +9 -6
- package/app-template/src/views/widgets/home-hero-slider-content.tsx +41 -39
- package/app-template/src/widgets/flatpages/about-us/index.tsx +78 -0
- package/app-template/src/widgets/flatpages/blog-list/index.tsx +129 -0
- package/app-template/src/widgets/footer-app-banner.tsx +444 -0
- package/app-template/src/widgets/footer-bottom.tsx +127 -0
- package/app-template/src/widgets/footer-menu-compact.tsx +238 -0
- package/app-template/src/widgets/footer-menu-two.tsx +298 -0
- package/app-template/src/widgets/footer-social-client.tsx +251 -0
- package/app-template/src/widgets/footer-social.tsx +47 -16
- package/app-template/src/widgets/footer-subscription/footer-subscription-form.tsx +17 -14
- package/app-template/src/widgets/footer-subscription/index.tsx +183 -17
- package/app-template/src/widgets/footer-value-props.tsx +201 -0
- package/app-template/src/widgets/index.ts +7 -0
- package/app-template/src/widgets/schemas/about-us.json +46 -0
- package/app-template/src/widgets/schemas/blog-list.json +37 -0
- package/app-template/src/widgets/schemas/blog.json +29 -0
- package/app-template/tailwind.config.js +18 -2
- package/package.json +1 -1
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Header Text Slider Section Registrar
|
|
5
|
+
*
|
|
6
|
+
* This component registers the "Text Slider" section for the header placeholder.
|
|
7
|
+
* The text slider section is a native widget that can be added via "Add Section" button.
|
|
8
|
+
* It displays scrolling/sliding text messages in the utility bar.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
createContext,
|
|
13
|
+
useContext,
|
|
14
|
+
useEffect,
|
|
15
|
+
useRef,
|
|
16
|
+
useState,
|
|
17
|
+
PropsWithChildren
|
|
18
|
+
} from 'react';
|
|
19
|
+
|
|
20
|
+
// Constants
|
|
21
|
+
export const HEADER_TEXT_SLIDER_PLACEHOLDER_ID = 'header';
|
|
22
|
+
export const HEADER_TEXT_SLIDER_SECTION_ID = 'header-text-slider';
|
|
23
|
+
export const HEADER_TEXT_SLIDER_WIDGET_SLUG = 'header-text-slider-settings-2';
|
|
24
|
+
|
|
25
|
+
// Global flag to track if registration has been done
|
|
26
|
+
declare global {
|
|
27
|
+
interface Window {
|
|
28
|
+
__headerTextSliderRegistered?: boolean;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Check if running inside designer iframe
|
|
34
|
+
*/
|
|
35
|
+
function isInDesignerMode(): boolean {
|
|
36
|
+
if (typeof window === 'undefined') return false;
|
|
37
|
+
return window.self !== window.top;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface ThemeSection {
|
|
41
|
+
id: string;
|
|
42
|
+
visible?: boolean;
|
|
43
|
+
properties?: Record<string, unknown>;
|
|
44
|
+
styles?: Record<string, unknown>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface ThemePlaceholder {
|
|
48
|
+
slug: string;
|
|
49
|
+
sections: ThemeSection[];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface TextSliderItem {
|
|
53
|
+
text: string;
|
|
54
|
+
link?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface HeaderTextSliderProperties {
|
|
58
|
+
visible?: boolean;
|
|
59
|
+
items?: TextSliderItem[];
|
|
60
|
+
autoPlay?: boolean;
|
|
61
|
+
autoPlayInterval?: number;
|
|
62
|
+
showArrows?: boolean;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
interface HeaderTextSliderContextValue {
|
|
66
|
+
isDesigner: boolean;
|
|
67
|
+
isTextSliderSectionSelected: boolean;
|
|
68
|
+
isSectionVisible: boolean;
|
|
69
|
+
properties: HeaderTextSliderProperties;
|
|
70
|
+
sectionStyles: Record<string, unknown>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const HeaderTextSliderContext = createContext<HeaderTextSliderContextValue>({
|
|
74
|
+
isDesigner: false,
|
|
75
|
+
isTextSliderSectionSelected: false,
|
|
76
|
+
isSectionVisible: false,
|
|
77
|
+
properties: {
|
|
78
|
+
items: [{ text: 'Welcome to our store!' }],
|
|
79
|
+
autoPlay: true,
|
|
80
|
+
autoPlayInterval: 3000,
|
|
81
|
+
showArrows: true
|
|
82
|
+
},
|
|
83
|
+
sectionStyles: {}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
export const useHeaderTextSlider = () => useContext(HeaderTextSliderContext);
|
|
87
|
+
|
|
88
|
+
interface HeaderTextSliderRegistrarProps extends PropsWithChildren {
|
|
89
|
+
/**
|
|
90
|
+
* Initial settings from server-side parsing (to avoid flash)
|
|
91
|
+
*/
|
|
92
|
+
initialSettings?: {
|
|
93
|
+
sectionStyles?: Record<string, unknown>;
|
|
94
|
+
properties?: HeaderTextSliderProperties;
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* HeaderTextSliderRegistrar
|
|
100
|
+
*
|
|
101
|
+
* Registers the Text Slider native section with Theme Editor.
|
|
102
|
+
* The section can be added via "Add Section" button in the header placeholder.
|
|
103
|
+
*/
|
|
104
|
+
export default function HeaderTextSliderRegistrar({
|
|
105
|
+
children,
|
|
106
|
+
initialSettings = {}
|
|
107
|
+
}: HeaderTextSliderRegistrarProps) {
|
|
108
|
+
const isDesignerRef = useRef(false);
|
|
109
|
+
const [sectionProperties, setSectionProperties] =
|
|
110
|
+
useState<HeaderTextSliderProperties>(
|
|
111
|
+
initialSettings.properties || {
|
|
112
|
+
items: [{ text: 'Welcome to our store!' }],
|
|
113
|
+
autoPlay: true,
|
|
114
|
+
autoPlayInterval: 3000,
|
|
115
|
+
showArrows: true
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
const [sectionStyles, setSectionStyles] = useState<Record<string, unknown>>(
|
|
119
|
+
initialSettings.sectionStyles || {}
|
|
120
|
+
);
|
|
121
|
+
const [isTextSliderSelected, setIsTextSliderSelected] = useState(false);
|
|
122
|
+
const [isSectionVisible, setIsSectionVisible] = useState(
|
|
123
|
+
initialSettings.properties?.visible ?? false
|
|
124
|
+
);
|
|
125
|
+
const hasRegisteredNativeWidget = useRef(false);
|
|
126
|
+
|
|
127
|
+
const hasInitialSettings = !!(
|
|
128
|
+
(initialSettings.sectionStyles &&
|
|
129
|
+
Object.keys(initialSettings.sectionStyles).length > 0) ||
|
|
130
|
+
(initialSettings.properties &&
|
|
131
|
+
Object.keys(initialSettings.properties).length > 0)
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
useEffect(() => {
|
|
135
|
+
isDesignerRef.current = isInDesignerMode();
|
|
136
|
+
}, []);
|
|
137
|
+
|
|
138
|
+
const isDesigner = isDesignerRef.current;
|
|
139
|
+
|
|
140
|
+
// Register native widget - only once on mount
|
|
141
|
+
useEffect(() => {
|
|
142
|
+
const isInIframe =
|
|
143
|
+
typeof window !== 'undefined' && window.self !== window.top;
|
|
144
|
+
if (!isInIframe || !window.parent) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Skip if already registered
|
|
149
|
+
if (
|
|
150
|
+
typeof window !== 'undefined' &&
|
|
151
|
+
window.__headerTextSliderRegistered &&
|
|
152
|
+
hasRegisteredNativeWidget.current
|
|
153
|
+
) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Send native widget registration to Theme Editor
|
|
158
|
+
// Use initial settings for registration, not dynamic state
|
|
159
|
+
const nativeWidgetConfig = {
|
|
160
|
+
placeholderId: HEADER_TEXT_SLIDER_PLACEHOLDER_ID,
|
|
161
|
+
autoAdd: false,
|
|
162
|
+
section: {
|
|
163
|
+
id: HEADER_TEXT_SLIDER_SECTION_ID,
|
|
164
|
+
type: 'native',
|
|
165
|
+
label: 'Text Slider',
|
|
166
|
+
blocks: [],
|
|
167
|
+
properties: initialSettings.properties || {
|
|
168
|
+
items: [{ text: 'Welcome to our store!' }],
|
|
169
|
+
autoPlay: true,
|
|
170
|
+
autoPlayInterval: 3000,
|
|
171
|
+
showArrows: true
|
|
172
|
+
},
|
|
173
|
+
styles: initialSettings.sectionStyles || {}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
window.parent.postMessage(
|
|
178
|
+
{
|
|
179
|
+
type: 'REGISTER_NATIVE_WIDGETS',
|
|
180
|
+
data: { widgets: [nativeWidgetConfig] }
|
|
181
|
+
},
|
|
182
|
+
'*'
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
// Mark as registered
|
|
186
|
+
window.__headerTextSliderRegistered = true;
|
|
187
|
+
hasRegisteredNativeWidget.current = true;
|
|
188
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
189
|
+
}, []);
|
|
190
|
+
|
|
191
|
+
// Apply highlight style to text slider container when section is selected
|
|
192
|
+
useEffect(() => {
|
|
193
|
+
if (typeof window === 'undefined') return;
|
|
194
|
+
|
|
195
|
+
const textSliderContainer = document.querySelector(
|
|
196
|
+
'[data-section-id="header-text-slider"]'
|
|
197
|
+
);
|
|
198
|
+
if (!textSliderContainer) return;
|
|
199
|
+
|
|
200
|
+
if (isTextSliderSelected) {
|
|
201
|
+
(textSliderContainer as HTMLElement).style.outline = '2px solid #3b82f6';
|
|
202
|
+
(textSliderContainer as HTMLElement).style.outlineOffset = '-2px';
|
|
203
|
+
} else {
|
|
204
|
+
(textSliderContainer as HTMLElement).style.outline = '';
|
|
205
|
+
(textSliderContainer as HTMLElement).style.outlineOffset = '';
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return () => {
|
|
209
|
+
(textSliderContainer as HTMLElement).style.outline = '';
|
|
210
|
+
(textSliderContainer as HTMLElement).style.outlineOffset = '';
|
|
211
|
+
};
|
|
212
|
+
}, [isTextSliderSelected]);
|
|
213
|
+
|
|
214
|
+
const hasReceivedInitialTheme = useRef(false);
|
|
215
|
+
|
|
216
|
+
// Listen for theme updates and selection changes from Theme Editor
|
|
217
|
+
useEffect(() => {
|
|
218
|
+
if (typeof window === 'undefined') return;
|
|
219
|
+
|
|
220
|
+
const handleMessage = (event: MessageEvent) => {
|
|
221
|
+
const { type, data } = event.data || {};
|
|
222
|
+
|
|
223
|
+
// Handle theme updates
|
|
224
|
+
if (
|
|
225
|
+
(type === 'UPDATE_THEME' || type === 'LOAD_THEME') &&
|
|
226
|
+
data?.theme?.placeholders
|
|
227
|
+
) {
|
|
228
|
+
const placeholder = data.theme.placeholders?.find(
|
|
229
|
+
(p: ThemePlaceholder) => p.slug === HEADER_TEXT_SLIDER_PLACEHOLDER_ID
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
const textSliderSection = placeholder?.sections?.find(
|
|
233
|
+
(s: ThemeSection) => s.id === HEADER_TEXT_SLIDER_SECTION_ID
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
if (textSliderSection) {
|
|
237
|
+
const sectionVisible = textSliderSection.properties?.visible;
|
|
238
|
+
if (sectionVisible !== undefined) {
|
|
239
|
+
const isVisible =
|
|
240
|
+
typeof sectionVisible === 'boolean'
|
|
241
|
+
? sectionVisible
|
|
242
|
+
: sectionVisible?.desktop === true ||
|
|
243
|
+
sectionVisible?.mobile === true;
|
|
244
|
+
setIsSectionVisible(isVisible);
|
|
245
|
+
} else if (typeof textSliderSection.visible === 'boolean') {
|
|
246
|
+
setIsSectionVisible(textSliderSection.visible);
|
|
247
|
+
} else {
|
|
248
|
+
setIsSectionVisible(true);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Skip property/style updates if we have initial settings and haven't
|
|
252
|
+
// received the first theme yet (to avoid format mismatch issues)
|
|
253
|
+
// After first theme load, we use UPDATE_SECTION_PROPERTY for changes
|
|
254
|
+
if (hasInitialSettings && !hasReceivedInitialTheme.current) {
|
|
255
|
+
hasReceivedInitialTheme.current = true;
|
|
256
|
+
// Don't apply properties/styles from UPDATE_THEME when we have server-side initial settings
|
|
257
|
+
// Individual property changes will come via UPDATE_SECTION_PROPERTY
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Only apply updates if we don't have initial settings (fresh load)
|
|
262
|
+
if (!hasInitialSettings) {
|
|
263
|
+
if (textSliderSection.properties) {
|
|
264
|
+
setSectionProperties((prev) => {
|
|
265
|
+
const newProps =
|
|
266
|
+
textSliderSection.properties as HeaderTextSliderProperties;
|
|
267
|
+
if (JSON.stringify(prev) === JSON.stringify(newProps)) {
|
|
268
|
+
return prev;
|
|
269
|
+
}
|
|
270
|
+
return newProps;
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (textSliderSection.styles) {
|
|
275
|
+
setSectionStyles((prev) => {
|
|
276
|
+
if (
|
|
277
|
+
JSON.stringify(prev) ===
|
|
278
|
+
JSON.stringify(textSliderSection.styles)
|
|
279
|
+
) {
|
|
280
|
+
return prev;
|
|
281
|
+
}
|
|
282
|
+
return textSliderSection.styles;
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
} else if (placeholder) {
|
|
287
|
+
setIsSectionVisible(false);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Handle property updates
|
|
292
|
+
if (type === 'UPDATE_SECTION_PROPERTY' || type === 'UPDATE_PROPERTY') {
|
|
293
|
+
const { sectionId, key, value, properties } = data || {};
|
|
294
|
+
|
|
295
|
+
if (sectionId === HEADER_TEXT_SLIDER_SECTION_ID) {
|
|
296
|
+
if (key && value !== undefined) {
|
|
297
|
+
setSectionProperties((prev) => ({
|
|
298
|
+
...prev,
|
|
299
|
+
[key]: value
|
|
300
|
+
}));
|
|
301
|
+
}
|
|
302
|
+
if (properties) {
|
|
303
|
+
setSectionProperties(properties as HeaderTextSliderProperties);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Handle style updates for the section
|
|
309
|
+
if (type === 'UPDATE_SECTION_STYLE' || type === 'UPDATE_STYLE') {
|
|
310
|
+
const { sectionId, key, value, styles } = data || {};
|
|
311
|
+
|
|
312
|
+
if (sectionId === HEADER_TEXT_SLIDER_SECTION_ID) {
|
|
313
|
+
if (key && value !== undefined) {
|
|
314
|
+
setSectionStyles((prev) => ({
|
|
315
|
+
...prev,
|
|
316
|
+
[key]: value
|
|
317
|
+
}));
|
|
318
|
+
}
|
|
319
|
+
if (styles) {
|
|
320
|
+
setSectionStyles(styles);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Handle selection changes
|
|
326
|
+
if (type === 'SELECT_SECTION') {
|
|
327
|
+
const { placeholderId, sectionId } = data || {};
|
|
328
|
+
|
|
329
|
+
const isSelected =
|
|
330
|
+
placeholderId === HEADER_TEXT_SLIDER_PLACEHOLDER_ID &&
|
|
331
|
+
sectionId === HEADER_TEXT_SLIDER_SECTION_ID;
|
|
332
|
+
|
|
333
|
+
setIsTextSliderSelected(isSelected);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Handle block selection
|
|
337
|
+
if (type === 'SELECT_BLOCK') {
|
|
338
|
+
const { sectionId } = data || {};
|
|
339
|
+
if (sectionId === HEADER_TEXT_SLIDER_SECTION_ID) {
|
|
340
|
+
setIsTextSliderSelected(true);
|
|
341
|
+
} else {
|
|
342
|
+
setIsTextSliderSelected(false);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Handle deselection
|
|
347
|
+
if (type === 'DESELECT' || type === 'CLEAR_SELECTION') {
|
|
348
|
+
setIsTextSliderSelected(false);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Handle visibility toggle
|
|
352
|
+
if (type === 'TOGGLE_SECTION_VISIBILITY') {
|
|
353
|
+
const { sectionId } = data || {};
|
|
354
|
+
if (sectionId === HEADER_TEXT_SLIDER_SECTION_ID) {
|
|
355
|
+
setIsSectionVisible((prev) => !prev);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
window.addEventListener('message', handleMessage);
|
|
361
|
+
return () => window.removeEventListener('message', handleMessage);
|
|
362
|
+
}, [hasInitialSettings, isDesigner]);
|
|
363
|
+
|
|
364
|
+
// If no children, just return null (registration-only mode)
|
|
365
|
+
if (!children) {
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return (
|
|
370
|
+
<HeaderTextSliderContext.Provider
|
|
371
|
+
value={{
|
|
372
|
+
isDesigner,
|
|
373
|
+
isTextSliderSectionSelected: isTextSliderSelected,
|
|
374
|
+
isSectionVisible,
|
|
375
|
+
properties: sectionProperties,
|
|
376
|
+
sectionStyles
|
|
377
|
+
}}
|
|
378
|
+
>
|
|
379
|
+
{children}
|
|
380
|
+
</HeaderTextSliderContext.Provider>
|
|
381
|
+
);
|
|
382
|
+
}
|
|
@@ -1,66 +1,128 @@
|
|
|
1
1
|
import 'server-only';
|
|
2
2
|
|
|
3
|
-
import { Link } from '@theme/components';
|
|
4
|
-
import clsx from 'clsx';
|
|
5
|
-
import { ROUTES } from '@theme/routes';
|
|
6
3
|
import { menuGenerator } from '@akinon/next/utils';
|
|
7
4
|
|
|
8
5
|
import HeaderBand from './band';
|
|
9
6
|
import MobileHamburgerButton from './mobile-hamburger-button';
|
|
10
7
|
import MobileMenu from './mobile-menu';
|
|
11
8
|
import Navbar from './navbar';
|
|
9
|
+
import HeaderLogo from './header-logo';
|
|
10
|
+
import HeaderLayoutRegistrar from './header-layout-registrar';
|
|
11
|
+
import HeaderContent from './header-content';
|
|
12
12
|
import { getMenu } from '@akinon/next/data/server';
|
|
13
|
-
import {
|
|
13
|
+
import { getThemeSettings } from '@theme/data/server/theme';
|
|
14
|
+
import { getWidgetData } from '@akinon/next/data/server/widget';
|
|
15
|
+
import {
|
|
16
|
+
parseServerIconSettings,
|
|
17
|
+
parseServerLogoSettings,
|
|
18
|
+
parseServerNavbarMenuSettings,
|
|
19
|
+
parseServerLayoutSettings,
|
|
20
|
+
parseServerSearchSettings,
|
|
21
|
+
parseServerLanguageSettings,
|
|
22
|
+
parseServerCurrencySettings,
|
|
23
|
+
parseServerTextSliderSettings,
|
|
24
|
+
parseServerAnnouncementSettings
|
|
25
|
+
} from './server-settings-parser';
|
|
14
26
|
|
|
15
27
|
export default async function Header() {
|
|
16
28
|
const response = await getMenu({ depth: 3 });
|
|
17
29
|
const menu = menuGenerator(response);
|
|
30
|
+
const themeSettings = await getThemeSettings();
|
|
31
|
+
|
|
32
|
+
// Fetch native widget settings server-side to avoid flash
|
|
33
|
+
const [
|
|
34
|
+
iconSettingsWidget,
|
|
35
|
+
logoSettingsWidget,
|
|
36
|
+
navSettingsWidget,
|
|
37
|
+
layoutSettingsWidget,
|
|
38
|
+
searchSettingsWidget,
|
|
39
|
+
languageSettingsWidget,
|
|
40
|
+
currencySettingsWidget,
|
|
41
|
+
textSliderSettingsWidget,
|
|
42
|
+
announcementSettingsWidget
|
|
43
|
+
] = await Promise.all([
|
|
44
|
+
getWidgetData({ slug: 'header-icon-settings-2' }).catch(() => null),
|
|
45
|
+
getWidgetData({ slug: 'header-logo-settings-2' }).catch(() => null),
|
|
46
|
+
getWidgetData({ slug: 'header-nav-settings-2' }).catch(() => null),
|
|
47
|
+
getWidgetData({ slug: 'header-layout-settings-2' }).catch(() => null),
|
|
48
|
+
getWidgetData({ slug: 'header-search-settings-2' }).catch(() => null),
|
|
49
|
+
getWidgetData({ slug: 'header-language-settings-2' }).catch(() => null),
|
|
50
|
+
getWidgetData({ slug: 'header-currency-settings-2' }).catch(() => null),
|
|
51
|
+
getWidgetData({ slug: 'header-text-slider-settings-2' }).catch(() => null),
|
|
52
|
+
getWidgetData({ slug: 'header-announcement-bar-settings-2' }).catch(
|
|
53
|
+
() => null
|
|
54
|
+
)
|
|
55
|
+
]);
|
|
56
|
+
|
|
57
|
+
const initialIconSettings = parseServerIconSettings(iconSettingsWidget);
|
|
58
|
+
const initialLogoSettings = parseServerLogoSettings(
|
|
59
|
+
logoSettingsWidget,
|
|
60
|
+
themeSettings.logo
|
|
61
|
+
);
|
|
62
|
+
const initialNavSettings = parseServerNavbarMenuSettings(navSettingsWidget);
|
|
63
|
+
const initialLayoutSettings = parseServerLayoutSettings(layoutSettingsWidget);
|
|
64
|
+
const initialSearchSettings = parseServerSearchSettings(searchSettingsWidget);
|
|
65
|
+
const initialLanguageSettings = parseServerLanguageSettings(
|
|
66
|
+
languageSettingsWidget
|
|
67
|
+
);
|
|
68
|
+
const initialCurrencySettings = parseServerCurrencySettings(
|
|
69
|
+
currencySettingsWidget
|
|
70
|
+
);
|
|
71
|
+
const initialTextSliderSettings = parseServerTextSliderSettings(
|
|
72
|
+
textSliderSettingsWidget
|
|
73
|
+
);
|
|
74
|
+
const initialAnnouncementSettings = parseServerAnnouncementSettings(
|
|
75
|
+
announcementSettingsWidget
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
// Use layout settings for sticky, fallback to theme settings
|
|
79
|
+
const isSticky = initialLayoutSettings.sticky;
|
|
80
|
+
const position = isSticky ? 'sticky' : 'relative';
|
|
81
|
+
const top = isSticky ? '0' : 'auto';
|
|
82
|
+
const zIndex = isSticky ? '40' : 'auto';
|
|
18
83
|
|
|
19
84
|
return (
|
|
20
|
-
<header
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
'sm:before:block'
|
|
41
|
-
])}
|
|
85
|
+
<header
|
|
86
|
+
className="relative"
|
|
87
|
+
style={{
|
|
88
|
+
position:
|
|
89
|
+
`var(--theme-header-position, ${position})` as React.CSSProperties['position'],
|
|
90
|
+
top: `var(--theme-header-top, ${top})`,
|
|
91
|
+
zIndex:
|
|
92
|
+
`var(--theme-header-z-index, ${zIndex})` as React.CSSProperties['zIndex'],
|
|
93
|
+
width: '100%',
|
|
94
|
+
backgroundColor: 'var(--theme-background, #fff)'
|
|
95
|
+
}}
|
|
96
|
+
>
|
|
97
|
+
{/* Register Layout section and provide layout context */}
|
|
98
|
+
<HeaderLayoutRegistrar
|
|
99
|
+
initialLayout={initialLayoutSettings.layout}
|
|
100
|
+
initialMenuPosition={initialLayoutSettings.menuPosition}
|
|
101
|
+
initialSearchPosition={initialLayoutSettings.searchPosition}
|
|
102
|
+
initialUtilityPosition={initialLayoutSettings.utilityPosition}
|
|
103
|
+
initialSticky={initialLayoutSettings.sticky}
|
|
104
|
+
initialBlockStyles={initialLayoutSettings.blockStyles}
|
|
42
105
|
>
|
|
43
|
-
<
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
</div>
|
|
106
|
+
<HeaderContent
|
|
107
|
+
logo={
|
|
108
|
+
<HeaderLogo
|
|
109
|
+
fallbackSrc={themeSettings.logo || '/logo.svg'}
|
|
110
|
+
initialSettings={initialLogoSettings}
|
|
111
|
+
/>
|
|
112
|
+
}
|
|
113
|
+
navbar={
|
|
114
|
+
<Navbar menu={menu} initialNavSettings={initialNavSettings} />
|
|
115
|
+
}
|
|
116
|
+
icons={<HeaderBand initialIconSettings={initialIconSettings} />}
|
|
117
|
+
mobileHamburger={<MobileHamburgerButton />}
|
|
118
|
+
mobileMenu={<MobileMenu menu={menu} />}
|
|
119
|
+
initialSearchSettings={initialSearchSettings}
|
|
120
|
+
initialLanguageSettings={initialLanguageSettings}
|
|
121
|
+
initialCurrencySettings={initialCurrencySettings}
|
|
122
|
+
initialTextSliderSettings={initialTextSliderSettings}
|
|
123
|
+
initialAnnouncementSettings={initialAnnouncementSettings}
|
|
124
|
+
/>
|
|
125
|
+
</HeaderLayoutRegistrar>
|
|
64
126
|
</header>
|
|
65
127
|
);
|
|
66
128
|
}
|