@akinon/next 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 (64) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/api/auth.ts +292 -60
  3. package/bin/pz-install-plugins.js +1 -1
  4. package/package.json +3 -3
  5. package/types/index.ts +19 -6
  6. package/types/next-auth.d.ts +1 -1
  7. package/with-pz-config.js +8 -1
  8. package/components/theme-editor/blocks/accordion-block.tsx +0 -136
  9. package/components/theme-editor/blocks/block-renderer-registry.tsx +0 -77
  10. package/components/theme-editor/blocks/button-block.tsx +0 -593
  11. package/components/theme-editor/blocks/counter-block.tsx +0 -348
  12. package/components/theme-editor/blocks/divider-block.tsx +0 -20
  13. package/components/theme-editor/blocks/embed-block.tsx +0 -208
  14. package/components/theme-editor/blocks/group-block.tsx +0 -116
  15. package/components/theme-editor/blocks/hotspot-block.tsx +0 -147
  16. package/components/theme-editor/blocks/icon-block.tsx +0 -230
  17. package/components/theme-editor/blocks/image-block.tsx +0 -137
  18. package/components/theme-editor/blocks/image-gallery-block.tsx +0 -269
  19. package/components/theme-editor/blocks/input-block.tsx +0 -123
  20. package/components/theme-editor/blocks/link-block.tsx +0 -216
  21. package/components/theme-editor/blocks/lottie-block.tsx +0 -325
  22. package/components/theme-editor/blocks/map-block.tsx +0 -89
  23. package/components/theme-editor/blocks/slider-block.tsx +0 -595
  24. package/components/theme-editor/blocks/tab-block.tsx +0 -10
  25. package/components/theme-editor/blocks/text-block.tsx +0 -52
  26. package/components/theme-editor/blocks/video-block.tsx +0 -122
  27. package/components/theme-editor/components/action-toolbar.tsx +0 -305
  28. package/components/theme-editor/components/designer-overlay.tsx +0 -74
  29. package/components/theme-editor/components/with-designer-features.tsx +0 -142
  30. package/components/theme-editor/dynamic-font-loader.tsx +0 -79
  31. package/components/theme-editor/hooks/use-designer-features.tsx +0 -100
  32. package/components/theme-editor/hooks/use-external-designer.tsx +0 -95
  33. package/components/theme-editor/hooks/use-native-widget-data.ts +0 -188
  34. package/components/theme-editor/hooks/use-visibility-context.ts +0 -27
  35. package/components/theme-editor/placeholder-registry.ts +0 -31
  36. package/components/theme-editor/sections/before-after-section.tsx +0 -245
  37. package/components/theme-editor/sections/contact-form-section.tsx +0 -563
  38. package/components/theme-editor/sections/countdown-campaign-banner-section.tsx +0 -433
  39. package/components/theme-editor/sections/coupon-banner-section.tsx +0 -710
  40. package/components/theme-editor/sections/divider-section.tsx +0 -62
  41. package/components/theme-editor/sections/featured-product-spotlight-section.tsx +0 -507
  42. package/components/theme-editor/sections/find-in-store-section.tsx +0 -1995
  43. package/components/theme-editor/sections/hover-showcase-section.tsx +0 -326
  44. package/components/theme-editor/sections/image-hotspot-section.tsx +0 -142
  45. package/components/theme-editor/sections/installment-options-section.tsx +0 -1065
  46. package/components/theme-editor/sections/notification-banner-section.tsx +0 -173
  47. package/components/theme-editor/sections/order-tracking-lookup-section.tsx +0 -1379
  48. package/components/theme-editor/sections/posts-slider-section.tsx +0 -472
  49. package/components/theme-editor/sections/pre-order-launch-banner-section.tsx +0 -663
  50. package/components/theme-editor/sections/section-renderer-registry.tsx +0 -89
  51. package/components/theme-editor/sections/section-wrapper.tsx +0 -135
  52. package/components/theme-editor/sections/shipping-threshold-progress-section.tsx +0 -586
  53. package/components/theme-editor/sections/stats-counter-section.tsx +0 -486
  54. package/components/theme-editor/sections/tabs-section.tsx +0 -578
  55. package/components/theme-editor/theme-block.tsx +0 -102
  56. package/components/theme-editor/theme-placeholder-client.tsx +0 -218
  57. package/components/theme-editor/theme-placeholder-wrapper.tsx +0 -732
  58. package/components/theme-editor/theme-placeholder.tsx +0 -288
  59. package/components/theme-editor/theme-section.tsx +0 -1224
  60. package/components/theme-editor/theme-settings-context.tsx +0 -13
  61. package/components/theme-editor/utils/index.ts +0 -792
  62. package/components/theme-editor/utils/iterator-utils.ts +0 -234
  63. package/components/theme-editor/utils/publish-window.ts +0 -86
  64. package/components/theme-editor/utils/visibility-rules.ts +0 -188
@@ -1,578 +0,0 @@
1
- import React, { useCallback, useEffect, useState } from 'react';
2
- import { Section } from '../theme-section';
3
- import ThemeBlock from '../theme-block';
4
- import {
5
- getCSSStyles,
6
- resolveThemeCssVariables,
7
- resolveThemeStyleObject
8
- } from '../utils';
9
- import { twMerge } from 'tailwind-merge';
10
- import clsx from 'clsx';
11
- import { useThemeSettingsContext } from '../theme-settings-context';
12
-
13
- interface TabsSectionProps {
14
- section: Section;
15
- currentBreakpoint?: string;
16
- placeholderId?: string;
17
- isDesigner?: boolean;
18
- selectedBlockId?: string | null;
19
- }
20
-
21
- const TabsSection: React.FC<TabsSectionProps> = ({
22
- section,
23
- currentBreakpoint = 'desktop',
24
- placeholderId = '',
25
- isDesigner = false,
26
- selectedBlockId = null
27
- }) => {
28
- const [activeTabIndex, setActiveTabIndex] = useState(0);
29
- const themeSettings = useThemeSettingsContext();
30
-
31
- // Separate tab blocks from non-tab blocks (like headers)
32
- const nonTabBlocks = section.blocks
33
- .filter((block) => block.type !== 'tab' && (isDesigner ? true : !block.hidden))
34
- .sort((a, b) => (a.order || 0) - (b.order || 0));
35
-
36
- const tabBlocks = section.blocks
37
- .filter((block) => block.type === 'tab' && (isDesigner ? true : !block.hidden))
38
- .sort((a, b) => (a.order || 0) - (b.order || 0));
39
-
40
- const getResponsiveValue = useCallback(
41
- <T,>(value: unknown, fallback: T): T => {
42
- if (value === undefined || value === null || value === '') return fallback;
43
- if (typeof value === 'object' && !Array.isArray(value)) {
44
- const responsiveValue = value as Record<string, T | undefined> & {
45
- desktop?: T;
46
- };
47
- const matchedValue =
48
- responsiveValue[currentBreakpoint] ?? responsiveValue.desktop;
49
- return matchedValue !== undefined ? (matchedValue as T) : fallback;
50
- }
51
- return value as T;
52
- },
53
- [currentBreakpoint]
54
- );
55
-
56
- const findTabIndexBySelectedBlock = useCallback(
57
- (blockId: string | null): number => {
58
- if (!blockId) return -1;
59
-
60
- const hasBlockInTree = (blocks?: Section['blocks']): boolean => {
61
- if (!blocks || blocks.length === 0) return false;
62
-
63
- for (const block of blocks) {
64
- if (block.id === blockId) return true;
65
- if (hasBlockInTree(block.blocks)) return true;
66
- }
67
-
68
- return false;
69
- };
70
-
71
- return tabBlocks.findIndex((tabBlock) => {
72
- if (tabBlock.id === blockId) return true;
73
- return hasBlockInTree(tabBlock.blocks);
74
- });
75
- },
76
- [tabBlocks]
77
- );
78
-
79
- useEffect(() => {
80
- if (tabBlocks.length === 0) {
81
- if (activeTabIndex !== 0) setActiveTabIndex(0);
82
- return;
83
- }
84
-
85
- const selectedTabIndex = findTabIndexBySelectedBlock(selectedBlockId);
86
- if (selectedTabIndex >= 0) {
87
- if (selectedTabIndex !== activeTabIndex) {
88
- setActiveTabIndex(selectedTabIndex);
89
- }
90
- return;
91
- }
92
-
93
- if (activeTabIndex > tabBlocks.length - 1) {
94
- setActiveTabIndex(tabBlocks.length - 1);
95
- }
96
- }, [
97
- activeTabIndex,
98
- findTabIndexBySelectedBlock,
99
- selectedBlockId,
100
- tabBlocks
101
- ]);
102
-
103
- const activeTabColor = resolveThemeCssVariables(
104
- getResponsiveValue<string>(
105
- section.styles?.['active-tab-color'],
106
- 'var(--theme-primary)'
107
- ),
108
- themeSettings
109
- );
110
- const activeTabBorderColor = resolveThemeCssVariables(
111
- getResponsiveValue<string>(
112
- section.styles?.['active-tab-border-color'],
113
- 'var(--theme-primary)'
114
- ),
115
- themeSettings
116
- );
117
- const activeTabBackgroundColor = resolveThemeCssVariables(
118
- getResponsiveValue<string>(
119
- section.styles?.['active-tab-background-color'],
120
- 'transparent'
121
- ),
122
- themeSettings
123
- );
124
- const headerBorderBottom = resolveThemeCssVariables(
125
- getResponsiveValue<string>(
126
- section.styles?.['header-border-bottom'],
127
- '1px solid #e5e7eb'
128
- ),
129
- themeSettings
130
- );
131
-
132
- const kebabToCamel = (str: string): string => {
133
- return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
134
- };
135
-
136
- const getCSSProperties = (
137
- properties?: Record<string, unknown>
138
- ): React.CSSProperties => {
139
- if (!properties) return {};
140
-
141
- const styles: Record<string, string | number> = {};
142
-
143
- Object.keys(properties).forEach((key) => {
144
- const value = getResponsiveValue<string | number | undefined>(
145
- properties[key],
146
- undefined
147
- );
148
- if (value === undefined || value === null) return;
149
-
150
- const camelKey = kebabToCamel(key);
151
- let finalValue: string | number = value;
152
-
153
- if (key.startsWith('padding-') || key.startsWith('margin-')) {
154
- finalValue =
155
- typeof value === 'number' ? `${value}px` : (value as string);
156
- } else if (typeof value === 'string') {
157
- finalValue = resolveThemeCssVariables(value, themeSettings);
158
- }
159
-
160
- styles[camelKey] = finalValue;
161
- });
162
-
163
- return styles as React.CSSProperties;
164
- };
165
-
166
- const sectionStyles = {
167
- ...getCSSProperties(section.styles),
168
- position: 'relative'
169
- } as React.CSSProperties;
170
-
171
- const containerStyles: Record<string, string | number> = {
172
- ...(sectionStyles as Record<string, string | number>)
173
- };
174
-
175
- const maxWidth = getResponsiveValue(
176
- section.styles?.['max-width'],
177
- 'normal'
178
- ) as string;
179
- const maxWidthClass =
180
- maxWidth === 'narrow'
181
- ? 'max-w-4xl'
182
- : maxWidth === 'normal'
183
- ? 'max-w-7xl'
184
- : '';
185
- const hasMaxWidth = maxWidth !== 'none' && maxWidth !== 'full';
186
-
187
- if (tabBlocks.length === 0) {
188
- return (
189
- <div
190
- className="p-4 text-gray-400 border border-dashed border-gray-300 rounded"
191
- style={sectionStyles}
192
- >
193
- No tabs available
194
- </div>
195
- );
196
- }
197
-
198
- return (
199
- <div
200
- className={twMerge(
201
- clsx(
202
- 'relative z-10 group/blocks w-full',
203
- hasMaxWidth && 'mx-auto',
204
- maxWidthClass
205
- )
206
- )}
207
- style={containerStyles as React.CSSProperties}
208
- >
209
- {/* Render non-tab blocks first (like FAQ Header) */}
210
- {nonTabBlocks.map((block, index) => (
211
- <ThemeBlock
212
- key={block.id || `non-tab-block-${index}`}
213
- block={block}
214
- placeholderId={placeholderId}
215
- sectionId={section.id}
216
- isDesigner={isDesigner}
217
- isSelected={selectedBlockId === block.id}
218
- selectedBlockId={selectedBlockId}
219
- onMoveUp={() => {
220
- if (window.parent) {
221
- window.parent.postMessage(
222
- {
223
- type: 'MOVE_BLOCK_UP',
224
- data: {
225
- placeholderId,
226
- sectionId: section.id,
227
- blockId: block.id
228
- }
229
- },
230
- '*'
231
- );
232
- }
233
- }}
234
- onMoveDown={() => {
235
- if (window.parent) {
236
- window.parent.postMessage(
237
- {
238
- type: 'MOVE_BLOCK_DOWN',
239
- data: {
240
- placeholderId,
241
- sectionId: section.id,
242
- blockId: block.id
243
- }
244
- },
245
- '*'
246
- );
247
- }
248
- }}
249
- onDuplicate={() => {
250
- if (window.parent) {
251
- window.parent.postMessage(
252
- {
253
- type: 'DUPLICATE_BLOCK',
254
- data: {
255
- placeholderId,
256
- sectionId: section.id,
257
- blockId: block.id
258
- }
259
- },
260
- '*'
261
- );
262
- }
263
- }}
264
- onToggleVisibility={() => {
265
- if (window.parent) {
266
- window.parent.postMessage(
267
- {
268
- type: 'TOGGLE_BLOCK_VISIBILITY',
269
- data: {
270
- placeholderId,
271
- sectionId: section.id,
272
- blockId: block.id
273
- }
274
- },
275
- '*'
276
- );
277
- }
278
- }}
279
- onDelete={() => {
280
- if (window.parent) {
281
- window.parent.postMessage(
282
- {
283
- type: 'DELETE_BLOCK',
284
- data: {
285
- placeholderId,
286
- sectionId: section.id,
287
- blockId: block.id
288
- }
289
- },
290
- '*'
291
- );
292
- }
293
- }}
294
- onRename={(newLabel) => {
295
- if (window.parent) {
296
- window.parent.postMessage(
297
- {
298
- type: 'RENAME_BLOCK',
299
- data: {
300
- placeholderId,
301
- sectionId: section.id,
302
- blockId: block.id,
303
- label: newLabel
304
- }
305
- },
306
- '*'
307
- );
308
- }
309
- }}
310
- />
311
- ))}
312
-
313
- {/* Tab headers */}
314
- <div
315
- style={{
316
- display: 'flex',
317
- gap: '0px',
318
- borderBottom: headerBorderBottom,
319
- position: 'relative'
320
- }}
321
- >
322
- {tabBlocks.map((tabBlock, index) => {
323
- const headerBlock = tabBlock.blocks?.find(
324
- (b) => b.label === 'Tab Header'
325
- );
326
-
327
- if (!headerBlock) return null;
328
-
329
- const isActive = index === activeTabIndex;
330
- const headerStyles = resolveThemeStyleObject(
331
- getCSSStyles(headerBlock.styles || {}, themeSettings, currentBreakpoint),
332
- themeSettings
333
- );
334
- const cleanHeaderStyles = {
335
- ...headerStyles
336
- } as Record<string, string | number>;
337
- const headerTextColor = cleanHeaderStyles.color as string | undefined;
338
-
339
- delete cleanHeaderStyles.border;
340
- delete cleanHeaderStyles.borderBottom;
341
- delete cleanHeaderStyles.backgroundColor;
342
- delete cleanHeaderStyles.color;
343
-
344
- return (
345
- <div
346
- key={tabBlock.id || `tab-header-${index}`}
347
- className="tab-header-wrapper"
348
- style={{
349
- position: 'relative'
350
- }}
351
- >
352
- {isDesigner && (
353
- <div
354
- style={{
355
- position: 'absolute',
356
- top: 0,
357
- left: 0,
358
- right: 0,
359
- zIndex: 10,
360
- pointerEvents: 'none',
361
- height: '100%'
362
- }}
363
- >
364
- <ThemeBlock
365
- block={tabBlock}
366
- placeholderId={placeholderId}
367
- sectionId={section.id}
368
- isDesigner={isDesigner}
369
- isSelected={selectedBlockId === tabBlock.id}
370
- selectedBlockId={selectedBlockId}
371
- onMoveUp={() => {
372
- if (window.parent) {
373
- window.parent.postMessage(
374
- {
375
- type: 'MOVE_BLOCK_UP',
376
- data: {
377
- placeholderId,
378
- sectionId: section.id,
379
- blockId: tabBlock.id
380
- }
381
- },
382
- '*'
383
- );
384
- }
385
- }}
386
- onMoveDown={() => {
387
- if (window.parent) {
388
- window.parent.postMessage(
389
- {
390
- type: 'MOVE_BLOCK_DOWN',
391
- data: {
392
- placeholderId,
393
- sectionId: section.id,
394
- blockId: tabBlock.id
395
- }
396
- },
397
- '*'
398
- );
399
- }
400
- }}
401
- onDuplicate={() => {
402
- if (window.parent) {
403
- window.parent.postMessage(
404
- {
405
- type: 'DUPLICATE_BLOCK',
406
- data: {
407
- placeholderId,
408
- sectionId: section.id,
409
- blockId: tabBlock.id
410
- }
411
- },
412
- '*'
413
- );
414
- }
415
- }}
416
- onToggleVisibility={() => {
417
- if (window.parent) {
418
- window.parent.postMessage(
419
- {
420
- type: 'TOGGLE_BLOCK_VISIBILITY',
421
- data: {
422
- placeholderId,
423
- sectionId: section.id,
424
- blockId: tabBlock.id
425
- }
426
- },
427
- '*'
428
- );
429
- }
430
- }}
431
- onDelete={() => {
432
- if (window.parent) {
433
- window.parent.postMessage(
434
- {
435
- type: 'DELETE_BLOCK',
436
- data: {
437
- placeholderId,
438
- sectionId: section.id,
439
- blockId: tabBlock.id
440
- }
441
- },
442
- '*'
443
- );
444
- }
445
- }}
446
- onRename={(newLabel) => {
447
- if (window.parent) {
448
- window.parent.postMessage(
449
- {
450
- type: 'RENAME_BLOCK',
451
- data: {
452
- placeholderId,
453
- sectionId: section.id,
454
- blockId: tabBlock.id,
455
- label: newLabel
456
- }
457
- },
458
- '*'
459
- );
460
- }
461
- }}
462
- />
463
- </div>
464
- )}
465
-
466
- <div
467
- style={{
468
- ...cleanHeaderStyles,
469
- cursor: 'pointer',
470
- borderTop: 'none',
471
- borderLeft: 'none',
472
- borderRight: 'none',
473
- borderBottom: isActive
474
- ? `2px solid ${activeTabBorderColor}`
475
- : '2px solid transparent',
476
- backgroundColor: isActive
477
- ? activeTabBackgroundColor
478
- : 'transparent',
479
- color: isActive
480
- ? activeTabColor
481
- : headerTextColor || 'inherit',
482
- position: 'relative',
483
- zIndex: 1
484
- }}
485
- onClick={() => setActiveTabIndex(index)}
486
- >
487
- {headerBlock.blocks
488
- ?.filter((childBlock) => (isDesigner ? true : !childBlock.hidden))
489
- .sort((a, b) => (a.order || 0) - (b.order || 0))
490
- .map((childBlock, childIndex) => {
491
- // If tab is active, we want to override the child's color with the active tab color
492
- // So we remove the color from the child's styles to let it inherit
493
- const blockToRender =
494
- isActive && childBlock.styles?.color
495
- ? {
496
- ...childBlock,
497
- styles: {
498
- ...childBlock.styles,
499
- color: undefined
500
- }
501
- }
502
- : childBlock;
503
-
504
- return (
505
- <ThemeBlock
506
- key={childBlock.id || `header-child-${childIndex}`}
507
- block={blockToRender}
508
- placeholderId={placeholderId}
509
- sectionId={section.id}
510
- isDesigner={isDesigner}
511
- isSelected={selectedBlockId === childBlock.id}
512
- selectedBlockId={selectedBlockId}
513
- currentBreakpoint={currentBreakpoint}
514
- onMoveUp={undefined}
515
- onMoveDown={undefined}
516
- onDuplicate={undefined}
517
- onToggleVisibility={undefined}
518
- onDelete={undefined}
519
- onRename={undefined}
520
- />
521
- );
522
- })}
523
- </div>
524
- </div>
525
- );
526
- })}
527
- </div>
528
-
529
- <div>
530
- {tabBlocks.map((tabBlock, index) => {
531
- if (index !== activeTabIndex) return null;
532
-
533
- const contentBlock = tabBlock.blocks?.find(
534
- (b) => b.label === 'Tab Content'
535
- );
536
-
537
- if (!contentBlock) return null;
538
-
539
- const contentStyles = resolveThemeStyleObject(
540
- getCSSStyles(contentBlock.styles || {}, themeSettings, currentBreakpoint),
541
- themeSettings
542
- );
543
-
544
- return (
545
- <div
546
- key={tabBlock.id || `tab-content-${index}`}
547
- style={contentStyles}
548
- >
549
- {contentBlock.blocks
550
- ?.filter((childBlock) => (isDesigner ? true : !childBlock.hidden))
551
- .sort((a, b) => (a.order || 0) - (b.order || 0))
552
- .map((childBlock, childIndex) => (
553
- <ThemeBlock
554
- key={childBlock.id || `content-child-${childIndex}`}
555
- block={childBlock}
556
- placeholderId={placeholderId}
557
- sectionId={section.id}
558
- isDesigner={isDesigner}
559
- isSelected={selectedBlockId === childBlock.id}
560
- selectedBlockId={selectedBlockId}
561
- currentBreakpoint={currentBreakpoint}
562
- onMoveUp={undefined}
563
- onMoveDown={undefined}
564
- onDuplicate={undefined}
565
- onToggleVisibility={undefined}
566
- onDelete={undefined}
567
- onRename={undefined}
568
- />
569
- ))}
570
- </div>
571
- );
572
- })}
573
- </div>
574
- </div>
575
- );
576
- };
577
-
578
- export default TabsSection;
@@ -1,102 +0,0 @@
1
- 'use client';
2
-
3
- import React from 'react';
4
- import blockRendererRegistry from './blocks/block-renderer-registry';
5
- import { WithDesignerFeatures } from './components/with-designer-features';
6
- import { isPublishWindowVisible } from './utils';
7
-
8
- export interface Block {
9
- id: string;
10
- styleSourceId?: string;
11
- type: string;
12
- label: string;
13
- value?: any;
14
- properties: any;
15
- styles: any;
16
- order: number;
17
- hidden: boolean;
18
- locked?: boolean;
19
- blocks?: Block[]; // Optional - only group blocks have nested blocks
20
- isIterator?: boolean;
21
- iteratorDataPath?: string;
22
- }
23
-
24
- interface ThemeBlockProps {
25
- block: Block;
26
- placeholderId: string;
27
- selectedBlockId?: string | null;
28
- sectionId: string;
29
- isDesigner?: boolean;
30
- isSelected?: boolean;
31
- currentBreakpoint?: string;
32
- onSelect?: (blockId: string) => void;
33
- onMoveUp?: () => void;
34
- onMoveDown?: () => void;
35
- onDuplicate?: () => void;
36
- onToggleVisibility?: () => void;
37
- onDelete?: () => void;
38
- onRename?: (newLabel: string) => void;
39
- }
40
-
41
- export default function ThemeBlock({
42
- block,
43
- placeholderId,
44
- selectedBlockId,
45
- sectionId,
46
- isDesigner = false,
47
- isSelected = false,
48
- currentBreakpoint = 'desktop',
49
- onSelect,
50
- onMoveUp,
51
- onMoveDown,
52
- onDuplicate,
53
- onToggleVisibility,
54
- onDelete,
55
- onRename
56
- }: ThemeBlockProps) {
57
- const BlockRenderer = blockRendererRegistry.getRenderer(block.type);
58
-
59
- if (!BlockRenderer) {
60
- return <div>Unknown block type: {block.type}</div>;
61
- }
62
-
63
- if (
64
- !isDesigner &&
65
- !isPublishWindowVisible(block.properties?.['publish-window'])
66
- ) {
67
- return null;
68
- }
69
-
70
- return (
71
- <WithDesignerFeatures
72
- block={block}
73
- placeholderId={placeholderId}
74
- sectionId={sectionId}
75
- isDesigner={isDesigner}
76
- isSelected={isSelected}
77
- currentBreakpoint={currentBreakpoint}
78
- onMoveUp={onMoveUp}
79
- onMoveDown={onMoveDown}
80
- onDuplicate={onDuplicate}
81
- onToggleVisibility={onToggleVisibility}
82
- onDelete={onDelete}
83
- onRename={onRename}
84
- >
85
- <BlockRenderer
86
- block={block}
87
- placeholderId={placeholderId}
88
- sectionId={sectionId}
89
- isDesigner={isDesigner}
90
- isSelected={isSelected}
91
- selectedBlockId={selectedBlockId}
92
- currentBreakpoint={currentBreakpoint}
93
- onMoveUp={onMoveUp}
94
- onMoveDown={onMoveDown}
95
- onDuplicate={onDuplicate}
96
- onToggleVisibility={onToggleVisibility}
97
- onDelete={onDelete}
98
- onRename={onRename}
99
- />
100
- </WithDesignerFeatures>
101
- );
102
- }