@akinon/projectzero 2.0.0-beta.20 → 2.0.0-beta.22

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.
Files changed (140) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/app-template/CHANGELOG.md +170 -0
  3. package/app-template/next.config.mjs +0 -1
  4. package/app-template/package.json +31 -30
  5. package/app-template/src/app/[pz]/[...prettyurl]/page.tsx +2 -2
  6. package/app-template/src/app/[pz]/account/layout.tsx +2 -1
  7. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/blog/[slug]/page.tsx +4 -2
  8. package/app-template/src/app/[pz]/category/[pk]/page.tsx +11 -1
  9. package/app-template/src/app/[pz]/group-product/[pk]/page.tsx +2 -2
  10. package/app-template/src/app/[pz]/layout.tsx +3 -1
  11. package/app-template/src/app/[pz]/list/page.tsx +11 -1
  12. package/app-template/src/app/[pz]/page.tsx +13 -35
  13. package/app-template/src/app/[pz]/pages/[slug]/page.tsx +19 -0
  14. package/app-template/src/app/[pz]/product/[pk]/page.tsx +2 -2
  15. package/app-template/src/app/api/barcode-search/route.ts +1 -1
  16. package/app-template/src/app/api/cache/route.ts +1 -1
  17. package/app-template/src/app/api/image-proxy/route.ts +1 -1
  18. package/app-template/src/app/api/logout/route.ts +1 -1
  19. package/app-template/src/app/api/product-categories/route.ts +1 -1
  20. package/app-template/src/app/api/similar-product-list/route.ts +1 -1
  21. package/app-template/src/app/api/similar-products/route.ts +1 -1
  22. package/app-template/src/app/api/virtual-try-on/route.ts +1 -1
  23. package/app-template/src/app/api/web-vitals/route.ts +1 -1
  24. package/app-template/src/components/quantity-selector.tsx +16 -4
  25. package/app-template/src/components/widget-content.tsx +3 -3
  26. package/app-template/src/routes/index.ts +6 -6
  27. package/app-template/src/utils/__tests__/theme-page-context.test.ts +145 -0
  28. package/app-template/src/utils/theme-page-context.ts +309 -0
  29. package/app-template/src/views/basket/basket-item.tsx +107 -691
  30. package/app-template/src/views/basket/index.ts +0 -2
  31. package/app-template/src/views/basket/summary.tsx +75 -496
  32. package/app-template/src/views/breadcrumb.tsx +38 -13
  33. package/app-template/src/views/category/category-header.tsx +66 -289
  34. package/app-template/src/views/category/category-info.tsx +24 -173
  35. package/app-template/src/views/category/filters/index.tsx +48 -208
  36. package/app-template/src/views/category/layout.tsx +5 -7
  37. package/app-template/src/views/checkout/index.tsx +0 -5
  38. package/app-template/src/views/checkout/steps/payment/index.tsx +2 -5
  39. package/app-template/src/views/checkout/steps/payment/options/credit-card/index.tsx +1 -72
  40. package/app-template/src/views/checkout/steps/payment/payment-option-buttons.tsx +40 -171
  41. package/app-template/src/views/checkout/steps/shipping/address-box.tsx +12 -74
  42. package/app-template/src/views/checkout/steps/shipping/addresses.tsx +45 -128
  43. package/app-template/src/views/checkout/steps/shipping/shipping-options.tsx +27 -232
  44. package/app-template/src/views/checkout/summary.tsx +29 -303
  45. package/app-template/src/views/footer.tsx +13 -415
  46. package/app-template/src/views/guest-login/index.tsx +1 -1
  47. package/app-template/src/views/header/action-menu.tsx +45 -277
  48. package/app-template/src/views/header/band.tsx +21 -6
  49. package/app-template/src/views/header/index.tsx +47 -109
  50. package/app-template/src/views/header/mini-basket.tsx +45 -820
  51. package/app-template/src/views/header/navbar.tsx +111 -178
  52. package/app-template/src/views/header/search/index.tsx +32 -71
  53. package/app-template/src/views/header/search/results.tsx +65 -127
  54. package/app-template/src/views/product/accordion-wrapper.tsx +43 -135
  55. package/app-template/src/views/product/index.ts +1 -1
  56. package/app-template/src/views/product/layout.tsx +7 -2
  57. package/app-template/src/views/product/misc-buttons.tsx +25 -339
  58. package/app-template/src/views/product/product-actions.tsx +8 -137
  59. package/app-template/src/views/product/product-info.tsx +31 -69
  60. package/app-template/src/views/product/product-share.tsx +8 -11
  61. package/app-template/src/views/product/slider.tsx +79 -117
  62. package/app-template/src/views/product-item/index.tsx +46 -119
  63. package/app-template/src/widgets/footer-social.tsx +16 -47
  64. package/app-template/src/widgets/footer-subscription/index.tsx +17 -183
  65. package/codemods/migrate-auth-v5/index.js +339 -0
  66. package/codemods/migrate-auth-v5/transform.js +86 -0
  67. package/dist/commands/plugins.js +23 -2
  68. package/package.json +1 -1
  69. package/app-template/src/app/[commerce]/[locale]/[currency]/pages/[slug]/page.tsx +0 -15
  70. package/app-template/src/views/basket/basket-summary-context.tsx +0 -560
  71. package/app-template/src/views/basket/designer-context.tsx +0 -617
  72. package/app-template/src/views/breadcrumb/breadcrumb-client.tsx +0 -190
  73. package/app-template/src/views/breadcrumb/breadcrumb-registrar.tsx +0 -286
  74. package/app-template/src/views/breadcrumb/constants.ts +0 -15
  75. package/app-template/src/views/breadcrumb/index.tsx +0 -127
  76. package/app-template/src/views/category/native-widget-context.tsx +0 -257
  77. package/app-template/src/views/category/product-list-registrar.tsx +0 -665
  78. package/app-template/src/views/checkout/checkout-address-registrar.tsx +0 -254
  79. package/app-template/src/views/checkout/checkout-buttons-registrar.tsx +0 -183
  80. package/app-template/src/views/checkout/checkout-delivery-method-registrar.tsx +0 -259
  81. package/app-template/src/views/checkout/checkout-payment-options-registrar.tsx +0 -253
  82. package/app-template/src/views/checkout/checkout-summary-registrar.tsx +0 -183
  83. package/app-template/src/views/checkout/constants.ts +0 -5
  84. package/app-template/src/views/checkout/steps/payment/options/masterpass-rest.tsx +0 -15
  85. package/app-template/src/views/checkout/steps/payment/options/saved-card.tsx +0 -18
  86. package/app-template/src/views/footer/footer-app-banner-context.tsx +0 -326
  87. package/app-template/src/views/footer/footer-bottom-context.tsx +0 -215
  88. package/app-template/src/views/footer/footer-bottom-wrapper.tsx +0 -74
  89. package/app-template/src/views/footer/footer-layout-constants.ts +0 -35
  90. package/app-template/src/views/footer/footer-layout-registrar.tsx +0 -342
  91. package/app-template/src/views/footer/footer-layout-switcher.tsx +0 -110
  92. package/app-template/src/views/footer/footer-menu-context.tsx +0 -211
  93. package/app-template/src/views/footer/footer-native-widgets.tsx +0 -60
  94. package/app-template/src/views/footer/footer-social-context.tsx +0 -254
  95. package/app-template/src/views/footer/footer-subscription-context.tsx +0 -210
  96. package/app-template/src/views/footer/footer-utils.ts +0 -43
  97. package/app-template/src/views/footer/footer-value-props-context.tsx +0 -326
  98. package/app-template/src/views/footer/logo-settings.ts +0 -183
  99. package/app-template/src/views/footer/native-widget-config.ts +0 -262
  100. package/app-template/src/views/footer/subscription-settings.ts +0 -122
  101. package/app-template/src/views/footer/use-footer-logo.ts +0 -162
  102. package/app-template/src/views/header/designer-context.tsx +0 -261
  103. package/app-template/src/views/header/header-announcement-registrar.tsx +0 -267
  104. package/app-template/src/views/header/header-client-wrapper.tsx +0 -496
  105. package/app-template/src/views/header/header-content.tsx +0 -1026
  106. package/app-template/src/views/header/header-currency-registrar.tsx +0 -348
  107. package/app-template/src/views/header/header-icons-context.tsx +0 -262
  108. package/app-template/src/views/header/header-language-registrar.tsx +0 -348
  109. package/app-template/src/views/header/header-layout-context.tsx +0 -143
  110. package/app-template/src/views/header/header-layout-registrar.tsx +0 -658
  111. package/app-template/src/views/header/header-logo-context.tsx +0 -228
  112. package/app-template/src/views/header/header-logo.tsx +0 -118
  113. package/app-template/src/views/header/header-mini-basket-context.tsx +0 -524
  114. package/app-template/src/views/header/header-search-registrar.tsx +0 -511
  115. package/app-template/src/views/header/header-text-slider-registrar.tsx +0 -382
  116. package/app-template/src/views/header/inline-search.tsx +0 -262
  117. package/app-template/src/views/header/navbar-menu-context.tsx +0 -219
  118. package/app-template/src/views/header/search/search-input.tsx +0 -61
  119. package/app-template/src/views/header/server-settings-parser.ts +0 -1105
  120. package/app-template/src/views/header/use-header-icons.ts +0 -241
  121. package/app-template/src/views/header/use-header-logo.ts +0 -213
  122. package/app-template/src/views/header/use-navbar-menu.ts +0 -179
  123. package/app-template/src/views/product/accordion-section.tsx +0 -61
  124. package/app-template/src/views/product/custom-button-group.tsx +0 -69
  125. package/app-template/src/views/product/favorites-button-section.tsx +0 -69
  126. package/app-template/src/views/product/find-in-store-section.tsx +0 -60
  127. package/app-template/src/views/product/product-info-section.tsx +0 -140
  128. package/app-template/src/views/product/quantity-section.tsx +0 -73
  129. package/app-template/src/views/product/sale-tag.tsx +0 -10
  130. package/app-template/src/views/product/share-section.tsx +0 -357
  131. package/app-template/src/views/product/variants-section.tsx +0 -126
  132. package/app-template/src/views/product-detail/constants.ts +0 -272
  133. package/app-template/src/views/product-detail/index.ts +0 -10
  134. package/app-template/src/views/product-detail/product-detail-registrar.tsx +0 -616
  135. package/app-template/src/widgets/footer-app-banner.tsx +0 -444
  136. package/app-template/src/widgets/footer-bottom.tsx +0 -127
  137. package/app-template/src/widgets/footer-menu-compact.tsx +0 -238
  138. package/app-template/src/widgets/footer-menu-two.tsx +0 -298
  139. package/app-template/src/widgets/footer-social-client.tsx +0 -251
  140. package/app-template/src/widgets/footer-value-props.tsx +0 -201
@@ -1,262 +0,0 @@
1
- export const FOOTER_PLACEHOLDER_ID = 'footer';
2
- export const FOOTER_MENU_SECTION_ID = 'footer-menu';
3
- export const FOOTER_SUBSCRIPTION_SECTION_ID = 'footer-subscription';
4
- export const FOOTER_SOCIAL_SECTION_ID = 'footer-social';
5
- export const FOOTER_BOTTOM_SECTION_ID = 'footer-bottom';
6
- export const FOOTER_APP_BANNER_SECTION_ID = 'footer-app-banner';
7
- export const FOOTER_VALUE_PROPS_SECTION_ID = 'footer-value-props';
8
-
9
- export const FOOTER_MENU_WIDGET_SLUG = 'footer-menu-settings-2';
10
- export const FOOTER_SUBSCRIPTION_WIDGET_SLUG = 'footer-subscription-settings-2';
11
- export const FOOTER_SOCIAL_WIDGET_SLUG = 'footer-social-settings-2';
12
- export const FOOTER_BOTTOM_WIDGET_SLUG = 'footer-bottom-settings-2';
13
- export const FOOTER_APP_BANNER_WIDGET_SLUG = 'footer-app-banner-settings-2';
14
- export const FOOTER_VALUE_PROPS_WIDGET_SLUG = 'footer-value-props-settings-2';
15
-
16
- export const FOOTER_MENU_LOGO_BLOCK_ID = 'footer-menu-logo';
17
- export const FOOTER_MENU_HEADING_BLOCK_ID = 'footer-menu-heading';
18
- export const FOOTER_MENU_LINK_BLOCK_ID = 'footer-menu-link';
19
- export const FOOTER_SUBSCRIPTION_TITLE_BLOCK_ID = 'footer-subscription-title';
20
- export const FOOTER_SUBSCRIPTION_DESCRIPTION_BLOCK_ID =
21
- 'footer-subscription-description';
22
- export const FOOTER_SUBSCRIPTION_FORM_BLOCK_ID = 'footer-subscription-form';
23
- export const FOOTER_SOCIAL_ICONS_BLOCK_ID = 'footer-social-icons';
24
- export const FOOTER_BOTTOM_LABELS_BLOCK_ID = 'footer-bottom-labels';
25
- export const FOOTER_BOTTOM_SELECTORS_BLOCK_ID = 'footer-bottom-selectors';
26
- export const FOOTER_BOTTOM_PAYMENTS_BLOCK_ID = 'footer-bottom-payment-icons';
27
-
28
- export const FOOTER_APP_BANNER_IMAGE_BLOCK_ID = 'footer-app-banner-image';
29
- export const FOOTER_APP_BANNER_TITLE_BLOCK_ID = 'footer-app-banner-title';
30
- export const FOOTER_APP_BANNER_DESCRIPTION_BLOCK_ID =
31
- 'footer-app-banner-description';
32
- export const FOOTER_APP_BANNER_BUTTONS_BLOCK_ID = 'footer-app-banner-buttons';
33
- export const FOOTER_APP_BANNER_APPSTORE_BLOCK_ID = 'footer-app-banner-appstore';
34
- export const FOOTER_APP_BANNER_PLAYSTORE_BLOCK_ID =
35
- 'footer-app-banner-playstore';
36
-
37
- export const FOOTER_VALUE_PROPS_LIST_BLOCK_ID = 'footer-value-props-list';
38
-
39
- export interface FooterNativeWidgetBlockConfig {
40
- id: string;
41
- type: string;
42
- label: string;
43
- blocks?: FooterNativeWidgetBlockConfig[];
44
- }
45
-
46
- export interface FooterNativeWidgetSectionConfig {
47
- placeholderId: string;
48
- sectionId: string;
49
- label: string;
50
- widgetSlug: string;
51
- blocks: FooterNativeWidgetBlockConfig[];
52
- }
53
-
54
- export interface FooterNativeWidgetBlock extends FooterNativeWidgetBlockConfig {
55
- styles?: Record<string, unknown>;
56
- properties?: Record<string, unknown>;
57
- value?: unknown;
58
- blocks?: FooterNativeWidgetBlock[];
59
- }
60
-
61
- export interface FooterNativeWidgetSection
62
- extends FooterNativeWidgetSectionConfig {
63
- blocks: FooterNativeWidgetBlock[];
64
- sectionProperties?: Record<string, unknown>;
65
- sectionStyles?: Record<string, unknown>;
66
- }
67
-
68
- export const FOOTER_NATIVE_SECTIONS: FooterNativeWidgetSectionConfig[] = [
69
- {
70
- placeholderId: FOOTER_PLACEHOLDER_ID,
71
- sectionId: FOOTER_MENU_SECTION_ID,
72
- label: 'Footer Menu',
73
- widgetSlug: FOOTER_MENU_WIDGET_SLUG,
74
- blocks: [
75
- {
76
- id: 'footer-menu-heading',
77
- type: 'text',
78
- label: 'Menu Headings'
79
- },
80
- {
81
- id: 'footer-menu-link',
82
- type: 'text',
83
- label: 'Menu Links'
84
- },
85
- {
86
- id: FOOTER_MENU_LOGO_BLOCK_ID,
87
- type: 'image',
88
- label: 'Footer Logo'
89
- }
90
- ]
91
- },
92
- {
93
- placeholderId: FOOTER_PLACEHOLDER_ID,
94
- sectionId: FOOTER_SUBSCRIPTION_SECTION_ID,
95
- label: 'Footer Subscription',
96
- widgetSlug: FOOTER_SUBSCRIPTION_WIDGET_SLUG,
97
- blocks: [
98
- {
99
- id: FOOTER_SUBSCRIPTION_TITLE_BLOCK_ID,
100
- type: 'text',
101
- label: 'Subscription Title'
102
- },
103
- {
104
- id: FOOTER_SUBSCRIPTION_DESCRIPTION_BLOCK_ID,
105
- type: 'text',
106
- label: 'Subscription Description'
107
- },
108
- {
109
- id: FOOTER_SUBSCRIPTION_FORM_BLOCK_ID,
110
- type: 'group',
111
- label: 'Subscription Form'
112
- }
113
- ]
114
- },
115
- {
116
- placeholderId: FOOTER_PLACEHOLDER_ID,
117
- sectionId: FOOTER_SOCIAL_SECTION_ID,
118
- label: 'Footer Social Icons',
119
- widgetSlug: FOOTER_SOCIAL_WIDGET_SLUG,
120
- blocks: [
121
- {
122
- id: FOOTER_SOCIAL_ICONS_BLOCK_ID,
123
- type: 'social-icons-list',
124
- label: 'Social Icons'
125
- }
126
- ]
127
- },
128
- {
129
- placeholderId: FOOTER_PLACEHOLDER_ID,
130
- sectionId: FOOTER_BOTTOM_SECTION_ID,
131
- label: 'Footer Bottom',
132
- widgetSlug: FOOTER_BOTTOM_WIDGET_SLUG,
133
- blocks: [
134
- {
135
- id: FOOTER_BOTTOM_PAYMENTS_BLOCK_ID,
136
- type: 'icon-group',
137
- label: 'Payment Icons'
138
- }
139
- ]
140
- },
141
- {
142
- placeholderId: FOOTER_PLACEHOLDER_ID,
143
- sectionId: FOOTER_APP_BANNER_SECTION_ID,
144
- label: 'App Banner',
145
- widgetSlug: FOOTER_APP_BANNER_WIDGET_SLUG,
146
- blocks: [
147
- {
148
- id: FOOTER_APP_BANNER_IMAGE_BLOCK_ID,
149
- type: 'image',
150
- label: 'App Image'
151
- },
152
- {
153
- id: FOOTER_APP_BANNER_TITLE_BLOCK_ID,
154
- type: 'text',
155
- label: 'Banner Title'
156
- },
157
- {
158
- id: FOOTER_APP_BANNER_DESCRIPTION_BLOCK_ID,
159
- type: 'text',
160
- label: 'Banner Description'
161
- },
162
- {
163
- id: FOOTER_APP_BANNER_BUTTONS_BLOCK_ID,
164
- type: 'group',
165
- label: 'Store Buttons',
166
- blocks: [
167
- {
168
- id: FOOTER_APP_BANNER_APPSTORE_BLOCK_ID,
169
- type: 'image',
170
- label: 'App Store Button'
171
- },
172
- {
173
- id: FOOTER_APP_BANNER_PLAYSTORE_BLOCK_ID,
174
- type: 'image',
175
- label: 'Google Play Button'
176
- }
177
- ]
178
- }
179
- ]
180
- },
181
- {
182
- placeholderId: FOOTER_PLACEHOLDER_ID,
183
- sectionId: FOOTER_VALUE_PROPS_SECTION_ID,
184
- label: 'Value Propositions',
185
- widgetSlug: FOOTER_VALUE_PROPS_WIDGET_SLUG,
186
- blocks: [
187
- {
188
- id: FOOTER_VALUE_PROPS_LIST_BLOCK_ID,
189
- type: 'value-props-list',
190
- label: 'Value Props'
191
- }
192
- ]
193
- }
194
- ];
195
-
196
- type WidgetAttributes = Record<string, unknown>;
197
-
198
- type WidgetData = {
199
- attributes?: WidgetAttributes;
200
- } | null;
201
-
202
- type ParsedBlockPayload = {
203
- styles?: Record<string, unknown>;
204
- properties?: Record<string, unknown>;
205
- value?: unknown;
206
- [key: string]: unknown;
207
- };
208
-
209
- export function parseWidgetBlockAttributes(
210
- widgetData: WidgetData,
211
- blockId: string
212
- ): Pick<FooterNativeWidgetBlock, 'styles' | 'properties' | 'value'> {
213
- const attributes = widgetData?.attributes;
214
- if (!attributes || !(blockId in attributes)) {
215
- return {};
216
- }
217
-
218
- const attrData = attributes[blockId];
219
- let parsed: unknown = attrData;
220
-
221
- if (typeof attrData === 'string') {
222
- try {
223
- parsed = JSON.parse(attrData);
224
- } catch {
225
- return { value: attrData };
226
- }
227
- } else if (
228
- typeof attrData === 'object' &&
229
- attrData !== null &&
230
- 'value' in (attrData as Record<string, unknown>)
231
- ) {
232
- const value = (attrData as { value?: unknown }).value;
233
- if (typeof value === 'string') {
234
- try {
235
- parsed = JSON.parse(value);
236
- } catch {
237
- return { value };
238
- }
239
- } else {
240
- parsed = value;
241
- }
242
- }
243
-
244
- if (typeof parsed !== 'object' || parsed === null) {
245
- if (typeof parsed === 'string') {
246
- return { value: parsed };
247
- }
248
- return {};
249
- }
250
-
251
- const payload = parsed as ParsedBlockPayload;
252
- const styles =
253
- payload.styles ||
254
- // Legacy format where style props live at root
255
- (!payload.properties && !('value' in payload) ? payload : undefined);
256
-
257
- return {
258
- styles,
259
- properties: payload.properties,
260
- value: payload.value
261
- };
262
- }
@@ -1,122 +0,0 @@
1
- import {
2
- FOOTER_SUBSCRIPTION_SECTION_ID,
3
- FOOTER_SUBSCRIPTION_TITLE_BLOCK_ID,
4
- FOOTER_SUBSCRIPTION_DESCRIPTION_BLOCK_ID,
5
- FOOTER_SUBSCRIPTION_FORM_BLOCK_ID,
6
- FOOTER_SUBSCRIPTION_WIDGET_SLUG,
7
- type FooterNativeWidgetSection,
8
- type FooterNativeWidgetBlock
9
- } from './native-widget-config';
10
-
11
- export type FooterSubscriptionBlockSnapshot = Array<FooterNativeWidgetBlock>;
12
-
13
- export const FOOTER_SUBSCRIPTION_DEFAULT_CONTENT = {
14
- title: 'Keep up with our latest news',
15
- description:
16
- 'Subscribe to our newsletter to hear about new arrivals before anyone else.'
17
- } as const;
18
-
19
- export const FOOTER_SUBSCRIPTION_BLOCKS = {
20
- TITLE: {
21
- id: FOOTER_SUBSCRIPTION_TITLE_BLOCK_ID,
22
- type: 'text',
23
- label: 'Subscription Title'
24
- },
25
- DESCRIPTION: {
26
- id: FOOTER_SUBSCRIPTION_DESCRIPTION_BLOCK_ID,
27
- type: 'text',
28
- label: 'Subscription Description'
29
- },
30
- FORM: {
31
- id: FOOTER_SUBSCRIPTION_FORM_BLOCK_ID,
32
- type: 'group',
33
- label: 'Subscription Form'
34
- }
35
- } as const;
36
-
37
- const FOOTER_SUBSCRIPTION_BLOCK_LIST = Object.values(
38
- FOOTER_SUBSCRIPTION_BLOCKS
39
- );
40
-
41
- const FOOTER_SUBSCRIPTION_BLOCK_ID_SET = new Set<string>(
42
- FOOTER_SUBSCRIPTION_BLOCK_LIST.map((block) => block.id)
43
- );
44
-
45
- const createTextValue = (text?: string) => {
46
- if (!text) {
47
- return undefined;
48
- }
49
-
50
- return text;
51
- };
52
-
53
- export function getFooterSubscriptionInitialBlocks(
54
- sections: FooterNativeWidgetSection[]
55
- ): FooterSubscriptionBlockSnapshot {
56
- const section = sections.find(
57
- (item) => item.sectionId === FOOTER_SUBSCRIPTION_SECTION_ID
58
- );
59
-
60
- if (!section) {
61
- return [];
62
- }
63
-
64
- return section.blocks.map((block) => ({
65
- id: block.id,
66
- type: block.type,
67
- label: block.label,
68
- styles: block.styles,
69
- properties: block.properties,
70
- value: block.value
71
- }));
72
- }
73
-
74
- type FooterSubscriptionContent = {
75
- title?: string;
76
- description?: string;
77
- };
78
-
79
- export function mergeFooterSubscriptionContent(
80
- blocks: FooterSubscriptionBlockSnapshot,
81
- content: FooterSubscriptionContent
82
- ): FooterSubscriptionBlockSnapshot {
83
- const blockMap = new Map<string, FooterNativeWidgetBlock>();
84
- blocks.forEach((block) => {
85
- blockMap.set(block.id, { ...block });
86
- });
87
-
88
- const normalizedBlocks = FOOTER_SUBSCRIPTION_BLOCK_LIST.map((config) => {
89
- const existing = blockMap.get(config.id) ?? {
90
- id: config.id,
91
- type: config.type,
92
- label: config.label
93
- };
94
-
95
- if (existing.value == null) {
96
- const fallbackText =
97
- config.id === FOOTER_SUBSCRIPTION_TITLE_BLOCK_ID
98
- ? content.title
99
- : config.id === FOOTER_SUBSCRIPTION_DESCRIPTION_BLOCK_ID
100
- ? content.description
101
- : undefined;
102
-
103
- const fallbackValue = createTextValue(fallbackText);
104
- if (fallbackValue) {
105
- return {
106
- ...existing,
107
- value: fallbackValue
108
- };
109
- }
110
- }
111
-
112
- return existing;
113
- });
114
-
115
- const extraBlocks = blocks.filter(
116
- (block) => !FOOTER_SUBSCRIPTION_BLOCK_ID_SET.has(block.id)
117
- );
118
-
119
- return [...normalizedBlocks, ...extraBlocks];
120
- }
121
-
122
- export { FOOTER_SUBSCRIPTION_WIDGET_SLUG };
@@ -1,162 +0,0 @@
1
- 'use client';
2
-
3
- import { useEffect, useRef, useState } from 'react';
4
- import { useNativeWidgetData } from '@akinon/next/components/theme-editor/hooks/use-native-widget-data';
5
- import { useGetWidgetQuery } from '@akinon/next/data/client/misc';
6
- import {
7
- defaultFooterLogoSettings,
8
- FooterLogoSettings,
9
- parseFooterLogoBlockPayload,
10
- FOOTER_LOGO_PLACEHOLDER_ID,
11
- FOOTER_LOGO_SECTION_ID,
12
- FOOTER_LOGO_BLOCK_ID,
13
- FOOTER_LOGO_WIDGET_SLUG
14
- } from './logo-settings';
15
-
16
- const THEME_CONFIG_SLUG = 'theme-config';
17
-
18
- const BLOCK_META = [
19
- { id: FOOTER_LOGO_BLOCK_ID, type: 'image', label: 'Footer Logo' }
20
- ];
21
-
22
- type ThemeSettings = {
23
- logo?: string;
24
- };
25
-
26
- const parseThemeConfigLogo = (
27
- themeSettings?: ThemeSettings
28
- ): Partial<FooterLogoSettings> => {
29
- if (!themeSettings?.logo) {
30
- return {};
31
- }
32
- return { src: themeSettings.logo };
33
- };
34
-
35
- export function useFooterLogoSettings(
36
- initialSettings?: FooterLogoSettings
37
- ): FooterLogoSettings {
38
- const isDesignerRef = useRef(false);
39
- const [isDesignerChecked, setIsDesignerChecked] = useState(false);
40
-
41
- useEffect(() => {
42
- if (typeof window === 'undefined') return;
43
- isDesignerRef.current = window.self !== window.top;
44
- setIsDesignerChecked(true);
45
- }, []);
46
-
47
- const isDesigner = isDesignerRef.current;
48
-
49
- const { data: themeConfigData } = useGetWidgetQuery(THEME_CONFIG_SLUG, {
50
- skip: !isDesignerChecked || isDesigner
51
- });
52
-
53
- const widgetData = useNativeWidgetData({
54
- widgetSlug: FOOTER_LOGO_WIDGET_SLUG,
55
- sectionId: FOOTER_LOGO_SECTION_ID,
56
- skip: !isDesignerChecked || isDesigner,
57
- blockMeta: BLOCK_META
58
- });
59
-
60
- const [settings, setSettings] = useState<FooterLogoSettings>(
61
- initialSettings || defaultFooterLogoSettings
62
- );
63
- const hasInitialSettings = !!initialSettings;
64
-
65
- useEffect(() => {
66
- if (!isDesignerChecked) return;
67
- if (isDesigner) return;
68
- if (hasInitialSettings) return;
69
- if (widgetData.isLoading && !themeConfigData) return;
70
-
71
- let nextSettings: FooterLogoSettings = { ...defaultFooterLogoSettings };
72
-
73
- const themeSettingsAttr = themeConfigData?.attributes?.theme_settings;
74
- if (themeSettingsAttr) {
75
- try {
76
- let parsedSettings: ThemeSettings | undefined;
77
-
78
- if (typeof themeSettingsAttr === 'string') {
79
- parsedSettings = JSON.parse(themeSettingsAttr) as ThemeSettings;
80
- } else if (
81
- typeof themeSettingsAttr === 'object' &&
82
- 'value' in themeSettingsAttr
83
- ) {
84
- const rawValue = themeSettingsAttr.value;
85
- if (typeof rawValue === 'string') {
86
- parsedSettings = JSON.parse(rawValue) as ThemeSettings;
87
- } else if (rawValue && typeof rawValue === 'object') {
88
- parsedSettings = rawValue as ThemeSettings;
89
- }
90
- } else if (typeof themeSettingsAttr === 'object') {
91
- parsedSettings = themeSettingsAttr as ThemeSettings;
92
- }
93
-
94
- if (parsedSettings) {
95
- nextSettings = {
96
- ...nextSettings,
97
- ...parseThemeConfigLogo(parsedSettings)
98
- };
99
- }
100
- } catch {
101
- // ignore
102
- }
103
- }
104
-
105
- const block = widgetData.getBlock(FOOTER_LOGO_BLOCK_ID);
106
- if (block) {
107
- const overrides = parseFooterLogoBlockPayload(block);
108
- nextSettings = {
109
- ...nextSettings,
110
- ...overrides,
111
- src: overrides.src ?? nextSettings.src
112
- };
113
- }
114
-
115
- setSettings(nextSettings);
116
- }, [
117
- widgetData,
118
- themeConfigData,
119
- hasInitialSettings,
120
- isDesigner,
121
- isDesignerChecked
122
- ]);
123
-
124
- useEffect(() => {
125
- const handleMessage = (event: MessageEvent) => {
126
- const { type, data } = event.data || {};
127
-
128
- if (
129
- (type === 'UPDATE_THEME' || type === 'LOAD_THEME') &&
130
- data?.theme?.placeholders
131
- ) {
132
- const placeholder = data.theme.placeholders.find(
133
- (p: { slug: string }) => p.slug === FOOTER_LOGO_PLACEHOLDER_ID
134
- );
135
- const section = placeholder?.sections?.find(
136
- (s: { id: string }) => s.id === FOOTER_LOGO_SECTION_ID
137
- );
138
- const block = section?.blocks?.find(
139
- (b: { id: string }) => b.id === FOOTER_LOGO_BLOCK_ID
140
- );
141
-
142
- if (block) {
143
- const overrides = parseFooterLogoBlockPayload(block);
144
- if (Object.keys(overrides).length > 0) {
145
- setSettings((prev) => ({
146
- ...prev,
147
- ...overrides,
148
- src: overrides.src ?? prev.src
149
- }));
150
- }
151
- }
152
- }
153
- };
154
-
155
- window.addEventListener('message', handleMessage);
156
- return () => window.removeEventListener('message', handleMessage);
157
- }, []);
158
-
159
- return settings;
160
- }
161
-
162
- export type { FooterLogoSettings };