@morphika/andami 0.5.1 → 0.5.2

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 (117) hide show
  1. package/app/admin/assets/page.tsx +6 -6
  2. package/app/admin/database/page.tsx +302 -302
  3. package/app/admin/error.tsx +53 -53
  4. package/app/admin/layout.tsx +320 -320
  5. package/app/admin/navigation/page.tsx +255 -255
  6. package/app/admin/pages/[slug]/page.tsx +6 -6
  7. package/app/admin/pages/page.tsx +11 -11
  8. package/app/admin/projects/page.tsx +14 -14
  9. package/app/admin/setup/page.tsx +1 -1
  10. package/app/admin/styles/page.tsx +1 -1
  11. package/components/admin/MetadataEditor.tsx +6 -6
  12. package/components/admin/nav-builder/NavBuilder.tsx +1 -1
  13. package/components/admin/nav-builder/NavBuilderGrid.tsx +3 -3
  14. package/components/admin/nav-builder/NavGridCell.tsx +48 -48
  15. package/components/admin/nav-builder/NavGridItem.tsx +4 -4
  16. package/components/admin/nav-builder/NavItemSettings.tsx +331 -331
  17. package/components/admin/nav-builder/NavItemTypePicker.tsx +102 -102
  18. package/components/admin/nav-builder/NavLivePreview.tsx +1 -1
  19. package/components/admin/nav-builder/NavMobileLivePreview.tsx +226 -226
  20. package/components/admin/nav-builder/NavMobileSettings.tsx +242 -242
  21. package/components/admin/nav-builder/NavSettingsFields.tsx +514 -514
  22. package/components/admin/setup-wizard/BrandingStep.tsx +3 -3
  23. package/components/admin/setup-wizard/DatabaseStep.tsx +2 -2
  24. package/components/admin/setup-wizard/DoneStep.tsx +1 -1
  25. package/components/admin/setup-wizard/SetupWizard.tsx +4 -4
  26. package/components/admin/setup-wizard/StorageStep.tsx +2 -2
  27. package/components/admin/setup-wizard/WelcomeStep.tsx +2 -2
  28. package/components/admin/styles/ColorsEditor.tsx +2 -2
  29. package/components/admin/styles/FontsEditor.tsx +6 -6
  30. package/components/admin/styles/GridLayoutEditor.tsx +9 -9
  31. package/components/admin/styles/LinksButtonsEditor.tsx +5 -5
  32. package/components/admin/styles/TypographyEditor.tsx +6 -6
  33. package/components/admin/styles/shared.tsx +68 -68
  34. package/components/blocks/AudioBlockRenderer.tsx +286 -286
  35. package/components/blocks/MarqueeBlockRenderer.tsx +316 -0
  36. package/components/blocks/ProjectCarouselBlockRenderer.tsx +1 -1
  37. package/components/builder/BlockCardIcons.tsx +316 -316
  38. package/components/builder/BlockTypePicker.tsx +1 -1
  39. package/components/builder/BubbleIcons.tsx +90 -0
  40. package/components/builder/BuilderCanvas.tsx +2 -0
  41. package/components/builder/CanvasMinimap.tsx +2 -2
  42. package/components/builder/CoverSectionCanvas.tsx +363 -363
  43. package/components/builder/DeviceFrame.tsx +1 -1
  44. package/components/builder/DndWrapper.tsx +3 -3
  45. package/components/builder/InsertionLines.tsx +1 -1
  46. package/components/builder/SectionCardIcons.tsx +421 -320
  47. package/components/builder/SectionEditorBar.tsx +1 -1
  48. package/components/builder/SectionTypePicker.tsx +4 -4
  49. package/components/builder/SectionV2Canvas.tsx +1 -1
  50. package/components/builder/SectionV2Column.tsx +69 -67
  51. package/components/builder/SortableBlock.tsx +93 -73
  52. package/components/builder/SortableRow.tsx +27 -26
  53. package/components/builder/VirtualAssetGrid.tsx +2 -2
  54. package/components/builder/asset-browser/R2BrowserContent.tsx +11 -11
  55. package/components/builder/blockStyles.tsx +192 -185
  56. package/components/builder/color-picker/AlphaSlider.tsx +141 -141
  57. package/components/builder/color-picker/ColorInputs.tsx +105 -105
  58. package/components/builder/color-picker/EyedropperButton.tsx +74 -74
  59. package/components/builder/color-picker/HueSlider.tsx +124 -124
  60. package/components/builder/color-picker/SaturationCanvas.tsx +142 -142
  61. package/components/builder/color-picker/SwatchBar.tsx +93 -93
  62. package/components/builder/editors/AudioBlockEditor.tsx +242 -242
  63. package/components/builder/editors/BeforeAfterBlockEditor.tsx +360 -360
  64. package/components/builder/editors/ButtonBlockEditor.tsx +4 -4
  65. package/components/builder/editors/EnterAnimationPicker.tsx +2 -2
  66. package/components/builder/editors/HoverEffectPicker.tsx +2 -2
  67. package/components/builder/editors/ImageBlockEditor.tsx +2 -2
  68. package/components/builder/editors/ImageGridBlockEditor.tsx +4 -4
  69. package/components/builder/editors/MarqueeBlockEditor.tsx +621 -0
  70. package/components/builder/editors/ProjectCarouselBlockEditor.tsx +443 -443
  71. package/components/builder/editors/ProjectGridEditor.tsx +9 -9
  72. package/components/builder/editors/SpacerBlockEditor.tsx +5 -5
  73. package/components/builder/editors/StaggerSettings.tsx +109 -109
  74. package/components/builder/editors/TextBlockEditor.tsx +3 -3
  75. package/components/builder/editors/TextStylePicker.tsx +1 -1
  76. package/components/builder/editors/VideoBlockEditor.tsx +2 -2
  77. package/components/builder/editors/index.ts +11 -10
  78. package/components/builder/editors/shared.tsx +6 -6
  79. package/components/builder/live-preview/LiveAudioPreview.tsx +120 -120
  80. package/components/builder/live-preview/LiveBeforeAfterPreview.tsx +1 -1
  81. package/components/builder/live-preview/LiveImageGridPreview.tsx +10 -2
  82. package/components/builder/live-preview/LiveImagePreview.tsx +1 -1
  83. package/components/builder/live-preview/LiveMarqueePreview.tsx +39 -0
  84. package/components/builder/live-preview/LiveProjectCarouselPreview.tsx +1 -1
  85. package/components/builder/live-preview/LiveVideoPreview.tsx +1 -1
  86. package/components/builder/live-preview/ProjectCardWrapper.tsx +291 -291
  87. package/components/builder/settings-panel/AnimationTab.tsx +138 -138
  88. package/components/builder/settings-panel/BlockLayoutTab.tsx +7 -7
  89. package/components/builder/settings-panel/CardEntranceSection.tsx +114 -114
  90. package/components/builder/settings-panel/ColumnV2Settings.tsx +5 -5
  91. package/components/builder/settings-panel/CoverSectionLayoutTab.tsx +71 -71
  92. package/components/builder/settings-panel/CoverSectionSettings.tsx +335 -335
  93. package/components/builder/settings-panel/PageSettings.tsx +3 -3
  94. package/components/builder/settings-panel/ParallaxSlideSettings.tsx +2 -2
  95. package/components/builder/settings-panel/SectionV2AnimationTab.tsx +4 -4
  96. package/components/builder/settings-panel/SectionV2LayoutTab.tsx +356 -356
  97. package/components/builder/settings-panel/SectionV2Settings.tsx +14 -14
  98. package/components/builder/settings-panel/TRBLInputs.tsx +1 -1
  99. package/lib/animation/enter-types.ts +1 -0
  100. package/lib/animation/hover-effect-presets.ts +210 -210
  101. package/lib/animation/hover-effect-types.ts +1 -0
  102. package/lib/builder/block-registrations.ts +468 -417
  103. package/lib/builder/constants.ts +111 -111
  104. package/lib/builder/store-sections.ts +2 -2
  105. package/lib/builder/types-slices.ts +414 -414
  106. package/lib/builder/types.ts +4 -1
  107. package/lib/config/index.ts +27 -27
  108. package/lib/sanity/types.ts +98 -1
  109. package/lib/version.ts +1 -1
  110. package/package.json +1 -1
  111. package/sanity/schemas/blocks/audioBlock.ts +69 -69
  112. package/sanity/schemas/blocks/index.ts +12 -11
  113. package/sanity/schemas/blocks/marqueeBlock.ts +292 -0
  114. package/sanity/schemas/index.ts +120 -117
  115. package/styles/admin.css +85 -85
  116. package/styles/animations.css +237 -237
  117. package/styles/base.css +114 -114
@@ -1,316 +1,316 @@
1
- "use client";
2
-
3
- /**
4
- * Full-size block card icons (220×120) used in the Add Block modal.
5
- *
6
- * Visual language: soft grid background with a 24-rect brick overlay that
7
- * fades to #F4F4F4 on the right (matches the card's clean gray). 3D white
8
- * shapes with cool-blue bevel + vector drop shadow. Dashed blue (#4794E2)
9
- * construction guides on top.
10
- *
11
- * IDs are namespaced per icon (`tBlk`, `iBlk`, `igBlk`, `vBlk`, `sBlk`,
12
- * `bBlk`) so multiple cards can render side by side without filter /
13
- * gradient collisions.
14
- */
15
-
16
- import { Bg, BgDefs, ShadowFilter, VertBevel } from "./iconPrimitives";
17
-
18
- // ─────────────────────────────────────────────────────────────────────
19
- // Text
20
- // ─────────────────────────────────────────────────────────────────────
21
- export function TextBlockCardIcon() {
22
- return (
23
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 120" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
24
- <defs>
25
- <BgDefs prefix="tBlk" />
26
- <ShadowFilter id="shadTBlk" />
27
- <linearGradient id="bevelATBlk" x1="61.7" y1="19.7" x2="61.7" y2="99.7" gradientUnits="userSpaceOnUse">
28
- <stop offset="0" stopColor="#FFFFFF" />
29
- <stop offset="1" stopColor="#E6ECF6" />
30
- </linearGradient>
31
- <linearGradient id="bevelaTBlk" x1="125.3" y1="44.9" x2="125.2" y2="84.4" gradientUnits="userSpaceOnUse">
32
- <stop offset="0" stopColor="#FFFFFF" />
33
- <stop offset="1" stopColor="#E6ECF6" />
34
- </linearGradient>
35
- </defs>
36
- <Bg prefix="tBlk" />
37
-
38
- {/* Uppercase A — 3D body with shadow */}
39
- <g filter="url(#shadTBlk)">
40
- <path fillRule="evenodd" clipRule="evenodd" fill="url(#bevelATBlk)" stroke="#C9D3E4" strokeWidth="0.7"
41
- d="M93.5,97.8H74.3l-3.1-13.6H51.8l-3.2,13.6H29.8l21.5-81.2h20.6L93.5,97.8z M67.7,69.7c-2.7-12.1-4.9-23.6-6.2-34.4h-0.3c-1.5,11.2-3.5,22.7-6.2,34.4H67.7z" />
42
- </g>
43
- {/* A dashed accent */}
44
- <path fillRule="evenodd" clipRule="evenodd" fill="none" stroke="#4794E2" strokeWidth="2" strokeMiterlimit="10" strokeDasharray="3,3" opacity="0.69"
45
- d="M93.5,97.8H74.3l-3.1-13.6H51.8l-3.2,13.6H29.8l21.5-81.2h20.6L93.5,97.8z M67.7,69.7c-2.7-12.1-4.9-23.6-6.2-34.4h-0.3c-1.5,11.2-3.5,22.7-6.2,34.4H67.7z" />
46
-
47
- {/* Lowercase a — 3D body with shadow */}
48
- <g filter="url(#shadTBlk)">
49
- <path fill="url(#bevelaTBlk)" stroke="#C9D3E4" strokeWidth="0.7"
50
- d="M136.7,98l-0.7-6.2h-0.3c-2.8,3.9-8.1,7.4-15.1,7.4c-10,0-15.1-7.1-15.1-14.2c0-12,10.6-18.5,29.7-18.4v-1c0-4.1-1.1-11.4-11.2-11.4c-4.6,0-9.4,1.4-12.9,3.7l-2-5.9c4.1-2.7,10-4.4,16.3-4.4c15.1,0,18.8,10.3,18.8,20.2v18.5c0,4.3,0.2,8.5,0.8,11.9H136.7z M135.4,72.8c-9.8-0.2-21,1.5-21,11.1c0,5.8,3.9,8.6,8.5,8.6c6.4,0,10.5-4.1,12-8.3c0.3-0.9,0.5-1.9,0.5-2.9V72.8z" />
51
- </g>
52
- {/* a dashed accent (matches A) */}
53
- <path fill="none" stroke="#4794E2" strokeWidth="2" strokeMiterlimit="10" strokeDasharray="3,3" opacity="0.69"
54
- d="M136.7,98l-0.7-6.2h-0.3c-2.8,3.9-8.1,7.4-15.1,7.4c-10,0-15.1-7.1-15.1-14.2c0-12,10.6-18.5,29.7-18.4v-1c0-4.1-1.1-11.4-11.2-11.4c-4.6,0-9.4,1.4-12.9,3.7l-2-5.9c4.1-2.7,10-4.4,16.3-4.4c15.1,0,18.8,10.3,18.8,20.2v18.5c0,4.3,0.2,8.5,0.8,11.9H136.7z M135.4,72.8c-9.8-0.2-21,1.5-21,11.1c0,5.8,3.9,8.6,8.5,8.6c6.4,0,10.5-4.1,12-8.3c0.3-0.9,0.5-1.9,0.5-2.9V72.8z" />
55
-
56
- {/* Right-side vertical bracket */}
57
- <g fill="none" stroke="#4794E2" strokeWidth="2" strokeMiterlimit="10">
58
- <line x1="159.7" y1="18.5" x2="159.7" y2="101.4" />
59
- <line x1="153.4" y1="18.5" x2="166.1" y2="18.5" />
60
- <line x1="153.4" y1="101.4" x2="166.1" y2="101.4" />
61
- </g>
62
- </svg>
63
- );
64
- }
65
-
66
- // ─────────────────────────────────────────────────────────────────────
67
- // Image
68
- // ─────────────────────────────────────────────────────────────────────
69
- export function ImageBlockCardIcon() {
70
- return (
71
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 120" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
72
- <defs>
73
- <BgDefs prefix="iBlk" />
74
- <ShadowFilter id="shadIBlk" />
75
- <VertBevel id="bevelIBlk" />
76
- </defs>
77
- <Bg prefix="iBlk" />
78
-
79
- <g filter="url(#shadIBlk)">
80
- <path d="M26.8,19h112.7c1.3,0,2.3,1.2,2.3,2.7v75c0,1.5-1.1,2.7-2.3,2.7H26.8c-1.3-0.1-2.3-1.3-2.3-2.7V21.6C24.5,20.2,25.5,19,26.8,19z"
81
- fill="url(#bevelIBlk)" stroke="#C9D3E4" strokeWidth="0.7" />
82
- </g>
83
- <path d="M31.5,25.3h103.4c0.7,0,1.4,0.7,1.4,1.6v64.4c0,0.9-0.6,1.6-1.4,1.6H31.5c-0.7,0-1.4-0.7-1.4-1.6V26.9C30.1,25.9,30.7,25.3,31.5,25.3z"
84
- fill="#DDE6F5" stroke="#C9D3E4" strokeWidth="0.5" />
85
- <ellipse cx="116.3" cy="41.3" rx="5.1" ry="5.1" fill="#FFFFFF" stroke="#4794E2" strokeWidth="2" />
86
- <path d="M37.1,79.6l20.3-23c1.4-1.5,3.7-1.6,5.2-0.1l11.6,11.7c1.4,1.4,3.6,1.4,5,0L89.5,58c1.2-1.2,3.1-1.4,4.5-0.4l31,21.5c2.9,1.9,1.5,6.5-2,6.5H39.7C36.7,85.5,35.1,81.9,37.1,79.6z"
87
- fill="#FFFFFF" stroke="#4794E2" strokeWidth="2" strokeMiterlimit="10" />
88
- <path d="M26.8,19h112.7c1.3,0,2.3,1.2,2.3,2.7v75c0,1.5-1.1,2.7-2.3,2.7H26.8c-1.3-0.1-2.3-1.3-2.3-2.7V21.6C24.5,20.2,25.5,19,26.8,19z"
89
- fill="none" stroke="#4794E2" strokeWidth="2" strokeDasharray="3,3" />
90
- </svg>
91
- );
92
- }
93
-
94
- // ─────────────────────────────────────────────────────────────────────
95
- // Image Grid
96
- // ─────────────────────────────────────────────────────────────────────
97
- export function ImageGridBlockCardIcon() {
98
- return (
99
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 120" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
100
- <defs>
101
- <BgDefs prefix="igBlk" />
102
- <ShadowFilter id="shadIGBlk" />
103
- <VertBevel id="bevelIGBlk" />
104
- </defs>
105
- <Bg prefix="igBlk" />
106
-
107
- <g filter="url(#shadIGBlk)">
108
- <rect x="24" y="26" width="58" height="34" rx="2" fill="url(#bevelIGBlk)" stroke="#C9D3E4" strokeWidth="0.7" />
109
- <rect x="90" y="26" width="58" height="34" rx="2" fill="url(#bevelIGBlk)" stroke="#C9D3E4" strokeWidth="0.7" />
110
- <rect x="24" y="68" width="58" height="34" rx="2" fill="url(#bevelIGBlk)" stroke="#C9D3E4" strokeWidth="0.7" />
111
- <rect x="90" y="68" width="58" height="34" rx="2" fill="url(#bevelIGBlk)" stroke="#C9D3E4" strokeWidth="0.7" />
112
- </g>
113
- <rect x="30" y="32" width="46" height="22" rx="1.2" fill="#DDE6F5" />
114
- <rect x="96" y="32" width="46" height="22" rx="1.2" fill="#DDE6F5" />
115
- <rect x="30" y="74" width="46" height="22" rx="1.2" fill="#DDE6F5" />
116
- <rect x="96" y="74" width="46" height="22" rx="1.2" fill="#DDE6F5" />
117
- <g fill="none" stroke="#4794E2" strokeWidth="2" strokeDasharray="3,3">
118
- <rect x="24" y="26" width="58" height="34" rx="2" />
119
- <rect x="90" y="26" width="58" height="34" rx="2" />
120
- <rect x="24" y="68" width="58" height="34" rx="2" />
121
- <rect x="90" y="68" width="58" height="34" rx="2" />
122
- </g>
123
- </svg>
124
- );
125
- }
126
-
127
- // ─────────────────────────────────────────────────────────────────────
128
- // Video
129
- // ─────────────────────────────────────────────────────────────────────
130
- export function VideoBlockCardIcon() {
131
- return (
132
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 120" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
133
- <defs>
134
- <BgDefs prefix="vBlk" />
135
- <ShadowFilter id="shadVBlk" />
136
- <VertBevel id="bevelVBlk" />
137
- </defs>
138
- <Bg prefix="vBlk" />
139
-
140
- <g filter="url(#shadVBlk)">
141
- <path d="M26.8,19h112.7c1.3,0,2.3,1.2,2.3,2.7v75c0,1.5-1.1,2.7-2.3,2.7H26.8c-1.3-0.1-2.3-1.3-2.3-2.7V21.6C24.5,20.2,25.5,19,26.8,19z"
142
- fill="url(#bevelVBlk)" stroke="#C9D3E4" strokeWidth="0.7" />
143
- </g>
144
- <path d="M31.5,25.3h103.4c0.7,0,1.4,0.7,1.4,1.6v64.4c0,0.9-0.6,1.6-1.4,1.6H31.5c-0.7,0-1.4-0.7-1.4-1.6V26.9C30.1,25.9,30.7,25.3,31.5,25.3z"
145
- fill="#DDE6F5" stroke="#C9D3E4" strokeWidth="0.5" />
146
- <path d="M26.8,19h112.7c1.3,0,2.3,1.2,2.3,2.7v75c0,1.5-1.1,2.7-2.3,2.7H26.8c-1.3-0.1-2.3-1.3-2.3-2.7V21.6C24.5,20.2,25.5,19,26.8,19z"
147
- fill="none" stroke="#4794E2" strokeWidth="2" strokeDasharray="3,3" />
148
- <path d="M75.2,45.9l21.3,11.4c2.4,1.2,2.4,4.6,0,5.9L75.2,74.5c-2.3,1.2-4.9-0.5-4.9-2.9V48.8C70.3,46.3,73,44.6,75.2,45.9z"
149
- fill="#FFFFFF" stroke="#4794E2" strokeWidth="2" strokeMiterlimit="10" />
150
- </svg>
151
- );
152
- }
153
-
154
- // ─────────────────────────────────────────────────────────────────────
155
- // Spacer (edge case — horizontal gradient, no shadow)
156
- // ─────────────────────────────────────────────────────────────────────
157
- export function SpacerBlockCardIcon() {
158
- return (
159
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 120" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
160
- <defs>
161
- <BgDefs prefix="sBlk" />
162
- <linearGradient id="bevelSBlk" x1="15" y1="59" x2="144.7" y2="59" gradientUnits="userSpaceOnUse">
163
- <stop offset="0" stopColor="#FFFFFF" stopOpacity="0" />
164
- <stop offset="0.26" stopColor="#F2F5FA" />
165
- <stop offset="0.79" stopColor="#F2F5FA" />
166
- <stop offset="1" stopColor="#E6ECF6" stopOpacity="0" />
167
- </linearGradient>
168
- </defs>
169
- <Bg prefix="sBlk" />
170
-
171
- {/* Main frame — no shadow (edge case: horizontal gradient fill) */}
172
- <path d="M26.8,19h112.7c1.3,0,2.3,1.2,2.3,2.7v75c0,1.5-1.1,2.7-2.3,2.7H26.8c-1.3-0.1-2.3-1.3-2.3-2.7V21.6C24.5,20.2,25.5,19,26.8,19z"
173
- fill="url(#bevelSBlk)" />
174
-
175
- {/* Blue up/down arrows */}
176
- <g fill="#4794E2">
177
- <path d="M82.7,27v18.8h2V27l2,1.9c0.3,0.3,0.9,0.3,1.2,0l0.2-0.2c0.3-0.3,0.3-0.9,0-1.2l-3.7-3.6c-0.4-0.4-1-0.4-1.4,0l-3.7,3.6c-0.3,0.3-0.3,0.9,0,1.2l0.2,0.2c0.3,0.3,0.9,0.3,1.2,0L82.7,27z" />
178
- <path d="M86.7,89.7l-2,2v-18c0-0.5-0.4-0.8-0.8-0.8h-0.3c-0.5,0-0.8,0.4-0.8,0.8v18l-2-2c-0.3-0.3-0.9-0.3-1.2,0l-0.2,0.2c-0.3,0.3-0.3,0.9,0,1.2l3.7,3.7c0.2,0.2,0.4,0.3,0.7,0.3s0.5-0.1,0.7-0.3l3.7-3.7c0.3-0.3,0.3-0.9,0-1.2l-0.2-0.2C87.5,89.3,87,89.3,86.7,89.7z" />
179
- </g>
180
-
181
- {/* Dashed blue boundary lines */}
182
- <line x1="22.1" y1="20.9" x2="146.5" y2="20.9" fill="none" stroke="#4794E2" strokeWidth="2" strokeDasharray="3,3" />
183
- <line x1="22.1" y1="99.2" x2="146.5" y2="99.2" fill="none" stroke="#4794E2" strokeWidth="2" strokeDasharray="3,3" />
184
- </svg>
185
- );
186
- }
187
-
188
- // ─────────────────────────────────────────────────────────────────────
189
- // Button
190
- // ─────────────────────────────────────────────────────────────────────
191
- export function ButtonBlockCardIcon() {
192
- return (
193
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 120" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
194
- <defs>
195
- <BgDefs prefix="bBlk" />
196
- <ShadowFilter id="shadBBlk" />
197
- <VertBevel id="bevelBBlk" />
198
- </defs>
199
- <Bg prefix="bBlk" />
200
-
201
- <g filter="url(#shadBBlk)">
202
- <path d="M43,39h83.3c12.7,0,22.9,9.2,22.9,20.7l0,0c0,11.5-10.2,20.7-22.9,20.7H43c-12.7,0-22.9-9.2-22.9-20.7l0,0C20.1,48.3,30.4,39,43,39z"
203
- fill="url(#bevelBBlk)" stroke="#C9D3E4" strokeWidth="0.7" />
204
- </g>
205
- <path d="M43,39h83.3c12.7,0,22.9,9.2,22.9,20.7l0,0c0,11.5-10.2,20.7-22.9,20.7H43c-12.7,0-22.9-9.2-22.9-20.7l0,0C20.1,48.3,30.4,39,43,39z"
206
- fill="none" stroke="#4794E2" strokeWidth="2" strokeDasharray="3,3" />
207
-
208
- {/* Cursor icon */}
209
- <g transform="translate(-240 -432)">
210
- <path fillRule="evenodd" clipRule="evenodd" fill="#FFFFFF" stroke="#4794E2" strokeWidth="2" strokeMiterlimit="10"
211
- d="M353.1,513.5l8.2,8.2c0.9,0.9,2.5,0.9,3.4,0c0.9-0.9,2.3-2.3,3.1-3.1c0.5-0.5,0.7-1.1,0.7-1.7c0-0.6-0.3-1.3-0.7-1.7l-8.2-8.2l5.6-3.8c0.8-0.5,1.2-1.4,1-2.3c-0.1-0.9-0.8-1.7-1.6-2l-24.8-8.2c-0.9-0.3-1.8-0.1-2.5,0.6c-0.6,0.6-0.9,1.6-0.6,2.5l8.2,24.8c0.3,0.9,1.1,1.5,2,1.6c0.9,0.1,1.8-0.3,2.3-1L353.1,513.5z" />
212
- </g>
213
- </svg>
214
- );
215
- }
216
-
217
- // ─────────────────────────────────────────────────────────────────────
218
- // Before / After
219
- // ─────────────────────────────────────────────────────────────────────
220
- export function BeforeAfterBlockCardIcon() {
221
- return (
222
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 120" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
223
- <defs>
224
- <BgDefs prefix="baBlk" />
225
- <ShadowFilter id="shadBABlk" />
226
- <VertBevel id="bevelBABlk" />
227
- </defs>
228
- <Bg prefix="baBlk" />
229
-
230
- {/* 3D frame body with vertical bevel + shadow */}
231
- <g filter="url(#shadBABlk)">
232
- <path d="M26.8,19h112.7c1.3,0,2.3,1.2,2.3,2.7v75c0,1.5-1.1,2.7-2.3,2.7H26.8c-1.3-0.1-2.3-1.3-2.3-2.7V21.6C24.5,20.2,25.5,19,26.8,19z"
233
- fill="url(#bevelBABlk)" stroke="#C9D3E4" strokeWidth="0.7" />
234
- </g>
235
-
236
- {/* Inner image-block background (right side — "after") */}
237
- <path d="M31.5,25.3h103.4c0.7,0,1.4,0.7,1.4,1.6v64.4c0,0.9-0.6,1.6-1.4,1.6H31.5c-0.7,0-1.4-0.7-1.4-1.6V26.9C30.1,25.9,30.7,25.3,31.5,25.3z"
238
- fill="#DDE6F5" stroke="#C9D3E4" strokeWidth="0.5" />
239
-
240
- {/* Sun + mountain silhouette (composes the "after" image) */}
241
- <ellipse cx="116.3" cy="41.3" rx="5.1" ry="5.1" fill="#FFFFFF" stroke="#4794E2" strokeWidth="2" />
242
- <path d="M37.1,79.6l20.3-23c1.4-1.5,3.7-1.6,5.2-0.1l11.6,11.7c1.4,1.4,3.6,1.4,5,0L89.5,58c1.2-1.2,3.1-1.4,4.5-0.4l31,21.5c2.9,1.9,1.5,6.5-2,6.5H39.7C36.7,85.5,35.1,81.9,37.1,79.6z"
243
- fill="#FFFFFF" stroke="#4794E2" strokeWidth="2" strokeMiterlimit="10" />
244
-
245
- {/* Dashed frame outline */}
246
- <path d="M26.8,19h112.7c1.3,0,2.3,1.2,2.3,2.7v75c0,1.5-1.1,2.7-2.3,2.7H26.8c-1.3-0.1-2.3-1.3-2.3-2.7V21.6C24.5,20.2,25.5,19,26.8,19z"
247
- fill="none" stroke="#4794E2" strokeWidth="2" strokeDasharray="3,3" />
248
-
249
- {/* "Before" half — gray panel clipped by the diagonal slider */}
250
- <path d="M101.6,25.3H31.5c-0.8,0-1.4,0.6-1.4,1.6v64.4c0,0.9,0.7,1.6,1.4,1.6h30.4L101.6,25.3z"
251
- fill="#E0E0E0" stroke="#D8D8D8" strokeWidth="0.5" />
252
-
253
- {/* Before-side mountain silhouette */}
254
- <path d="M75.9,69.1c-0.6-0.2-1.2-0.5-1.7-0.9L62.6,56.5c-1.5-1.5-3.8-1.4-5.2,0.1l-20.3,23c-2,2.3-0.4,5.9,2.6,6h26.5L75.9,69.1z"
255
- fill="#FFFFFF" stroke="#B2B2B2" strokeWidth="2" strokeMiterlimit="10" />
256
-
257
- {/* Diagonal slider line */}
258
- <line x1="111" y1="8.4" x2="51.6" y2="110.1" stroke="#4794E2" strokeWidth="3" strokeLinecap="round" strokeMiterlimit="10" fill="none" />
259
- </svg>
260
- );
261
- }
262
-
263
- // ─────────────────────────────────────────────────────────────────────
264
- // Audio
265
- // ─────────────────────────────────────────────────────────────────────
266
- export function AudioBlockCardIcon() {
267
- return (
268
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 120" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
269
- <defs>
270
- <BgDefs prefix="aBlk" />
271
- <ShadowFilter id="shadABlk" />
272
- <VertBevel id="bevelABlk" />
273
- </defs>
274
- <Bg prefix="aBlk" />
275
-
276
- {/* Pill-shaped frame body with vertical bevel + shadow */}
277
- <g filter="url(#shadABlk)">
278
- <path d="M120.1,84.3H46.9c-14.2,0-25.6-11.5-25.6-25.6v0c0-14.2,11.5-25.6,25.6-25.6h73.2c14.2,0,25.6,11.5,25.6,25.6v0C145.7,72.8,134.2,84.3,120.1,84.3z"
279
- fill="url(#bevelABlk)" stroke="#C9D3E4" strokeWidth="0.7" />
280
- </g>
281
-
282
- {/* Inner pill panel */}
283
- <path d="M120.3,79.3H46.6C35.2,79.3,26,70.1,26,58.7v0c0-11.4,9.2-20.6,20.6-20.6h73.6c11.4,0,20.6,9.2,20.6,20.6v0C140.8,70.1,131.6,79.3,120.3,79.3z"
284
- fill="#DDE6F5" stroke="#C9D3E4" strokeWidth="0.5" />
285
-
286
- {/* Waveform bars — positions from block_audio.svg mockup (tall, short, short, tall, short) */}
287
- <path d="M73.9,43.1c-1.1,0-1.9,0.9-1.9,1.9v27.2c0,1.1,0.9,1.9,1.9,1.9c1.1,0,1.9-0.9,1.9-1.9V45.1C75.8,44,74.9,43.1,73.9,43.1z" fill="#4794E2" />
288
- <path d="M86.9,49.2c-1.1,0-1.9,0.9-1.9,1.9v15.2c0,1.1,0.9,1.9,1.9,1.9c1.1,0,1.9-0.9,1.9-1.9V51.1C88.9,50,88,49.2,86.9,49.2z" fill="#4794E2" />
289
- <path d="M98.3,49.2c-1.1,0-1.9,0.9-1.9,1.9v15.2c0,1.1,0.9,1.9,1.9,1.9c1.1,0,1.9-0.9,1.9-1.9V51.1C100.2,50,99.3,49.2,98.3,49.2z" fill="#4794E2" />
290
- <path d="M109.5,43.1c-1.1,0-1.9,0.9-1.9,1.9v27.2c0,1.1,0.9,1.9,1.9,1.9c1.1,0,1.9-0.9,1.9-1.9V45.1C111.4,44,110.5,43.1,109.5,43.1z" fill="#4794E2" />
291
- <path d="M121.1,49.2c-1.1,0-1.9,0.9-1.9,1.9v15.2c0,1.1,0.9,1.9,1.9,1.9c1.1,0,1.9-0.9,1.9-1.9V51.1C123,50,122.2,49.2,121.1,49.2z" fill="#4794E2" />
292
-
293
- {/* Play button — rounded triangle */}
294
- <path d="M42.3,59.6v-7.7c0-1.7,1.9-2.8,3.4-2l6.7,3.8l6.7,3.8c1.5,0.9,1.5,3.1,0,3.9l-6.7,3.8l-6.7,3.8c-1.5,0.9-3.4-0.2-3.4-2V59.6z"
295
- fill="#4794E2" />
296
-
297
- {/* Dashed frame outline — matches the pill frame */}
298
- <path d="M120.1,84.3H46.9c-14.2,0-25.6-11.5-25.6-25.6v0c0-14.2,11.5-25.6,25.6-25.6h73.2c14.2,0,25.6,11.5,25.6,25.6v0C145.7,72.8,134.2,84.3,120.1,84.3z"
299
- fill="none" stroke="#4794E2" strokeWidth="2" strokeDasharray="3,3" />
300
- </svg>
301
- );
302
- }
303
-
304
- // ─────────────────────────────────────────────────────────────────────
305
- // Lookup map
306
- // ─────────────────────────────────────────────────────────────────────
307
- export const BLOCK_CARD_ICONS: Record<string, React.FC> = {
308
- textBlock: TextBlockCardIcon,
309
- imageBlock: ImageBlockCardIcon,
310
- imageGridBlock: ImageGridBlockCardIcon,
311
- videoBlock: VideoBlockCardIcon,
312
- spacerBlock: SpacerBlockCardIcon,
313
- buttonBlock: ButtonBlockCardIcon,
314
- beforeAfterBlock: BeforeAfterBlockCardIcon,
315
- audioBlock: AudioBlockCardIcon,
316
- };
1
+ "use client";
2
+
3
+ /**
4
+ * Full-size block card icons (220×120) used in the Add Block modal.
5
+ *
6
+ * Visual language: soft grid background with a 24-rect brick overlay that
7
+ * fades to #F4F4F4 on the right (matches the card's clean gray). 3D white
8
+ * shapes with cool-blue bevel + vector drop shadow. Dashed blue (#3580f9)
9
+ * construction guides on top.
10
+ *
11
+ * IDs are namespaced per icon (`tBlk`, `iBlk`, `igBlk`, `vBlk`, `sBlk`,
12
+ * `bBlk`) so multiple cards can render side by side without filter /
13
+ * gradient collisions.
14
+ */
15
+
16
+ import { Bg, BgDefs, ShadowFilter, VertBevel } from "./iconPrimitives";
17
+
18
+ // ─────────────────────────────────────────────────────────────────────
19
+ // Text
20
+ // ─────────────────────────────────────────────────────────────────────
21
+ export function TextBlockCardIcon() {
22
+ return (
23
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 120" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
24
+ <defs>
25
+ <BgDefs prefix="tBlk" />
26
+ <ShadowFilter id="shadTBlk" />
27
+ <linearGradient id="bevelATBlk" x1="61.7" y1="19.7" x2="61.7" y2="99.7" gradientUnits="userSpaceOnUse">
28
+ <stop offset="0" stopColor="#FFFFFF" />
29
+ <stop offset="1" stopColor="#E6ECF6" />
30
+ </linearGradient>
31
+ <linearGradient id="bevelaTBlk" x1="125.3" y1="44.9" x2="125.2" y2="84.4" gradientUnits="userSpaceOnUse">
32
+ <stop offset="0" stopColor="#FFFFFF" />
33
+ <stop offset="1" stopColor="#E6ECF6" />
34
+ </linearGradient>
35
+ </defs>
36
+ <Bg prefix="tBlk" />
37
+
38
+ {/* Uppercase A — 3D body with shadow */}
39
+ <g filter="url(#shadTBlk)">
40
+ <path fillRule="evenodd" clipRule="evenodd" fill="url(#bevelATBlk)" stroke="#C9D3E4" strokeWidth="0.7"
41
+ d="M93.5,97.8H74.3l-3.1-13.6H51.8l-3.2,13.6H29.8l21.5-81.2h20.6L93.5,97.8z M67.7,69.7c-2.7-12.1-4.9-23.6-6.2-34.4h-0.3c-1.5,11.2-3.5,22.7-6.2,34.4H67.7z" />
42
+ </g>
43
+ {/* A dashed accent */}
44
+ <path fillRule="evenodd" clipRule="evenodd" fill="none" stroke="#3580f9" strokeWidth="2" strokeMiterlimit="10" strokeDasharray="3,3" opacity="0.69"
45
+ d="M93.5,97.8H74.3l-3.1-13.6H51.8l-3.2,13.6H29.8l21.5-81.2h20.6L93.5,97.8z M67.7,69.7c-2.7-12.1-4.9-23.6-6.2-34.4h-0.3c-1.5,11.2-3.5,22.7-6.2,34.4H67.7z" />
46
+
47
+ {/* Lowercase a — 3D body with shadow */}
48
+ <g filter="url(#shadTBlk)">
49
+ <path fill="url(#bevelaTBlk)" stroke="#C9D3E4" strokeWidth="0.7"
50
+ d="M136.7,98l-0.7-6.2h-0.3c-2.8,3.9-8.1,7.4-15.1,7.4c-10,0-15.1-7.1-15.1-14.2c0-12,10.6-18.5,29.7-18.4v-1c0-4.1-1.1-11.4-11.2-11.4c-4.6,0-9.4,1.4-12.9,3.7l-2-5.9c4.1-2.7,10-4.4,16.3-4.4c15.1,0,18.8,10.3,18.8,20.2v18.5c0,4.3,0.2,8.5,0.8,11.9H136.7z M135.4,72.8c-9.8-0.2-21,1.5-21,11.1c0,5.8,3.9,8.6,8.5,8.6c6.4,0,10.5-4.1,12-8.3c0.3-0.9,0.5-1.9,0.5-2.9V72.8z" />
51
+ </g>
52
+ {/* a dashed accent (matches A) */}
53
+ <path fill="none" stroke="#3580f9" strokeWidth="2" strokeMiterlimit="10" strokeDasharray="3,3" opacity="0.69"
54
+ d="M136.7,98l-0.7-6.2h-0.3c-2.8,3.9-8.1,7.4-15.1,7.4c-10,0-15.1-7.1-15.1-14.2c0-12,10.6-18.5,29.7-18.4v-1c0-4.1-1.1-11.4-11.2-11.4c-4.6,0-9.4,1.4-12.9,3.7l-2-5.9c4.1-2.7,10-4.4,16.3-4.4c15.1,0,18.8,10.3,18.8,20.2v18.5c0,4.3,0.2,8.5,0.8,11.9H136.7z M135.4,72.8c-9.8-0.2-21,1.5-21,11.1c0,5.8,3.9,8.6,8.5,8.6c6.4,0,10.5-4.1,12-8.3c0.3-0.9,0.5-1.9,0.5-2.9V72.8z" />
55
+
56
+ {/* Right-side vertical bracket */}
57
+ <g fill="none" stroke="#3580f9" strokeWidth="2" strokeMiterlimit="10">
58
+ <line x1="159.7" y1="18.5" x2="159.7" y2="101.4" />
59
+ <line x1="153.4" y1="18.5" x2="166.1" y2="18.5" />
60
+ <line x1="153.4" y1="101.4" x2="166.1" y2="101.4" />
61
+ </g>
62
+ </svg>
63
+ );
64
+ }
65
+
66
+ // ─────────────────────────────────────────────────────────────────────
67
+ // Image
68
+ // ─────────────────────────────────────────────────────────────────────
69
+ export function ImageBlockCardIcon() {
70
+ return (
71
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 120" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
72
+ <defs>
73
+ <BgDefs prefix="iBlk" />
74
+ <ShadowFilter id="shadIBlk" />
75
+ <VertBevel id="bevelIBlk" />
76
+ </defs>
77
+ <Bg prefix="iBlk" />
78
+
79
+ <g filter="url(#shadIBlk)">
80
+ <path d="M26.8,19h112.7c1.3,0,2.3,1.2,2.3,2.7v75c0,1.5-1.1,2.7-2.3,2.7H26.8c-1.3-0.1-2.3-1.3-2.3-2.7V21.6C24.5,20.2,25.5,19,26.8,19z"
81
+ fill="url(#bevelIBlk)" stroke="#C9D3E4" strokeWidth="0.7" />
82
+ </g>
83
+ <path d="M31.5,25.3h103.4c0.7,0,1.4,0.7,1.4,1.6v64.4c0,0.9-0.6,1.6-1.4,1.6H31.5c-0.7,0-1.4-0.7-1.4-1.6V26.9C30.1,25.9,30.7,25.3,31.5,25.3z"
84
+ fill="#DDE6F5" stroke="#C9D3E4" strokeWidth="0.5" />
85
+ <ellipse cx="116.3" cy="41.3" rx="5.1" ry="5.1" fill="#FFFFFF" stroke="#3580f9" strokeWidth="2" />
86
+ <path d="M37.1,79.6l20.3-23c1.4-1.5,3.7-1.6,5.2-0.1l11.6,11.7c1.4,1.4,3.6,1.4,5,0L89.5,58c1.2-1.2,3.1-1.4,4.5-0.4l31,21.5c2.9,1.9,1.5,6.5-2,6.5H39.7C36.7,85.5,35.1,81.9,37.1,79.6z"
87
+ fill="#FFFFFF" stroke="#3580f9" strokeWidth="2" strokeMiterlimit="10" />
88
+ <path d="M26.8,19h112.7c1.3,0,2.3,1.2,2.3,2.7v75c0,1.5-1.1,2.7-2.3,2.7H26.8c-1.3-0.1-2.3-1.3-2.3-2.7V21.6C24.5,20.2,25.5,19,26.8,19z"
89
+ fill="none" stroke="#3580f9" strokeWidth="2" strokeDasharray="3,3" />
90
+ </svg>
91
+ );
92
+ }
93
+
94
+ // ─────────────────────────────────────────────────────────────────────
95
+ // Image Grid
96
+ // ─────────────────────────────────────────────────────────────────────
97
+ export function ImageGridBlockCardIcon() {
98
+ return (
99
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 120" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
100
+ <defs>
101
+ <BgDefs prefix="igBlk" />
102
+ <ShadowFilter id="shadIGBlk" />
103
+ <VertBevel id="bevelIGBlk" />
104
+ </defs>
105
+ <Bg prefix="igBlk" />
106
+
107
+ <g filter="url(#shadIGBlk)">
108
+ <rect x="24" y="26" width="58" height="34" rx="2" fill="url(#bevelIGBlk)" stroke="#C9D3E4" strokeWidth="0.7" />
109
+ <rect x="90" y="26" width="58" height="34" rx="2" fill="url(#bevelIGBlk)" stroke="#C9D3E4" strokeWidth="0.7" />
110
+ <rect x="24" y="68" width="58" height="34" rx="2" fill="url(#bevelIGBlk)" stroke="#C9D3E4" strokeWidth="0.7" />
111
+ <rect x="90" y="68" width="58" height="34" rx="2" fill="url(#bevelIGBlk)" stroke="#C9D3E4" strokeWidth="0.7" />
112
+ </g>
113
+ <rect x="30" y="32" width="46" height="22" rx="1.2" fill="#DDE6F5" />
114
+ <rect x="96" y="32" width="46" height="22" rx="1.2" fill="#DDE6F5" />
115
+ <rect x="30" y="74" width="46" height="22" rx="1.2" fill="#DDE6F5" />
116
+ <rect x="96" y="74" width="46" height="22" rx="1.2" fill="#DDE6F5" />
117
+ <g fill="none" stroke="#3580f9" strokeWidth="2" strokeDasharray="3,3">
118
+ <rect x="24" y="26" width="58" height="34" rx="2" />
119
+ <rect x="90" y="26" width="58" height="34" rx="2" />
120
+ <rect x="24" y="68" width="58" height="34" rx="2" />
121
+ <rect x="90" y="68" width="58" height="34" rx="2" />
122
+ </g>
123
+ </svg>
124
+ );
125
+ }
126
+
127
+ // ─────────────────────────────────────────────────────────────────────
128
+ // Video
129
+ // ─────────────────────────────────────────────────────────────────────
130
+ export function VideoBlockCardIcon() {
131
+ return (
132
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 120" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
133
+ <defs>
134
+ <BgDefs prefix="vBlk" />
135
+ <ShadowFilter id="shadVBlk" />
136
+ <VertBevel id="bevelVBlk" />
137
+ </defs>
138
+ <Bg prefix="vBlk" />
139
+
140
+ <g filter="url(#shadVBlk)">
141
+ <path d="M26.8,19h112.7c1.3,0,2.3,1.2,2.3,2.7v75c0,1.5-1.1,2.7-2.3,2.7H26.8c-1.3-0.1-2.3-1.3-2.3-2.7V21.6C24.5,20.2,25.5,19,26.8,19z"
142
+ fill="url(#bevelVBlk)" stroke="#C9D3E4" strokeWidth="0.7" />
143
+ </g>
144
+ <path d="M31.5,25.3h103.4c0.7,0,1.4,0.7,1.4,1.6v64.4c0,0.9-0.6,1.6-1.4,1.6H31.5c-0.7,0-1.4-0.7-1.4-1.6V26.9C30.1,25.9,30.7,25.3,31.5,25.3z"
145
+ fill="#DDE6F5" stroke="#C9D3E4" strokeWidth="0.5" />
146
+ <path d="M26.8,19h112.7c1.3,0,2.3,1.2,2.3,2.7v75c0,1.5-1.1,2.7-2.3,2.7H26.8c-1.3-0.1-2.3-1.3-2.3-2.7V21.6C24.5,20.2,25.5,19,26.8,19z"
147
+ fill="none" stroke="#3580f9" strokeWidth="2" strokeDasharray="3,3" />
148
+ <path d="M75.2,45.9l21.3,11.4c2.4,1.2,2.4,4.6,0,5.9L75.2,74.5c-2.3,1.2-4.9-0.5-4.9-2.9V48.8C70.3,46.3,73,44.6,75.2,45.9z"
149
+ fill="#FFFFFF" stroke="#3580f9" strokeWidth="2" strokeMiterlimit="10" />
150
+ </svg>
151
+ );
152
+ }
153
+
154
+ // ─────────────────────────────────────────────────────────────────────
155
+ // Spacer (edge case — horizontal gradient, no shadow)
156
+ // ─────────────────────────────────────────────────────────────────────
157
+ export function SpacerBlockCardIcon() {
158
+ return (
159
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 120" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
160
+ <defs>
161
+ <BgDefs prefix="sBlk" />
162
+ <linearGradient id="bevelSBlk" x1="15" y1="59" x2="144.7" y2="59" gradientUnits="userSpaceOnUse">
163
+ <stop offset="0" stopColor="#FFFFFF" stopOpacity="0" />
164
+ <stop offset="0.26" stopColor="#F2F5FA" />
165
+ <stop offset="0.79" stopColor="#F2F5FA" />
166
+ <stop offset="1" stopColor="#E6ECF6" stopOpacity="0" />
167
+ </linearGradient>
168
+ </defs>
169
+ <Bg prefix="sBlk" />
170
+
171
+ {/* Main frame — no shadow (edge case: horizontal gradient fill) */}
172
+ <path d="M26.8,19h112.7c1.3,0,2.3,1.2,2.3,2.7v75c0,1.5-1.1,2.7-2.3,2.7H26.8c-1.3-0.1-2.3-1.3-2.3-2.7V21.6C24.5,20.2,25.5,19,26.8,19z"
173
+ fill="url(#bevelSBlk)" />
174
+
175
+ {/* Blue up/down arrows */}
176
+ <g fill="#3580f9">
177
+ <path d="M82.7,27v18.8h2V27l2,1.9c0.3,0.3,0.9,0.3,1.2,0l0.2-0.2c0.3-0.3,0.3-0.9,0-1.2l-3.7-3.6c-0.4-0.4-1-0.4-1.4,0l-3.7,3.6c-0.3,0.3-0.3,0.9,0,1.2l0.2,0.2c0.3,0.3,0.9,0.3,1.2,0L82.7,27z" />
178
+ <path d="M86.7,89.7l-2,2v-18c0-0.5-0.4-0.8-0.8-0.8h-0.3c-0.5,0-0.8,0.4-0.8,0.8v18l-2-2c-0.3-0.3-0.9-0.3-1.2,0l-0.2,0.2c-0.3,0.3-0.3,0.9,0,1.2l3.7,3.7c0.2,0.2,0.4,0.3,0.7,0.3s0.5-0.1,0.7-0.3l3.7-3.7c0.3-0.3,0.3-0.9,0-1.2l-0.2-0.2C87.5,89.3,87,89.3,86.7,89.7z" />
179
+ </g>
180
+
181
+ {/* Dashed blue boundary lines */}
182
+ <line x1="22.1" y1="20.9" x2="146.5" y2="20.9" fill="none" stroke="#3580f9" strokeWidth="2" strokeDasharray="3,3" />
183
+ <line x1="22.1" y1="99.2" x2="146.5" y2="99.2" fill="none" stroke="#3580f9" strokeWidth="2" strokeDasharray="3,3" />
184
+ </svg>
185
+ );
186
+ }
187
+
188
+ // ─────────────────────────────────────────────────────────────────────
189
+ // Button
190
+ // ─────────────────────────────────────────────────────────────────────
191
+ export function ButtonBlockCardIcon() {
192
+ return (
193
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 120" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
194
+ <defs>
195
+ <BgDefs prefix="bBlk" />
196
+ <ShadowFilter id="shadBBlk" />
197
+ <VertBevel id="bevelBBlk" />
198
+ </defs>
199
+ <Bg prefix="bBlk" />
200
+
201
+ <g filter="url(#shadBBlk)">
202
+ <path d="M43,39h83.3c12.7,0,22.9,9.2,22.9,20.7l0,0c0,11.5-10.2,20.7-22.9,20.7H43c-12.7,0-22.9-9.2-22.9-20.7l0,0C20.1,48.3,30.4,39,43,39z"
203
+ fill="url(#bevelBBlk)" stroke="#C9D3E4" strokeWidth="0.7" />
204
+ </g>
205
+ <path d="M43,39h83.3c12.7,0,22.9,9.2,22.9,20.7l0,0c0,11.5-10.2,20.7-22.9,20.7H43c-12.7,0-22.9-9.2-22.9-20.7l0,0C20.1,48.3,30.4,39,43,39z"
206
+ fill="none" stroke="#3580f9" strokeWidth="2" strokeDasharray="3,3" />
207
+
208
+ {/* Cursor icon */}
209
+ <g transform="translate(-240 -432)">
210
+ <path fillRule="evenodd" clipRule="evenodd" fill="#FFFFFF" stroke="#3580f9" strokeWidth="2" strokeMiterlimit="10"
211
+ d="M353.1,513.5l8.2,8.2c0.9,0.9,2.5,0.9,3.4,0c0.9-0.9,2.3-2.3,3.1-3.1c0.5-0.5,0.7-1.1,0.7-1.7c0-0.6-0.3-1.3-0.7-1.7l-8.2-8.2l5.6-3.8c0.8-0.5,1.2-1.4,1-2.3c-0.1-0.9-0.8-1.7-1.6-2l-24.8-8.2c-0.9-0.3-1.8-0.1-2.5,0.6c-0.6,0.6-0.9,1.6-0.6,2.5l8.2,24.8c0.3,0.9,1.1,1.5,2,1.6c0.9,0.1,1.8-0.3,2.3-1L353.1,513.5z" />
212
+ </g>
213
+ </svg>
214
+ );
215
+ }
216
+
217
+ // ─────────────────────────────────────────────────────────────────────
218
+ // Before / After
219
+ // ─────────────────────────────────────────────────────────────────────
220
+ export function BeforeAfterBlockCardIcon() {
221
+ return (
222
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 120" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
223
+ <defs>
224
+ <BgDefs prefix="baBlk" />
225
+ <ShadowFilter id="shadBABlk" />
226
+ <VertBevel id="bevelBABlk" />
227
+ </defs>
228
+ <Bg prefix="baBlk" />
229
+
230
+ {/* 3D frame body with vertical bevel + shadow */}
231
+ <g filter="url(#shadBABlk)">
232
+ <path d="M26.8,19h112.7c1.3,0,2.3,1.2,2.3,2.7v75c0,1.5-1.1,2.7-2.3,2.7H26.8c-1.3-0.1-2.3-1.3-2.3-2.7V21.6C24.5,20.2,25.5,19,26.8,19z"
233
+ fill="url(#bevelBABlk)" stroke="#C9D3E4" strokeWidth="0.7" />
234
+ </g>
235
+
236
+ {/* Inner image-block background (right side — "after") */}
237
+ <path d="M31.5,25.3h103.4c0.7,0,1.4,0.7,1.4,1.6v64.4c0,0.9-0.6,1.6-1.4,1.6H31.5c-0.7,0-1.4-0.7-1.4-1.6V26.9C30.1,25.9,30.7,25.3,31.5,25.3z"
238
+ fill="#DDE6F5" stroke="#C9D3E4" strokeWidth="0.5" />
239
+
240
+ {/* Sun + mountain silhouette (composes the "after" image) */}
241
+ <ellipse cx="116.3" cy="41.3" rx="5.1" ry="5.1" fill="#FFFFFF" stroke="#3580f9" strokeWidth="2" />
242
+ <path d="M37.1,79.6l20.3-23c1.4-1.5,3.7-1.6,5.2-0.1l11.6,11.7c1.4,1.4,3.6,1.4,5,0L89.5,58c1.2-1.2,3.1-1.4,4.5-0.4l31,21.5c2.9,1.9,1.5,6.5-2,6.5H39.7C36.7,85.5,35.1,81.9,37.1,79.6z"
243
+ fill="#FFFFFF" stroke="#3580f9" strokeWidth="2" strokeMiterlimit="10" />
244
+
245
+ {/* Dashed frame outline */}
246
+ <path d="M26.8,19h112.7c1.3,0,2.3,1.2,2.3,2.7v75c0,1.5-1.1,2.7-2.3,2.7H26.8c-1.3-0.1-2.3-1.3-2.3-2.7V21.6C24.5,20.2,25.5,19,26.8,19z"
247
+ fill="none" stroke="#3580f9" strokeWidth="2" strokeDasharray="3,3" />
248
+
249
+ {/* "Before" half — gray panel clipped by the diagonal slider */}
250
+ <path d="M101.6,25.3H31.5c-0.8,0-1.4,0.6-1.4,1.6v64.4c0,0.9,0.7,1.6,1.4,1.6h30.4L101.6,25.3z"
251
+ fill="#E0E0E0" stroke="#D8D8D8" strokeWidth="0.5" />
252
+
253
+ {/* Before-side mountain silhouette */}
254
+ <path d="M75.9,69.1c-0.6-0.2-1.2-0.5-1.7-0.9L62.6,56.5c-1.5-1.5-3.8-1.4-5.2,0.1l-20.3,23c-2,2.3-0.4,5.9,2.6,6h26.5L75.9,69.1z"
255
+ fill="#FFFFFF" stroke="#B2B2B2" strokeWidth="2" strokeMiterlimit="10" />
256
+
257
+ {/* Diagonal slider line */}
258
+ <line x1="111" y1="8.4" x2="51.6" y2="110.1" stroke="#3580f9" strokeWidth="3" strokeLinecap="round" strokeMiterlimit="10" fill="none" />
259
+ </svg>
260
+ );
261
+ }
262
+
263
+ // ─────────────────────────────────────────────────────────────────────
264
+ // Audio
265
+ // ─────────────────────────────────────────────────────────────────────
266
+ export function AudioBlockCardIcon() {
267
+ return (
268
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 120" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
269
+ <defs>
270
+ <BgDefs prefix="aBlk" />
271
+ <ShadowFilter id="shadABlk" />
272
+ <VertBevel id="bevelABlk" />
273
+ </defs>
274
+ <Bg prefix="aBlk" />
275
+
276
+ {/* Pill-shaped frame body with vertical bevel + shadow */}
277
+ <g filter="url(#shadABlk)">
278
+ <path d="M120.1,84.3H46.9c-14.2,0-25.6-11.5-25.6-25.6v0c0-14.2,11.5-25.6,25.6-25.6h73.2c14.2,0,25.6,11.5,25.6,25.6v0C145.7,72.8,134.2,84.3,120.1,84.3z"
279
+ fill="url(#bevelABlk)" stroke="#C9D3E4" strokeWidth="0.7" />
280
+ </g>
281
+
282
+ {/* Inner pill panel */}
283
+ <path d="M120.3,79.3H46.6C35.2,79.3,26,70.1,26,58.7v0c0-11.4,9.2-20.6,20.6-20.6h73.6c11.4,0,20.6,9.2,20.6,20.6v0C140.8,70.1,131.6,79.3,120.3,79.3z"
284
+ fill="#DDE6F5" stroke="#C9D3E4" strokeWidth="0.5" />
285
+
286
+ {/* Waveform bars — positions from block_audio.svg mockup (tall, short, short, tall, short) */}
287
+ <path d="M73.9,43.1c-1.1,0-1.9,0.9-1.9,1.9v27.2c0,1.1,0.9,1.9,1.9,1.9c1.1,0,1.9-0.9,1.9-1.9V45.1C75.8,44,74.9,43.1,73.9,43.1z" fill="#3580f9" />
288
+ <path d="M86.9,49.2c-1.1,0-1.9,0.9-1.9,1.9v15.2c0,1.1,0.9,1.9,1.9,1.9c1.1,0,1.9-0.9,1.9-1.9V51.1C88.9,50,88,49.2,86.9,49.2z" fill="#3580f9" />
289
+ <path d="M98.3,49.2c-1.1,0-1.9,0.9-1.9,1.9v15.2c0,1.1,0.9,1.9,1.9,1.9c1.1,0,1.9-0.9,1.9-1.9V51.1C100.2,50,99.3,49.2,98.3,49.2z" fill="#3580f9" />
290
+ <path d="M109.5,43.1c-1.1,0-1.9,0.9-1.9,1.9v27.2c0,1.1,0.9,1.9,1.9,1.9c1.1,0,1.9-0.9,1.9-1.9V45.1C111.4,44,110.5,43.1,109.5,43.1z" fill="#3580f9" />
291
+ <path d="M121.1,49.2c-1.1,0-1.9,0.9-1.9,1.9v15.2c0,1.1,0.9,1.9,1.9,1.9c1.1,0,1.9-0.9,1.9-1.9V51.1C123,50,122.2,49.2,121.1,49.2z" fill="#3580f9" />
292
+
293
+ {/* Play button — rounded triangle */}
294
+ <path d="M42.3,59.6v-7.7c0-1.7,1.9-2.8,3.4-2l6.7,3.8l6.7,3.8c1.5,0.9,1.5,3.1,0,3.9l-6.7,3.8l-6.7,3.8c-1.5,0.9-3.4-0.2-3.4-2V59.6z"
295
+ fill="#3580f9" />
296
+
297
+ {/* Dashed frame outline — matches the pill frame */}
298
+ <path d="M120.1,84.3H46.9c-14.2,0-25.6-11.5-25.6-25.6v0c0-14.2,11.5-25.6,25.6-25.6h73.2c14.2,0,25.6,11.5,25.6,25.6v0C145.7,72.8,134.2,84.3,120.1,84.3z"
299
+ fill="none" stroke="#3580f9" strokeWidth="2" strokeDasharray="3,3" />
300
+ </svg>
301
+ );
302
+ }
303
+
304
+ // ─────────────────────────────────────────────────────────────────────
305
+ // Lookup map
306
+ // ─────────────────────────────────────────────────────────────────────
307
+ export const BLOCK_CARD_ICONS: Record<string, React.FC> = {
308
+ textBlock: TextBlockCardIcon,
309
+ imageBlock: ImageBlockCardIcon,
310
+ imageGridBlock: ImageGridBlockCardIcon,
311
+ videoBlock: VideoBlockCardIcon,
312
+ spacerBlock: SpacerBlockCardIcon,
313
+ buttonBlock: ButtonBlockCardIcon,
314
+ beforeAfterBlock: BeforeAfterBlockCardIcon,
315
+ audioBlock: AudioBlockCardIcon,
316
+ };