@morphika/andami 0.1.9 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/admin/pages/[slug]/page.tsx +3 -7
- package/app/api/admin/pages/[slug]/route.ts +2 -28
- package/app/api/admin/settings/route.ts +30 -0
- package/components/admin/nav-builder/NavBuilder.tsx +90 -14
- package/components/admin/nav-builder/NavGeneralSettings.tsx +521 -271
- package/components/admin/nav-builder/NavItemSettings.tsx +331 -312
- package/components/admin/nav-builder/NavMobileSettings.tsx +159 -140
- package/components/admin/nav-builder/NavSettingsFields.tsx +287 -21
- package/components/admin/nav-builder/NavSettingsPanel.tsx +137 -127
- package/components/blocks/EnterAnimationWrapper.tsx +19 -4
- package/components/blocks/PageRenderer.tsx +2 -15
- package/components/blocks/ProjectGridBlockRenderer.tsx +34 -36
- package/components/blocks/TextBlockRenderer.tsx +1 -1
- package/components/builder/DndWrapper.tsx +2 -24
- package/components/builder/InsertionLines.tsx +5 -5
- package/components/builder/ReadOnlyFrame.tsx +5 -49
- package/components/builder/SectionV2Canvas.tsx +2 -2
- package/components/builder/SectionV2Column.tsx +5 -5
- package/components/builder/SettingsPanel.tsx +0 -12
- package/components/builder/SortableBlock.tsx +3 -3
- package/components/builder/SortableRow.tsx +6 -27
- package/components/builder/editors/ButtonBlockEditor.tsx +8 -3
- package/components/builder/editors/CoverBlockEditor.tsx +14 -6
- package/components/builder/editors/ImageBlockEditor.tsx +8 -3
- package/components/builder/editors/ImageGridBlockEditor.tsx +8 -3
- package/components/builder/editors/ProjectGridEditor.tsx +7 -46
- package/components/builder/editors/SpacerBlockEditor.tsx +4 -1
- package/components/builder/editors/StaggerSettings.tsx +2 -1
- package/components/builder/editors/TextBlockEditor.tsx +8 -3
- package/components/builder/editors/VideoBlockEditor.tsx +10 -4
- package/components/builder/editors/section-icons.tsx +492 -0
- package/components/builder/editors/shared.tsx +23 -4
- package/components/builder/live-preview/LiveTextEditor.tsx +1 -1
- package/components/builder/live-preview/ProjectCardWrapper.tsx +3 -3
- package/components/builder/live-preview/drag-utils.tsx +2 -2
- package/components/builder/settings-panel/AnimationTab.tsx +2 -16
- package/components/builder/settings-panel/BlockLayoutTab.tsx +13 -58
- package/components/builder/settings-panel/ColumnV2Settings.tsx +4 -1
- package/components/builder/settings-panel/PageSettings.tsx +10 -4
- package/components/builder/settings-panel/ParallaxGroupSettings.tsx +6 -2
- package/components/builder/settings-panel/ParallaxSlideSettings.tsx +8 -3
- package/components/builder/settings-panel/SectionV2LayoutTab.tsx +11 -47
- package/components/builder/settings-panel/SectionV2Settings.tsx +6 -27
- package/components/builder/settings-panel/index.ts +0 -1
- package/components/builder/settings-panel/responsive-helpers.ts +2 -50
- package/components/builder/settings-panel/useSettingsPanelSelection.ts +1 -16
- package/components/ui/Navbar.tsx +151 -30
- package/lib/builder/constants.ts +5 -4
- package/lib/builder/serializer/normalizers.ts +2 -40
- package/lib/builder/serializer/serializers.ts +3 -74
- package/lib/builder/store-blocks.ts +3 -19
- package/lib/builder/store-helpers.ts +2 -2
- package/lib/builder/store-sections.ts +26 -64
- package/lib/builder/store.ts +3 -6
- package/lib/builder/templates.ts +9 -45
- package/lib/builder/types.ts +4 -11
- package/lib/sanity/queries.ts +6 -29
- package/lib/sanity/types.ts +24 -70
- package/package.json +4 -1
- package/sanity/schemas/index.ts +0 -5
- package/sanity/schemas/objects/parallaxGroup.ts +2 -2
- package/sanity/schemas/page.ts +1 -1
- package/sanity/schemas/pageSectionV2.ts +1 -0
- package/sanity/schemas/siteSettings.ts +42 -0
- package/styles/base.css +8 -2
- package/components/blocks/SectionRenderer.tsx +0 -171
- package/components/builder/settings-panel/LayoutTab.tsx +0 -382
- package/sanity/schemas/pageSection.ts +0 -157
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* section-icons.tsx — Centralized colored section header icons.
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for ALL SettingsSection icons across the builder.
|
|
5
|
+
* Each concept (Spacing, Background, Border, etc.) has one icon + one color,
|
|
6
|
+
* used consistently everywhere it appears (blocks, sections, pages, etc.).
|
|
7
|
+
*
|
|
8
|
+
* Color palette (semantic grouping):
|
|
9
|
+
* Amber #d97706 / #fef3c7 — Spacing, Style
|
|
10
|
+
* Rose #e11d48 / #ffe4e6 — Offset
|
|
11
|
+
* Indigo #6366f1 / #e0e7ff — Background, Cover Background
|
|
12
|
+
* Slate #475569 / #f1f5f9 — Border
|
|
13
|
+
* Blue #2563eb / #dbeafe — Typography, Grid, Grid Gaps, Column Size
|
|
14
|
+
* Cyan #0891b2 / #cffafe — Content, Source, Images, Projects
|
|
15
|
+
* Green #059669 / #d1fae5 — Animation, Stagger, Transition
|
|
16
|
+
* Purple #7c3aed / #ede9fe — Position, Link, Alignment
|
|
17
|
+
* Orange #ea580c / #ffedd5 — Appearance, Cover Effects
|
|
18
|
+
* Teal #0d9488 / #ccfbf1 — Layout, Layout Preset
|
|
19
|
+
* Sky #0284c7 / #e0f2fe — Playback, Video, Height
|
|
20
|
+
* Pink #db2777 / #fce7f3 — Options, CTA Button
|
|
21
|
+
* Neutral #525252 / #f5f5f5 — General, Info, SEO
|
|
22
|
+
* Violet #8b5cf6 / #ede9fe — Navigation, Navbar Color
|
|
23
|
+
* Red #dc2626 / #fee2e2 — Overlay
|
|
24
|
+
*
|
|
25
|
+
* Session 163: Created — unified icon system for the entire builder.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import type { ReactNode } from "react";
|
|
29
|
+
|
|
30
|
+
// ============================================
|
|
31
|
+
// Icon + color definitions
|
|
32
|
+
// ============================================
|
|
33
|
+
|
|
34
|
+
export interface SectionIconDef {
|
|
35
|
+
icon: ReactNode;
|
|
36
|
+
color: string; // stroke/fill color for the SVG
|
|
37
|
+
bg: string; // background pill color
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ── Spacing (Amber) ──
|
|
41
|
+
export function SpacingIcon() {
|
|
42
|
+
return (
|
|
43
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#d97706" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
44
|
+
<rect x="3" y="3" width="18" height="18" rx="2" strokeDasharray="4 2" />
|
|
45
|
+
<rect x="7" y="7" width="10" height="10" rx="1" />
|
|
46
|
+
</svg>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
SpacingIcon.bg = "#fef3c7";
|
|
50
|
+
|
|
51
|
+
// ── Offset (Rose) ──
|
|
52
|
+
export function OffsetIcon() {
|
|
53
|
+
return (
|
|
54
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#e11d48" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
55
|
+
<rect x="3" y="3" width="14" height="14" rx="2" strokeDasharray="4 2" opacity="0.5" />
|
|
56
|
+
<rect x="7" y="7" width="14" height="14" rx="2" />
|
|
57
|
+
<path d="M5 5 L7 7" strokeWidth="1.5" />
|
|
58
|
+
</svg>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
OffsetIcon.bg = "#ffe4e6";
|
|
62
|
+
|
|
63
|
+
// ── Background (Indigo) ──
|
|
64
|
+
export function BackgroundIcon() {
|
|
65
|
+
return (
|
|
66
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#6366f1" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
67
|
+
<rect x="3" y="3" width="18" height="18" rx="2" />
|
|
68
|
+
<circle cx="8.5" cy="8.5" r="1.5" />
|
|
69
|
+
<polyline points="21 15 16 10 5 21" />
|
|
70
|
+
</svg>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
BackgroundIcon.bg = "#e0e7ff";
|
|
74
|
+
|
|
75
|
+
// ── Border (Slate) ──
|
|
76
|
+
export function BorderIcon() {
|
|
77
|
+
return (
|
|
78
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#475569" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
79
|
+
<rect x="3" y="3" width="18" height="18" rx="3" />
|
|
80
|
+
<path d="M3 9 L21 9" strokeWidth="1.5" opacity="0.5" />
|
|
81
|
+
</svg>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
BorderIcon.bg = "#f1f5f9";
|
|
85
|
+
|
|
86
|
+
// ── Alignment (Purple) ──
|
|
87
|
+
export function AlignmentIcon() {
|
|
88
|
+
return (
|
|
89
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#7c3aed" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
90
|
+
<line x1="18" y1="10" x2="6" y2="10" />
|
|
91
|
+
<line x1="21" y1="6" x2="3" y2="6" />
|
|
92
|
+
<line x1="15" y1="14" x2="9" y2="14" />
|
|
93
|
+
<line x1="18" y1="18" x2="6" y2="18" />
|
|
94
|
+
</svg>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
AlignmentIcon.bg = "#ede9fe";
|
|
98
|
+
|
|
99
|
+
// ── Typography (Blue) ──
|
|
100
|
+
export function TypographyIcon() {
|
|
101
|
+
return (
|
|
102
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#2563eb" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
103
|
+
<polyline points="4 7 4 4 20 4 20 7" />
|
|
104
|
+
<line x1="9" y1="20" x2="15" y2="20" />
|
|
105
|
+
<line x1="12" y1="4" x2="12" y2="20" />
|
|
106
|
+
</svg>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
TypographyIcon.bg = "#dbeafe";
|
|
110
|
+
|
|
111
|
+
// ── Grid / Grid Gaps (Blue) ──
|
|
112
|
+
export function GridIcon() {
|
|
113
|
+
return (
|
|
114
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#2563eb" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
115
|
+
<rect x="3" y="3" width="7" height="7" />
|
|
116
|
+
<rect x="14" y="3" width="7" height="7" />
|
|
117
|
+
<rect x="14" y="14" width="7" height="7" />
|
|
118
|
+
<rect x="3" y="14" width="7" height="7" />
|
|
119
|
+
</svg>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
GridIcon.bg = "#dbeafe";
|
|
123
|
+
|
|
124
|
+
// ── Grid Gaps (Blue — slightly different icon) ──
|
|
125
|
+
export function GridGapsIcon() {
|
|
126
|
+
return (
|
|
127
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#2563eb" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
128
|
+
<rect x="3" y="3" width="7" height="7" rx="1" />
|
|
129
|
+
<rect x="14" y="3" width="7" height="7" rx="1" />
|
|
130
|
+
<rect x="3" y="14" width="7" height="7" rx="1" />
|
|
131
|
+
<rect x="14" y="14" width="7" height="7" rx="1" />
|
|
132
|
+
<line x1="12" y1="3" x2="12" y2="21" strokeDasharray="2 2" opacity="0.5" />
|
|
133
|
+
<line x1="3" y1="12" x2="21" y2="12" strokeDasharray="2 2" opacity="0.5" />
|
|
134
|
+
</svg>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
GridGapsIcon.bg = "#dbeafe";
|
|
138
|
+
|
|
139
|
+
// ── Column Size (Blue) ──
|
|
140
|
+
export function ColumnSizeIcon() {
|
|
141
|
+
return (
|
|
142
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#2563eb" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
143
|
+
<rect x="3" y="4" width="18" height="16" rx="2" />
|
|
144
|
+
<line x1="9" y1="4" x2="9" y2="20" />
|
|
145
|
+
<path d="M4 12 L7 12" />
|
|
146
|
+
<path d="M11 12 L20 12" />
|
|
147
|
+
</svg>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
ColumnSizeIcon.bg = "#dbeafe";
|
|
151
|
+
|
|
152
|
+
// ── Layout Preset (Teal) ──
|
|
153
|
+
export function LayoutPresetIcon() {
|
|
154
|
+
return (
|
|
155
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0d9488" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
156
|
+
<rect x="3" y="3" width="18" height="18" rx="2" />
|
|
157
|
+
<line x1="9" y1="3" x2="9" y2="21" />
|
|
158
|
+
<line x1="3" y1="12" x2="9" y2="12" />
|
|
159
|
+
</svg>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
LayoutPresetIcon.bg = "#ccfbf1";
|
|
163
|
+
|
|
164
|
+
// ── Layout (Teal) ──
|
|
165
|
+
export function LayoutIcon() {
|
|
166
|
+
return (
|
|
167
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0d9488" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
168
|
+
<rect x="3" y="3" width="18" height="18" rx="2" />
|
|
169
|
+
<line x1="3" y1="9" x2="21" y2="9" />
|
|
170
|
+
<line x1="9" y1="9" x2="9" y2="21" />
|
|
171
|
+
</svg>
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
LayoutIcon.bg = "#ccfbf1";
|
|
175
|
+
|
|
176
|
+
// ── Content / Source (Cyan) ──
|
|
177
|
+
export function ContentIcon() {
|
|
178
|
+
return (
|
|
179
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0891b2" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
180
|
+
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
|
181
|
+
<polyline points="14 2 14 8 20 8" />
|
|
182
|
+
<line x1="16" y1="13" x2="8" y2="13" />
|
|
183
|
+
<line x1="16" y1="17" x2="8" y2="17" />
|
|
184
|
+
</svg>
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
ContentIcon.bg = "#cffafe";
|
|
188
|
+
|
|
189
|
+
// ── Source (Cyan) ──
|
|
190
|
+
export function SourceIcon() {
|
|
191
|
+
return (
|
|
192
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0891b2" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
193
|
+
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
|
|
194
|
+
<polyline points="7 10 12 15 17 10" />
|
|
195
|
+
<line x1="12" y1="15" x2="12" y2="3" />
|
|
196
|
+
</svg>
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
SourceIcon.bg = "#cffafe";
|
|
200
|
+
|
|
201
|
+
// ── Images (Cyan) ──
|
|
202
|
+
export function ImagesIcon() {
|
|
203
|
+
return (
|
|
204
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0891b2" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
205
|
+
<rect x="3" y="3" width="18" height="18" rx="2" />
|
|
206
|
+
<circle cx="8.5" cy="8.5" r="1.5" />
|
|
207
|
+
<polyline points="21 15 16 10 5 21" />
|
|
208
|
+
</svg>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
ImagesIcon.bg = "#cffafe";
|
|
212
|
+
|
|
213
|
+
// ── Projects (Cyan) ──
|
|
214
|
+
export function ProjectsIcon() {
|
|
215
|
+
return (
|
|
216
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0891b2" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
217
|
+
<rect x="3" y="3" width="18" height="7" rx="2" />
|
|
218
|
+
<rect x="3" y="14" width="18" height="7" rx="2" />
|
|
219
|
+
<circle cx="7" cy="6.5" r="1" />
|
|
220
|
+
<circle cx="7" cy="17.5" r="1" />
|
|
221
|
+
<line x1="10" y1="6.5" x2="17" y2="6.5" />
|
|
222
|
+
<line x1="10" y1="17.5" x2="17" y2="17.5" />
|
|
223
|
+
</svg>
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
ProjectsIcon.bg = "#cffafe";
|
|
227
|
+
|
|
228
|
+
// ── Text (Cyan) ──
|
|
229
|
+
export function TextIcon() {
|
|
230
|
+
return (
|
|
231
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0891b2" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
232
|
+
<line x1="17" y1="10" x2="3" y2="10" />
|
|
233
|
+
<line x1="21" y1="6" x2="3" y2="6" />
|
|
234
|
+
<line x1="21" y1="14" x2="3" y2="14" />
|
|
235
|
+
<line x1="17" y1="18" x2="3" y2="18" />
|
|
236
|
+
</svg>
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
TextIcon.bg = "#cffafe";
|
|
240
|
+
|
|
241
|
+
// ── Columns (Blue) ──
|
|
242
|
+
export function ColumnsIcon() {
|
|
243
|
+
return (
|
|
244
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#2563eb" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
245
|
+
<rect x="3" y="3" width="18" height="18" rx="2" />
|
|
246
|
+
<line x1="9" y1="3" x2="9" y2="21" />
|
|
247
|
+
<line x1="15" y1="3" x2="15" y2="21" />
|
|
248
|
+
</svg>
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
ColumnsIcon.bg = "#dbeafe";
|
|
252
|
+
|
|
253
|
+
// ── Appearance (Orange) ──
|
|
254
|
+
export function AppearanceIcon() {
|
|
255
|
+
return (
|
|
256
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#ea580c" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
257
|
+
<circle cx="12" cy="12" r="9" />
|
|
258
|
+
<path d="M12 3 A9 9 0 0 1 12 21 Z" fill="#ea580c" opacity="0.2" />
|
|
259
|
+
<circle cx="12" cy="12" r="3" />
|
|
260
|
+
</svg>
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
AppearanceIcon.bg = "#ffedd5";
|
|
264
|
+
|
|
265
|
+
// ── Style (Amber) ──
|
|
266
|
+
export function StyleIcon() {
|
|
267
|
+
return (
|
|
268
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#d97706" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
269
|
+
<circle cx="13.5" cy="6.5" r="2.5" />
|
|
270
|
+
<path d="M17 2H7a5 5 0 0 0-5 5v10a5 5 0 0 0 5 5h10a5 5 0 0 0 5-5V7a5 5 0 0 0-5-5z" />
|
|
271
|
+
</svg>
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
StyleIcon.bg = "#fef3c7";
|
|
275
|
+
|
|
276
|
+
// ── Animation / Entrance (Green) ──
|
|
277
|
+
export function AnimationIcon() {
|
|
278
|
+
return (
|
|
279
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#059669" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
280
|
+
<path d="M5 12h14" />
|
|
281
|
+
<path d="M12 5l7 7-7 7" />
|
|
282
|
+
</svg>
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
AnimationIcon.bg = "#d1fae5";
|
|
286
|
+
|
|
287
|
+
// ── Stagger Children (Green) ──
|
|
288
|
+
export function StaggerIcon() {
|
|
289
|
+
return (
|
|
290
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#059669" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
291
|
+
<line x1="4" y1="6" x2="14" y2="6" />
|
|
292
|
+
<line x1="7" y1="12" x2="17" y2="12" />
|
|
293
|
+
<line x1="10" y1="18" x2="20" y2="18" />
|
|
294
|
+
</svg>
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
StaggerIcon.bg = "#d1fae5";
|
|
298
|
+
|
|
299
|
+
// ── Transition Effect (Green) ──
|
|
300
|
+
export function TransitionIcon() {
|
|
301
|
+
return (
|
|
302
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#059669" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
303
|
+
<rect x="2" y="7" width="8" height="10" rx="2" opacity="0.5" />
|
|
304
|
+
<rect x="14" y="7" width="8" height="10" rx="2" />
|
|
305
|
+
<path d="M10 12 L14 12" />
|
|
306
|
+
<path d="M12 10 L14 12 L12 14" />
|
|
307
|
+
</svg>
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
TransitionIcon.bg = "#d1fae5";
|
|
311
|
+
|
|
312
|
+
// ── Position (Purple) ──
|
|
313
|
+
export function PositionIcon() {
|
|
314
|
+
return (
|
|
315
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#7c3aed" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
316
|
+
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" />
|
|
317
|
+
<circle cx="12" cy="10" r="3" />
|
|
318
|
+
</svg>
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
PositionIcon.bg = "#ede9fe";
|
|
322
|
+
|
|
323
|
+
// ── Link (Purple) ──
|
|
324
|
+
export function LinkIcon() {
|
|
325
|
+
return (
|
|
326
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#7c3aed" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
327
|
+
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" />
|
|
328
|
+
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" />
|
|
329
|
+
</svg>
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
LinkIcon.bg = "#ede9fe";
|
|
333
|
+
|
|
334
|
+
// ── Video (Sky) ──
|
|
335
|
+
export function VideoIcon() {
|
|
336
|
+
return (
|
|
337
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0284c7" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
338
|
+
<rect x="2" y="4" width="14" height="16" rx="2" />
|
|
339
|
+
<path d="M16 10 L22 7 L22 17 L16 14 Z" />
|
|
340
|
+
</svg>
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
VideoIcon.bg = "#e0f2fe";
|
|
344
|
+
|
|
345
|
+
// ── Playback (Sky) ──
|
|
346
|
+
export function PlaybackIcon() {
|
|
347
|
+
return (
|
|
348
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0284c7" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
349
|
+
<circle cx="12" cy="12" r="9" />
|
|
350
|
+
<polygon points="10 8 16 12 10 16" fill="#0284c7" opacity="0.3" />
|
|
351
|
+
</svg>
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
PlaybackIcon.bg = "#e0f2fe";
|
|
355
|
+
|
|
356
|
+
// ── Height (Sky) ──
|
|
357
|
+
export function HeightIcon() {
|
|
358
|
+
return (
|
|
359
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#0284c7" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
360
|
+
<path d="M12 4 L12 20" />
|
|
361
|
+
<path d="M8 8 L12 4 L16 8" />
|
|
362
|
+
<path d="M8 16 L12 20 L16 16" />
|
|
363
|
+
</svg>
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
HeightIcon.bg = "#e0f2fe";
|
|
367
|
+
|
|
368
|
+
// ── Options / CTA Button (Pink) ──
|
|
369
|
+
export function OptionsIcon() {
|
|
370
|
+
return (
|
|
371
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#db2777" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
372
|
+
<circle cx="12" cy="12" r="1" />
|
|
373
|
+
<circle cx="19" cy="12" r="1" />
|
|
374
|
+
<circle cx="5" cy="12" r="1" />
|
|
375
|
+
</svg>
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
OptionsIcon.bg = "#fce7f3";
|
|
379
|
+
|
|
380
|
+
// ── CTA Button (Pink) ──
|
|
381
|
+
export function CTAButtonIcon() {
|
|
382
|
+
return (
|
|
383
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#db2777" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
384
|
+
<rect x="3" y="8" width="18" height="8" rx="3" />
|
|
385
|
+
<line x1="8" y1="12" x2="16" y2="12" />
|
|
386
|
+
</svg>
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
CTAButtonIcon.bg = "#fce7f3";
|
|
390
|
+
|
|
391
|
+
// ── Settings (Amber) — generic ──
|
|
392
|
+
export function SettingsIcon() {
|
|
393
|
+
return (
|
|
394
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#d97706" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
395
|
+
<circle cx="12" cy="12" r="3" />
|
|
396
|
+
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
|
|
397
|
+
</svg>
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
SettingsIcon.bg = "#fef3c7";
|
|
401
|
+
|
|
402
|
+
// ── General / Info (Neutral) ──
|
|
403
|
+
export function GeneralIcon() {
|
|
404
|
+
return (
|
|
405
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#525252" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
406
|
+
<circle cx="12" cy="12" r="9" />
|
|
407
|
+
<line x1="12" y1="16" x2="12" y2="12" />
|
|
408
|
+
<line x1="12" y1="8" x2="12.01" y2="8" />
|
|
409
|
+
</svg>
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
GeneralIcon.bg = "#f5f5f5";
|
|
413
|
+
|
|
414
|
+
// ── Info (Neutral) ──
|
|
415
|
+
export function InfoIcon() {
|
|
416
|
+
return (
|
|
417
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#525252" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
418
|
+
<circle cx="12" cy="12" r="9" />
|
|
419
|
+
<line x1="12" y1="16" x2="12" y2="12" />
|
|
420
|
+
<line x1="12" y1="8" x2="12.01" y2="8" />
|
|
421
|
+
</svg>
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
InfoIcon.bg = "#f5f5f5";
|
|
425
|
+
|
|
426
|
+
// ── SEO (Neutral) ──
|
|
427
|
+
export function SEOIcon() {
|
|
428
|
+
return (
|
|
429
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#525252" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
430
|
+
<circle cx="11" cy="11" r="8" />
|
|
431
|
+
<line x1="21" y1="21" x2="16.65" y2="16.65" />
|
|
432
|
+
</svg>
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
SEOIcon.bg = "#f5f5f5";
|
|
436
|
+
|
|
437
|
+
// ── Navigation (Violet) ──
|
|
438
|
+
export function NavigationIcon() {
|
|
439
|
+
return (
|
|
440
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#8b5cf6" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
441
|
+
<line x1="3" y1="12" x2="21" y2="12" />
|
|
442
|
+
<line x1="3" y1="6" x2="21" y2="6" />
|
|
443
|
+
<line x1="3" y1="18" x2="21" y2="18" />
|
|
444
|
+
</svg>
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
NavigationIcon.bg = "#ede9fe";
|
|
448
|
+
|
|
449
|
+
// ── Navbar Color (Violet) ──
|
|
450
|
+
export function NavbarColorIcon() {
|
|
451
|
+
return (
|
|
452
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#8b5cf6" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
453
|
+
<rect x="3" y="3" width="18" height="6" rx="2" />
|
|
454
|
+
<circle cx="7" cy="6" r="1.5" fill="#8b5cf6" opacity="0.3" />
|
|
455
|
+
<line x1="11" y1="6" x2="17" y2="6" />
|
|
456
|
+
</svg>
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
NavbarColorIcon.bg = "#ede9fe";
|
|
460
|
+
|
|
461
|
+
// ── Overlay (Red) ──
|
|
462
|
+
export function OverlayIcon() {
|
|
463
|
+
return (
|
|
464
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#dc2626" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
465
|
+
<rect x="3" y="3" width="18" height="18" rx="2" />
|
|
466
|
+
<rect x="3" y="3" width="18" height="18" rx="2" fill="#dc2626" opacity="0.15" />
|
|
467
|
+
</svg>
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
OverlayIcon.bg = "#fee2e2";
|
|
471
|
+
|
|
472
|
+
// ── Cover Background (Indigo) ──
|
|
473
|
+
export function CoverBackgroundIcon() {
|
|
474
|
+
return (
|
|
475
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#6366f1" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
476
|
+
<rect x="3" y="3" width="18" height="18" rx="2" />
|
|
477
|
+
<path d="M3 3 L21 21" opacity="0.4" />
|
|
478
|
+
<path d="M21 3 L3 21" opacity="0.4" />
|
|
479
|
+
</svg>
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
CoverBackgroundIcon.bg = "#e0e7ff";
|
|
483
|
+
|
|
484
|
+
// ── Cover Effects (Orange) ──
|
|
485
|
+
export function CoverEffectsIcon() {
|
|
486
|
+
return (
|
|
487
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#ea580c" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
488
|
+
<path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" />
|
|
489
|
+
</svg>
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
CoverEffectsIcon.bg = "#ffedd5";
|
|
@@ -153,8 +153,13 @@ export function SettingsField({
|
|
|
153
153
|
// ============================================
|
|
154
154
|
|
|
155
155
|
/**
|
|
156
|
-
* Collapsible section
|
|
157
|
-
*
|
|
156
|
+
* Collapsible section with optional colored icon pill.
|
|
157
|
+
*
|
|
158
|
+
* When an `icon` is provided with a `bg` static property (from section-icons.tsx),
|
|
159
|
+
* it renders as a colored pill (26×26px rounded square with tinted background).
|
|
160
|
+
* Without `bg`, the icon renders inline in neutral gray (legacy behavior).
|
|
161
|
+
*
|
|
162
|
+
* Session 163: Upgraded to colored icon pills for visual consistency with nav builder.
|
|
158
163
|
*/
|
|
159
164
|
export function SettingsSection({
|
|
160
165
|
title,
|
|
@@ -169,14 +174,28 @@ export function SettingsSection({
|
|
|
169
174
|
}) {
|
|
170
175
|
const [isOpen, setIsOpen] = useState(defaultOpen);
|
|
171
176
|
|
|
177
|
+
// Check if icon component has a `.bg` property (colored icon from section-icons.tsx)
|
|
178
|
+
const iconBg = icon && typeof icon === "object"
|
|
179
|
+
? ((icon as unknown as { type?: { bg?: string } }).type?.bg ?? null)
|
|
180
|
+
: null;
|
|
181
|
+
|
|
172
182
|
return (
|
|
173
183
|
<div className="border-b border-[#f0f0f0] last:border-b-0">
|
|
174
184
|
<button
|
|
175
185
|
onClick={() => setIsOpen(!isOpen)}
|
|
176
186
|
className="w-full flex items-center justify-between px-4 py-3 transition-colors hover:bg-[#fafafa] group"
|
|
177
187
|
>
|
|
178
|
-
<span className="flex items-center gap-
|
|
179
|
-
{icon &&
|
|
188
|
+
<span className="flex items-center gap-2 text-xs font-medium text-neutral-900">
|
|
189
|
+
{icon && iconBg ? (
|
|
190
|
+
<span
|
|
191
|
+
className="w-[26px] h-[26px] rounded-[7px] flex items-center justify-center shrink-0"
|
|
192
|
+
style={{ background: iconBg }}
|
|
193
|
+
>
|
|
194
|
+
{icon}
|
|
195
|
+
</span>
|
|
196
|
+
) : icon ? (
|
|
197
|
+
<span className="text-neutral-400 flex-shrink-0">{icon}</span>
|
|
198
|
+
) : null}
|
|
180
199
|
{title}
|
|
181
200
|
</span>
|
|
182
201
|
<span className="text-base text-neutral-300 font-light leading-none transition-colors group-hover:text-neutral-500">
|
|
@@ -149,7 +149,7 @@ export default function LiveTextEditor({ block, editable = false }: { block: Tex
|
|
|
149
149
|
fontFamily: "inherit",
|
|
150
150
|
outline: "none",
|
|
151
151
|
whiteSpace: "pre-wrap",
|
|
152
|
-
wordBreak: "
|
|
152
|
+
wordBreak: "normal",
|
|
153
153
|
minHeight: "1em",
|
|
154
154
|
// Multi-column layout: gap inherits global grid gutter
|
|
155
155
|
...(cols ? {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
import { useState, useCallback, useRef } from "react";
|
|
12
12
|
import { ProjectGridCard } from "./shared";
|
|
13
13
|
import { useBuilderStore } from "../../../lib/builder/store";
|
|
14
|
-
import { ADMIN_BLUE,
|
|
14
|
+
import { ADMIN_BLUE, DROP_BLUE, CrossArrowIcon } from "./drag-utils";
|
|
15
15
|
import type { ProjectGridItem } from "../../../lib/sanity/types";
|
|
16
16
|
|
|
17
17
|
// ─── Props ───────────────────────────────────────────────────────────
|
|
@@ -278,11 +278,11 @@ export default function ProjectCardWrapper({
|
|
|
278
278
|
style={{
|
|
279
279
|
position: "absolute",
|
|
280
280
|
inset: 0,
|
|
281
|
-
backgroundColor: "rgba(
|
|
281
|
+
backgroundColor: "rgba(7,107,255,0.30)",
|
|
282
282
|
borderRadius: br,
|
|
283
283
|
pointerEvents: "none",
|
|
284
284
|
zIndex: 5,
|
|
285
|
-
border: `2px solid ${
|
|
285
|
+
border: `2px solid ${DROP_BLUE}`,
|
|
286
286
|
}}
|
|
287
287
|
/>
|
|
288
288
|
)}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Session 162: Extracted from LiveProjectGridPreview.tsx (Phase B1).
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { BUILDER_BLUE
|
|
10
|
+
import { BUILDER_BLUE } from "../../../lib/builder/constants";
|
|
11
11
|
import type { MasonryOutput } from "../../../lib/builder/masonry";
|
|
12
12
|
|
|
13
13
|
// ─── Constants ───────────────────────────────────────────────────────
|
|
@@ -16,7 +16,7 @@ export const HOLD_DELAY = 150; // ms before card-body drag activates
|
|
|
16
16
|
export const MOVE_THRESHOLD_SQ = 9; // 3px² — grabbed → dragging
|
|
17
17
|
export const CANCEL_DURATION = 200; // ms — cancel fly-back animation
|
|
18
18
|
export const ADMIN_BLUE = BUILDER_BLUE;
|
|
19
|
-
export const
|
|
19
|
+
export const DROP_BLUE = BUILDER_BLUE;
|
|
20
20
|
|
|
21
21
|
// ─── Types ───────────────────────────────────────────────────────────
|
|
22
22
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { useBuilderStore } from "../../../lib/builder/store";
|
|
10
|
-
import type { ContentBlock,
|
|
10
|
+
import type { ContentBlock, ProjectGridBlock } from "../../../lib/sanity/types";
|
|
11
11
|
import type { HoverEffectConfig } from "../../../lib/animation/hover-effect-types";
|
|
12
12
|
import EnterAnimationPicker from "../editors/EnterAnimationPicker";
|
|
13
13
|
import HoverEffectPicker from "../editors/HoverEffectPicker";
|
|
@@ -32,25 +32,11 @@ export function getBlockHoverEffect(block: ContentBlock): HoverEffectConfig | un
|
|
|
32
32
|
|
|
33
33
|
interface AnimationTabProps {
|
|
34
34
|
selectedBlock: { block: ContentBlock; rowKey: string; colKey: string; isSection: boolean } | null;
|
|
35
|
-
selectedSection: PageSection | null;
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
export function AnimationTab({ selectedBlock
|
|
37
|
+
export function AnimationTab({ selectedBlock }: AnimationTabProps) {
|
|
39
38
|
const store = useBuilderStore();
|
|
40
39
|
|
|
41
|
-
// PageSection (V1): enter animation on the section settings level
|
|
42
|
-
if (selectedSection) {
|
|
43
|
-
return (
|
|
44
|
-
<EnterAnimationPicker
|
|
45
|
-
mode={{ level: "section", parentConfig: store.pageSettings.enter_animation }}
|
|
46
|
-
config={selectedSection.settings?.enter_animation}
|
|
47
|
-
onChange={(cfg) => {
|
|
48
|
-
store.updateSectionSettings(selectedSection._key, { enter_animation: cfg });
|
|
49
|
-
}}
|
|
50
|
-
/>
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
40
|
// Block level: type-specific enter picker + card entrance for projectGrid
|
|
55
41
|
if (selectedBlock) {
|
|
56
42
|
const isProjectGrid = selectedBlock.block._type === "projectGridBlock";
|