@akinon/pz-theme 2.0.35-rc.0 → 2.0.35

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 (39) hide show
  1. package/CHANGELOG.md +12 -28
  2. package/package.json +4 -3
  3. package/src/__tests__/theme-contract.test.ts +130 -0
  4. package/src/blocks/__tests__/text-block.test.tsx +8 -1
  5. package/src/blocks/__tests__/video-block.test.tsx +14 -7
  6. package/src/blocks/counter-block.tsx +44 -56
  7. package/src/blocks/group-block.tsx +23 -22
  8. package/src/blocks/hotspot-block.tsx +171 -80
  9. package/src/blocks/input-block.tsx +15 -17
  10. package/src/blocks/link-block.tsx +18 -21
  11. package/src/blocks/slider-block.tsx +15 -12
  12. package/src/components/with-designer-features.tsx +2 -0
  13. package/src/editor-bridge.ts +160 -0
  14. package/src/hooks/use-designer-features.tsx +30 -37
  15. package/src/placeholder-registry.ts +5 -7
  16. package/src/sections/__tests__/countdown-campaign-banner-section.test.tsx +8 -4
  17. package/src/sections/__tests__/coupon-banner-section.test.tsx +4 -2
  18. package/src/sections/before-after-section.tsx +189 -134
  19. package/src/sections/contact-form-section.tsx +185 -60
  20. package/src/sections/countdown-campaign-banner-section.tsx +73 -27
  21. package/src/sections/coupon-banner-section.tsx +152 -48
  22. package/src/sections/featured-product-spotlight-section.tsx +67 -66
  23. package/src/sections/find-in-store-section.tsx +37 -25
  24. package/src/sections/hover-showcase-section.tsx +221 -89
  25. package/src/sections/image-hotspot-section.tsx +208 -94
  26. package/src/sections/installment-options-section.tsx +268 -259
  27. package/src/sections/notification-banner-section.tsx +111 -25
  28. package/src/sections/order-tracking-lookup-section.tsx +272 -247
  29. package/src/sections/posts-slider-section.tsx +17 -16
  30. package/src/sections/pre-order-launch-banner-section.tsx +31 -50
  31. package/src/sections/section-wrapper.tsx +9 -10
  32. package/src/sections/shipping-threshold-progress-section.tsx +72 -29
  33. package/src/sections/stats-counter-section.tsx +68 -30
  34. package/src/sections/tabs-section.tsx +124 -147
  35. package/src/theme-placeholder-client.tsx +11 -14
  36. package/src/theme-placeholder-wrapper.tsx +42 -51
  37. package/src/theme-section.tsx +27 -34
  38. package/src/utils/__tests__/transform-styles.test.ts +97 -0
  39. package/src/utils/index.ts +9 -0
@@ -8,6 +8,7 @@ import { twMerge } from 'tailwind-merge';
8
8
  import clsx from 'clsx';
9
9
  import ThemeBlock from '../theme-block';
10
10
 
11
+ import { postToEditor } from '../editor-bridge';
11
12
  interface NotificationBannerSectionProps {
12
13
  section: Section;
13
14
  currentBreakpoint?: string;
@@ -30,30 +31,74 @@ export default function NotificationBannerSection({
30
31
  const properties = section.properties || {};
31
32
 
32
33
  const gradientStart = resolveThemeCssVariables(
33
- getResponsiveValue(styles['background-gradient-start'], currentBreakpoint, '#a8e063') as string,
34
+ getResponsiveValue(
35
+ styles['background-gradient-start'],
36
+ currentBreakpoint,
37
+ '#a8e063'
38
+ ) as string,
34
39
  themeSettings
35
40
  );
36
41
  const gradientEnd = resolveThemeCssVariables(
37
- getResponsiveValue(styles['background-gradient-end'], currentBreakpoint, '#d4fc79') as string,
42
+ getResponsiveValue(
43
+ styles['background-gradient-end'],
44
+ currentBreakpoint,
45
+ '#d4fc79'
46
+ ) as string,
38
47
  themeSettings
39
48
  );
40
- const borderRadius = getResponsiveValue(styles['border-radius'], currentBreakpoint, '16px') as string;
41
- const paddingTop = getResponsiveValue(styles['padding-top'], currentBreakpoint, 20);
42
- const paddingRight = getResponsiveValue(styles['padding-right'], currentBreakpoint, 24);
43
- const paddingBottom = getResponsiveValue(styles['padding-bottom'], currentBreakpoint, 20);
44
- const paddingLeft = getResponsiveValue(styles['padding-left'], currentBreakpoint, 24);
49
+ const borderRadius = getResponsiveValue(
50
+ styles['border-radius'],
51
+ currentBreakpoint,
52
+ '16px'
53
+ ) as string;
54
+ const paddingTop = getResponsiveValue(
55
+ styles['padding-top'],
56
+ currentBreakpoint,
57
+ 20
58
+ );
59
+ const paddingRight = getResponsiveValue(
60
+ styles['padding-right'],
61
+ currentBreakpoint,
62
+ 24
63
+ );
64
+ const paddingBottom = getResponsiveValue(
65
+ styles['padding-bottom'],
66
+ currentBreakpoint,
67
+ 20
68
+ );
69
+ const paddingLeft = getResponsiveValue(
70
+ styles['padding-left'],
71
+ currentBreakpoint,
72
+ 24
73
+ );
45
74
  const gap = getResponsiveValue(styles.gap, currentBreakpoint, 16);
46
- const maxWidth = getResponsiveValue(styles['max-width'], currentBreakpoint, 'normal') as string;
75
+ const maxWidth = getResponsiveValue(
76
+ styles['max-width'],
77
+ currentBreakpoint,
78
+ 'normal'
79
+ ) as string;
47
80
  const closeButtonColor = resolveThemeCssVariables(
48
- getResponsiveValue(styles['close-button-color'], currentBreakpoint, '#33691e') as string,
81
+ getResponsiveValue(
82
+ styles['close-button-color'],
83
+ currentBreakpoint,
84
+ '#33691e'
85
+ ) as string,
49
86
  themeSettings
50
87
  );
51
88
  const iconBgColor = resolveThemeCssVariables(
52
- getResponsiveValue(styles['icon-background-color'], currentBreakpoint, '#ffffff40') as string,
89
+ getResponsiveValue(
90
+ styles['icon-background-color'],
91
+ currentBreakpoint,
92
+ '#ffffff40'
93
+ ) as string,
53
94
  themeSettings
54
95
  );
55
96
 
56
- const dismissible = getResponsiveValue(properties.dismissible, currentBreakpoint, true);
97
+ const dismissible = getResponsiveValue(
98
+ properties.dismissible,
99
+ currentBreakpoint,
100
+ true
101
+ );
57
102
 
58
103
  const maxWidthClass =
59
104
  maxWidth === 'narrow'
@@ -78,22 +123,51 @@ export default function NotificationBannerSection({
78
123
  selectedBlockId={selectedBlockId}
79
124
  currentBreakpoint={currentBreakpoint}
80
125
  onMoveUp={() => {
81
- if (window.parent) window.parent.postMessage({ type: 'MOVE_BLOCK_UP', data: { placeholderId, sectionId: section.id, blockId: block.id } }, '*');
126
+ if (window.parent)
127
+ postToEditor({
128
+ type: 'MOVE_BLOCK_UP',
129
+ data: { placeholderId, sectionId: section.id, blockId: block.id }
130
+ });
82
131
  }}
83
132
  onMoveDown={() => {
84
- if (window.parent) window.parent.postMessage({ type: 'MOVE_BLOCK_DOWN', data: { placeholderId, sectionId: section.id, blockId: block.id } }, '*');
133
+ if (window.parent)
134
+ postToEditor({
135
+ type: 'MOVE_BLOCK_DOWN',
136
+ data: { placeholderId, sectionId: section.id, blockId: block.id }
137
+ });
85
138
  }}
86
139
  onDuplicate={() => {
87
- if (window.parent) window.parent.postMessage({ type: 'DUPLICATE_BLOCK', data: { placeholderId, sectionId: section.id, blockId: block.id } }, '*');
140
+ if (window.parent)
141
+ postToEditor({
142
+ type: 'DUPLICATE_BLOCK',
143
+ data: { placeholderId, sectionId: section.id, blockId: block.id }
144
+ });
88
145
  }}
89
146
  onToggleVisibility={() => {
90
- if (window.parent) window.parent.postMessage({ type: 'TOGGLE_BLOCK_VISIBILITY', data: { placeholderId, sectionId: section.id, blockId: block.id } }, '*');
147
+ if (window.parent)
148
+ postToEditor({
149
+ type: 'TOGGLE_BLOCK_VISIBILITY',
150
+ data: { placeholderId, sectionId: section.id, blockId: block.id }
151
+ });
91
152
  }}
92
153
  onDelete={() => {
93
- if (window.parent) window.parent.postMessage({ type: 'DELETE_BLOCK', data: { placeholderId, sectionId: section.id, blockId: block.id } }, '*');
154
+ if (window.parent)
155
+ postToEditor({
156
+ type: 'DELETE_BLOCK',
157
+ data: { placeholderId, sectionId: section.id, blockId: block.id }
158
+ });
94
159
  }}
95
160
  onRename={(newLabel) => {
96
- if (window.parent) window.parent.postMessage({ type: 'RENAME_BLOCK', data: { placeholderId, sectionId: section.id, blockId: block.id, label: newLabel } }, '*');
161
+ if (window.parent)
162
+ postToEditor({
163
+ type: 'RENAME_BLOCK',
164
+ data: {
165
+ placeholderId,
166
+ sectionId: section.id,
167
+ blockId: block.id,
168
+ label: newLabel
169
+ }
170
+ });
97
171
  }}
98
172
  />
99
173
  );
@@ -103,8 +177,8 @@ export default function NotificationBannerSection({
103
177
  return null;
104
178
  }
105
179
 
106
- const iconBlock = section.blocks?.find(b => b.type === 'icon');
107
- const contentBlocks = section.blocks?.filter(b => b.type !== 'icon') || [];
180
+ const iconBlock = section.blocks?.find((b) => b.type === 'icon');
181
+ const contentBlocks = section.blocks?.filter((b) => b.type !== 'icon') || [];
108
182
 
109
183
  return (
110
184
  <div
@@ -119,11 +193,23 @@ export default function NotificationBannerSection({
119
193
  style={{
120
194
  background: `linear-gradient(135deg, ${gradientStart} 0%, ${gradientEnd} 100%)`,
121
195
  borderRadius,
122
- paddingTop: typeof paddingTop === 'number' ? `${paddingTop}px` : paddingTop as string,
123
- paddingRight: typeof paddingRight === 'number' ? `${paddingRight}px` : paddingRight as string,
124
- paddingBottom: typeof paddingBottom === 'number' ? `${paddingBottom}px` : paddingBottom as string,
125
- paddingLeft: typeof paddingLeft === 'number' ? `${paddingLeft}px` : paddingLeft as string,
126
- gap: typeof gap === 'number' ? `${gap}px` : gap as string
196
+ paddingTop:
197
+ typeof paddingTop === 'number'
198
+ ? `${paddingTop}px`
199
+ : (paddingTop as string),
200
+ paddingRight:
201
+ typeof paddingRight === 'number'
202
+ ? `${paddingRight}px`
203
+ : (paddingRight as string),
204
+ paddingBottom:
205
+ typeof paddingBottom === 'number'
206
+ ? `${paddingBottom}px`
207
+ : (paddingBottom as string),
208
+ paddingLeft:
209
+ typeof paddingLeft === 'number'
210
+ ? `${paddingLeft}px`
211
+ : (paddingLeft as string),
212
+ gap: typeof gap === 'number' ? `${gap}px` : (gap as string)
127
213
  }}
128
214
  >
129
215
  {iconBlock && (
@@ -140,7 +226,7 @@ export default function NotificationBannerSection({
140
226
  )}
141
227
 
142
228
  <div className="flex-1 min-w-0">
143
- {contentBlocks.map(block => renderBlock(block))}
229
+ {contentBlocks.map((block) => renderBlock(block))}
144
230
  </div>
145
231
 
146
232
  {Boolean(dismissible) && (