@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.
Files changed (68) hide show
  1. package/app/admin/pages/[slug]/page.tsx +3 -7
  2. package/app/api/admin/pages/[slug]/route.ts +2 -28
  3. package/app/api/admin/settings/route.ts +30 -0
  4. package/components/admin/nav-builder/NavBuilder.tsx +90 -14
  5. package/components/admin/nav-builder/NavGeneralSettings.tsx +521 -271
  6. package/components/admin/nav-builder/NavItemSettings.tsx +331 -312
  7. package/components/admin/nav-builder/NavMobileSettings.tsx +159 -140
  8. package/components/admin/nav-builder/NavSettingsFields.tsx +287 -21
  9. package/components/admin/nav-builder/NavSettingsPanel.tsx +137 -127
  10. package/components/blocks/EnterAnimationWrapper.tsx +19 -4
  11. package/components/blocks/PageRenderer.tsx +2 -15
  12. package/components/blocks/ProjectGridBlockRenderer.tsx +34 -36
  13. package/components/blocks/TextBlockRenderer.tsx +1 -1
  14. package/components/builder/DndWrapper.tsx +2 -24
  15. package/components/builder/InsertionLines.tsx +5 -5
  16. package/components/builder/ReadOnlyFrame.tsx +5 -49
  17. package/components/builder/SectionV2Canvas.tsx +2 -2
  18. package/components/builder/SectionV2Column.tsx +5 -5
  19. package/components/builder/SettingsPanel.tsx +0 -12
  20. package/components/builder/SortableBlock.tsx +3 -3
  21. package/components/builder/SortableRow.tsx +6 -27
  22. package/components/builder/editors/ButtonBlockEditor.tsx +8 -3
  23. package/components/builder/editors/CoverBlockEditor.tsx +14 -6
  24. package/components/builder/editors/ImageBlockEditor.tsx +8 -3
  25. package/components/builder/editors/ImageGridBlockEditor.tsx +8 -3
  26. package/components/builder/editors/ProjectGridEditor.tsx +7 -46
  27. package/components/builder/editors/SpacerBlockEditor.tsx +4 -1
  28. package/components/builder/editors/StaggerSettings.tsx +2 -1
  29. package/components/builder/editors/TextBlockEditor.tsx +8 -3
  30. package/components/builder/editors/VideoBlockEditor.tsx +10 -4
  31. package/components/builder/editors/section-icons.tsx +492 -0
  32. package/components/builder/editors/shared.tsx +23 -4
  33. package/components/builder/live-preview/LiveTextEditor.tsx +1 -1
  34. package/components/builder/live-preview/ProjectCardWrapper.tsx +3 -3
  35. package/components/builder/live-preview/drag-utils.tsx +2 -2
  36. package/components/builder/settings-panel/AnimationTab.tsx +2 -16
  37. package/components/builder/settings-panel/BlockLayoutTab.tsx +13 -58
  38. package/components/builder/settings-panel/ColumnV2Settings.tsx +4 -1
  39. package/components/builder/settings-panel/PageSettings.tsx +10 -4
  40. package/components/builder/settings-panel/ParallaxGroupSettings.tsx +6 -2
  41. package/components/builder/settings-panel/ParallaxSlideSettings.tsx +8 -3
  42. package/components/builder/settings-panel/SectionV2LayoutTab.tsx +11 -47
  43. package/components/builder/settings-panel/SectionV2Settings.tsx +6 -27
  44. package/components/builder/settings-panel/index.ts +0 -1
  45. package/components/builder/settings-panel/responsive-helpers.ts +2 -50
  46. package/components/builder/settings-panel/useSettingsPanelSelection.ts +1 -16
  47. package/components/ui/Navbar.tsx +151 -30
  48. package/lib/builder/constants.ts +5 -4
  49. package/lib/builder/serializer/normalizers.ts +2 -40
  50. package/lib/builder/serializer/serializers.ts +3 -74
  51. package/lib/builder/store-blocks.ts +3 -19
  52. package/lib/builder/store-helpers.ts +2 -2
  53. package/lib/builder/store-sections.ts +26 -64
  54. package/lib/builder/store.ts +3 -6
  55. package/lib/builder/templates.ts +9 -45
  56. package/lib/builder/types.ts +4 -11
  57. package/lib/sanity/queries.ts +6 -29
  58. package/lib/sanity/types.ts +24 -70
  59. package/package.json +4 -1
  60. package/sanity/schemas/index.ts +0 -5
  61. package/sanity/schemas/objects/parallaxGroup.ts +2 -2
  62. package/sanity/schemas/page.ts +1 -1
  63. package/sanity/schemas/pageSectionV2.ts +1 -0
  64. package/sanity/schemas/siteSettings.ts +42 -0
  65. package/styles/base.css +8 -2
  66. package/components/blocks/SectionRenderer.tsx +0 -171
  67. package/components/builder/settings-panel/LayoutTab.tsx +0 -382
  68. package/sanity/schemas/pageSection.ts +0 -157
@@ -145,59 +145,14 @@ function AlignmentButtons<T extends string>({
145
145
  );
146
146
  }
147
147
 
148
- // ── Section title icons (small, inline) ──
149
-
150
- function AlignmentSectionIcon() {
151
- return (
152
- <svg width={14} height={14} viewBox="0 0 14 14" fill="none">
153
- <rect x="1" y="2" width="9" height="2" rx="0.5" fill="currentColor" opacity="0.7" />
154
- <rect x="3" y="6" width="8" height="2" rx="0.5" fill="currentColor" opacity="0.5" />
155
- <rect x="2" y="10" width="10" height="2" rx="0.5" fill="currentColor" opacity="0.7" />
156
- </svg>
157
- );
158
- }
159
-
160
- function SpacingSectionIcon() {
161
- return (
162
- <svg width={14} height={14} viewBox="0 0 14 14" fill="none">
163
- <rect x="4" y="4" width="6" height="6" rx="1" stroke="currentColor" strokeWidth="1" fill="none" opacity="0.5" />
164
- <path d="M7 1 L7 3.5" stroke="currentColor" strokeWidth="0.8" opacity="0.7" />
165
- <path d="M7 10.5 L7 13" stroke="currentColor" strokeWidth="0.8" opacity="0.7" />
166
- <path d="M1 7 L3.5 7" stroke="currentColor" strokeWidth="0.8" opacity="0.7" />
167
- <path d="M10.5 7 L13 7" stroke="currentColor" strokeWidth="0.8" opacity="0.7" />
168
- </svg>
169
- );
170
- }
171
-
172
- function OffsetSectionIcon() {
173
- return (
174
- <svg width={14} height={14} viewBox="0 0 14 14" fill="none">
175
- <rect x="3" y="3" width="8" height="8" rx="1" stroke="currentColor" strokeWidth="0.8" strokeDasharray="2 1" fill="none" opacity="0.35" />
176
- <rect x="5" y="5" width="6" height="6" rx="1" stroke="currentColor" strokeWidth="1" fill="none" opacity="0.7" />
177
- <path d="M4 4 L5 5" stroke="currentColor" strokeWidth="0.6" opacity="0.5" />
178
- </svg>
179
- );
180
- }
181
-
182
- function BackgroundSectionIcon() {
183
- return (
184
- <svg width={14} height={14} viewBox="0 0 14 14" fill="none">
185
- <rect x="1.5" y="1.5" width="11" height="11" rx="2" fill="currentColor" opacity="0.15" />
186
- <rect x="1.5" y="1.5" width="11" height="11" rx="2" stroke="currentColor" strokeWidth="0.8" opacity="0.5" fill="none" />
187
- <circle cx="5" cy="5" r="1.5" fill="currentColor" opacity="0.5" />
188
- <path d="M1.5 10 L5 7 L8 9 L10.5 6.5 L12.5 8.5 L12.5 11 C12.5 11.8 11.8 12.5 11 12.5 L3 12.5 C2.2 12.5 1.5 11.8 1.5 11 Z" fill="currentColor" opacity="0.3" />
189
- </svg>
190
- );
191
- }
192
-
193
- function BorderSectionIcon() {
194
- return (
195
- <svg width={14} height={14} viewBox="0 0 14 14" fill="none">
196
- <rect x="2" y="2" width="10" height="10" rx="2" stroke="currentColor" strokeWidth="1.2" fill="none" opacity="0.6" />
197
- <rect x="2" y="2" width="10" height="1.2" rx="0.5" fill="currentColor" opacity="0.7" />
198
- </svg>
199
- );
200
- }
148
+ // ── Section title icons (centralized colored icons — Session 163) ──
149
+ import {
150
+ AlignmentIcon,
151
+ SpacingIcon,
152
+ OffsetIcon,
153
+ BackgroundIcon,
154
+ BorderIcon,
155
+ } from "../editors/section-icons";
201
156
 
202
157
  // ── Override indicator badge ──
203
158
 
@@ -287,7 +242,7 @@ export function BlockLayoutTab({ block }: { block: ContentBlock }) {
287
242
  )}
288
243
 
289
244
  {/* Alignment */}
290
- <SettingsSection title="Alignment" defaultOpen icon={<AlignmentSectionIcon />}>
245
+ <SettingsSection title="Alignment" defaultOpen icon={<AlignmentIcon />}>
291
246
  <SettingsField label="Horizontal">
292
247
  <AlignmentButtons<AlignH>
293
248
  options={[
@@ -329,7 +284,7 @@ export function BlockLayoutTab({ block }: { block: ContentBlock }) {
329
284
  </SettingsSection>
330
285
 
331
286
  {/* Spacing (Padding) */}
332
- <SettingsSection title="Spacing" defaultOpen icon={<SpacingSectionIcon />}>
287
+ <SettingsSection title="Spacing" defaultOpen icon={<SpacingIcon />}>
333
288
  <TRBLInputs
334
289
  top={getBlockLayoutValue<string>(block, activeViewport, "spacing_top", "0")}
335
290
  right={getBlockLayoutValue<string>(block, activeViewport, "spacing_right", "0")}
@@ -348,7 +303,7 @@ export function BlockLayoutTab({ block }: { block: ContentBlock }) {
348
303
  </SettingsSection>
349
304
 
350
305
  {/* Offset (Margin) */}
351
- <SettingsSection title="Offset" icon={<OffsetSectionIcon />}>
306
+ <SettingsSection title="Offset" icon={<OffsetIcon />}>
352
307
  <TRBLInputs
353
308
  top={getBlockLayoutValue<string>(block, activeViewport, "offset_top", "0")}
354
309
  right={getBlockLayoutValue<string>(block, activeViewport, "offset_right", "0")}
@@ -367,7 +322,7 @@ export function BlockLayoutTab({ block }: { block: ContentBlock }) {
367
322
  </SettingsSection>
368
323
 
369
324
  {/* Background */}
370
- <SettingsSection title="Background" defaultOpen icon={<BackgroundSectionIcon />}>
325
+ <SettingsSection title="Background" defaultOpen icon={<BackgroundIcon />}>
371
326
  <SettingsField label="Color">
372
327
  <ColorSwatchPicker
373
328
  value={parseColorField(getBlockLayoutValue<string>(block, activeViewport, "background_color", ""))}
@@ -466,7 +421,7 @@ export function BlockLayoutTab({ block }: { block: ContentBlock }) {
466
421
  </SettingsSection>
467
422
 
468
423
  {/* Border */}
469
- <SettingsSection title="Border" icon={<BorderSectionIcon />}>
424
+ <SettingsSection title="Border" icon={<BorderIcon />}>
470
425
  <SettingsField label="Color">
471
426
  <ColorSwatchPicker
472
427
  value={parseColorField(getBlockLayoutValue<string>(block, activeViewport, "border_color", ""))}
@@ -16,6 +16,9 @@
16
16
 
17
17
  import { useBuilderStore } from "../../../lib/builder/store";
18
18
  import type { PageSectionV2, SectionColumn } from "../../../lib/sanity/types";
19
+ import {
20
+ ColumnSizeIcon,
21
+ } from "../editors/section-icons";
19
22
  import {
20
23
  SettingsField,
21
24
  SettingsSection,
@@ -90,7 +93,7 @@ export default function ColumnV2Settings({
90
93
  </div>
91
94
  )}
92
95
 
93
- <SettingsSection title="Column Size" defaultOpen>
96
+ <SettingsSection title="Column Size" defaultOpen icon={<ColumnSizeIcon />}>
94
97
  <SettingsField label={
95
98
  <span>
96
99
  Span
@@ -11,6 +11,12 @@
11
11
 
12
12
  import { useState } from "react";
13
13
  import { useBuilderStore } from "../../../lib/builder/store";
14
+ import {
15
+ GeneralIcon,
16
+ AppearanceIcon,
17
+ NavigationIcon,
18
+ SEOIcon,
19
+ } from "../editors/section-icons";
14
20
  import {
15
21
  SettingsField,
16
22
  SettingsSection,
@@ -39,7 +45,7 @@ export default function PageSettings() {
39
45
 
40
46
  return (
41
47
  <>
42
- <SettingsSection title="General" defaultOpen>
48
+ <SettingsSection title="General" defaultOpen icon={<GeneralIcon />}>
43
49
  <SettingsField label="Title">
44
50
  <input
45
51
  type="text"
@@ -73,7 +79,7 @@ export default function PageSettings() {
73
79
  </SettingsField>
74
80
  </SettingsSection>
75
81
 
76
- <SettingsSection title="Appearance" defaultOpen>
82
+ <SettingsSection title="Appearance" defaultOpen icon={<AppearanceIcon />}>
77
83
  <SettingsField label="Background">
78
84
  <ColorSwatchPicker
79
85
  value={parseColorField(store.pageSettings.background_color || "")}
@@ -91,7 +97,7 @@ export default function PageSettings() {
91
97
  </SettingsField>
92
98
  </SettingsSection>
93
99
 
94
- <SettingsSection title="Navigation">
100
+ <SettingsSection title="Navigation" icon={<NavigationIcon />}>
95
101
  <SettingsField label="Nav Color">
96
102
  <ColorSwatchPicker
97
103
  value={store.pageSettings.nav_color || ""}
@@ -164,7 +170,7 @@ export function PageSeoSettings() {
164
170
 
165
171
  return (
166
172
  <>
167
- <SettingsSection title="SEO" defaultOpen>
173
+ <SettingsSection title="SEO" defaultOpen icon={<SEOIcon />}>
168
174
  <SettingsField label="SEO Title">
169
175
  <input
170
176
  type="text"
@@ -14,6 +14,10 @@
14
14
 
15
15
  import { useBuilderStore } from "../../../lib/builder/store";
16
16
  import type { ParallaxGroup } from "../../../lib/sanity/types";
17
+ import {
18
+ TransitionIcon,
19
+ InfoIcon,
20
+ } from "../editors/section-icons";
17
21
  import {
18
22
  SettingsSection,
19
23
  } from "../editors/shared";
@@ -56,7 +60,7 @@ export default function ParallaxGroupSettings({
56
60
 
57
61
  return (
58
62
  <>
59
- <SettingsSection title="Transition Effect" defaultOpen>
63
+ <SettingsSection title="Transition Effect" defaultOpen icon={<TransitionIcon />}>
60
64
  <div className="space-y-1.5">
61
65
  {TRANSITION_EFFECTS.map((effect) => {
62
66
  const isActive = activeEffect === effect.value;
@@ -103,7 +107,7 @@ export default function ParallaxGroupSettings({
103
107
  </SettingsSection>
104
108
 
105
109
  {/* Group info */}
106
- <SettingsSection title="Info">
110
+ <SettingsSection title="Info" icon={<InfoIcon />}>
107
111
  <div className="text-[11px] text-neutral-500 space-y-1">
108
112
  <p>
109
113
  {group.slides.length} slide{group.slides.length !== 1 ? "s" : ""}
@@ -19,6 +19,11 @@
19
19
 
20
20
  import { useBuilderStore } from "../../../lib/builder/store";
21
21
  import type { ParallaxSlideV2, ParallaxGroup, PageSectionV2 } from "../../../lib/sanity/types";
22
+ import {
23
+ BackgroundIcon,
24
+ NavbarColorIcon,
25
+ OverlayIcon,
26
+ } from "../editors/section-icons";
22
27
  import {
23
28
  SettingsField,
24
29
  SettingsSection,
@@ -70,7 +75,7 @@ export default function ParallaxSlideSettings({
70
75
  return (
71
76
  <>
72
77
  {/* Background Type */}
73
- <SettingsSection title="Background" defaultOpen>
78
+ <SettingsSection title="Background" defaultOpen icon={<BackgroundIcon />}>
74
79
  {/* Segmented control: Image / Video */}
75
80
  <SettingsField label="Type">
76
81
  <div className="flex rounded-lg bg-[#f0f0f0] p-[3px]">
@@ -123,7 +128,7 @@ export default function ParallaxSlideSettings({
123
128
  </SettingsSection>
124
129
 
125
130
  {/* Navbar Color Override */}
126
- <SettingsSection title="Navbar Color" defaultOpen={false}>
131
+ <SettingsSection title="Navbar Color" defaultOpen={false} icon={<NavbarColorIcon />}>
127
132
  <SettingsField label="Color">
128
133
  <div className="flex items-center gap-2">
129
134
  <ColorSwatchPicker
@@ -147,7 +152,7 @@ export default function ParallaxSlideSettings({
147
152
  </SettingsSection>
148
153
 
149
154
  {/* Overlay */}
150
- <SettingsSection title="Overlay" defaultOpen>
155
+ <SettingsSection title="Overlay" defaultOpen icon={<OverlayIcon />}>
151
156
  <SettingsField label="Color">
152
157
  <ColorSwatchPicker
153
158
  value={overlayColor}
@@ -25,49 +25,13 @@ import ColorSwatchPicker, { usePaletteSwatches } from "../ColorSwatchPicker";
25
25
  import { serializeColorField, parseColorField, isGradient } from "../../../lib/color-utils";
26
26
  import { TRBLInputs } from "./TRBLInputs";
27
27
 
28
- // ── Section title icons (matching BlockLayoutTab) ──
29
-
30
- function SpacingSectionIcon() {
31
- return (
32
- <svg width={14} height={14} viewBox="0 0 14 14" fill="none">
33
- <rect x="4" y="4" width="6" height="6" rx="1" stroke="currentColor" strokeWidth="1" fill="none" opacity="0.5" />
34
- <path d="M7 1 L7 3.5" stroke="currentColor" strokeWidth="0.8" opacity="0.7" />
35
- <path d="M7 10.5 L7 13" stroke="currentColor" strokeWidth="0.8" opacity="0.7" />
36
- <path d="M1 7 L3.5 7" stroke="currentColor" strokeWidth="0.8" opacity="0.7" />
37
- <path d="M10.5 7 L13 7" stroke="currentColor" strokeWidth="0.8" opacity="0.7" />
38
- </svg>
39
- );
40
- }
41
-
42
- function BackgroundSectionIcon() {
43
- return (
44
- <svg width={14} height={14} viewBox="0 0 14 14" fill="none">
45
- <rect x="1.5" y="1.5" width="11" height="11" rx="2" fill="currentColor" opacity="0.15" />
46
- <rect x="1.5" y="1.5" width="11" height="11" rx="2" stroke="currentColor" strokeWidth="0.8" opacity="0.5" fill="none" />
47
- <circle cx="5" cy="5" r="1.5" fill="currentColor" opacity="0.5" />
48
- <path d="M1.5 10 L5 7 L8 9 L10.5 6.5 L12.5 8.5 L12.5 11 C12.5 11.8 11.8 12.5 11 12.5 L3 12.5 C2.2 12.5 1.5 11.8 1.5 11 Z" fill="currentColor" opacity="0.3" />
49
- </svg>
50
- );
51
- }
52
-
53
- function OffsetSectionIcon() {
54
- return (
55
- <svg width={14} height={14} viewBox="0 0 14 14" fill="none">
56
- <rect x="3" y="3" width="8" height="8" rx="1" stroke="currentColor" strokeWidth="0.8" strokeDasharray="2 1" fill="none" opacity="0.35" />
57
- <rect x="5" y="5" width="6" height="6" rx="1" stroke="currentColor" strokeWidth="1" fill="none" opacity="0.7" />
58
- <path d="M4 4 L5 5" stroke="currentColor" strokeWidth="0.6" opacity="0.5" />
59
- </svg>
60
- );
61
- }
62
-
63
- function BorderSectionIcon() {
64
- return (
65
- <svg width={14} height={14} viewBox="0 0 14 14" fill="none">
66
- <rect x="2" y="2" width="10" height="10" rx="2" stroke="currentColor" strokeWidth="1.2" fill="none" opacity="0.6" />
67
- <rect x="2" y="2" width="10" height="1.2" rx="0.5" fill="currentColor" opacity="0.7" />
68
- </svg>
69
- );
70
- }
28
+ // ── Section title icons (centralized colored icons — Session 163) ──
29
+ import {
30
+ SpacingIcon,
31
+ OffsetIcon,
32
+ BackgroundIcon,
33
+ BorderIcon,
34
+ } from "../editors/section-icons";
71
35
 
72
36
  // ── Override indicator badge (matching BlockLayoutTab pattern) ──
73
37
 
@@ -179,7 +143,7 @@ export function SectionV2LayoutTab({ section }: { section: PageSectionV2 }) {
179
143
  )}
180
144
 
181
145
  {/* Spacing (Padding) */}
182
- <SettingsSection title="Spacing" defaultOpen icon={<SpacingSectionIcon />}>
146
+ <SettingsSection title="Spacing" defaultOpen icon={<SpacingIcon />}>
183
147
  <TRBLInputs
184
148
  top={getSettingValue<string>("spacing_top", "0")}
185
149
  right={getSettingValue<string>("spacing_right", "0")}
@@ -197,7 +161,7 @@ export function SectionV2LayoutTab({ section }: { section: PageSectionV2 }) {
197
161
  </SettingsSection>
198
162
 
199
163
  {/* Offset (Margin) */}
200
- <SettingsSection title="Offset" icon={<OffsetSectionIcon />}>
164
+ <SettingsSection title="Offset" icon={<OffsetIcon />}>
201
165
  <TRBLInputs
202
166
  top={getSettingValue<string>("offset_top", "0")}
203
167
  right={getSettingValue<string>("offset_right", "0")}
@@ -215,7 +179,7 @@ export function SectionV2LayoutTab({ section }: { section: PageSectionV2 }) {
215
179
  </SettingsSection>
216
180
 
217
181
  {/* Background */}
218
- <SettingsSection title="Background" defaultOpen icon={<BackgroundSectionIcon />}>
182
+ <SettingsSection title="Background" defaultOpen icon={<BackgroundIcon />}>
219
183
  <SettingsField label="Color">
220
184
  <ColorSwatchPicker
221
185
  value={parseColorField(getSettingValue<string>("background_color", ""))}
@@ -309,7 +273,7 @@ export function SectionV2LayoutTab({ section }: { section: PageSectionV2 }) {
309
273
  </SettingsSection>
310
274
 
311
275
  {/* Border */}
312
- <SettingsSection title="Border" icon={<BorderSectionIcon />}>
276
+ <SettingsSection title="Border" icon={<BorderIcon />}>
313
277
  <SettingsField label="Color">
314
278
  <ColorSwatchPicker
315
279
  value={parseColorField(getSettingValue<string>("border_color", ""))}
@@ -50,32 +50,11 @@ const PRESETS: PresetOption[] = [
50
50
 
51
51
  const CUSTOM_PRESET: PresetOption = { id: "custom", label: "Custom", cols: [], readonly: true };
52
52
 
53
- // ============================================
54
- // Section title icons (small, inline)
55
- // ============================================
56
-
57
- function LayoutPresetIcon() {
58
- return (
59
- <svg width={14} height={14} viewBox="0 0 14 14" fill="none">
60
- <rect x="1.5" y="1.5" width="11" height="11" rx="1.5" stroke="currentColor" strokeWidth="0.8" fill="none" opacity="0.4" />
61
- <line x1="6" y1="1.5" x2="6" y2="12.5" stroke="currentColor" strokeWidth="0.8" opacity="0.6" />
62
- <rect x="1.5" y="1.5" width="4.5" height="11" rx="0" fill="currentColor" opacity="0.12" />
63
- </svg>
64
- );
65
- }
66
-
67
- function GridGapIcon() {
68
- return (
69
- <svg width={14} height={14} viewBox="0 0 14 14" fill="none">
70
- <rect x="1" y="1" width="5" height="5" rx="1" fill="currentColor" opacity="0.25" />
71
- <rect x="8" y="1" width="5" height="5" rx="1" fill="currentColor" opacity="0.25" />
72
- <rect x="1" y="8" width="5" height="5" rx="1" fill="currentColor" opacity="0.25" />
73
- <rect x="8" y="8" width="5" height="5" rx="1" fill="currentColor" opacity="0.25" />
74
- <line x1="7" y1="1" x2="7" y2="13" stroke="currentColor" strokeWidth="0.8" strokeDasharray="1.5 1" opacity="0.5" />
75
- <line x1="1" y1="7" x2="13" y2="7" stroke="currentColor" strokeWidth="0.8" strokeDasharray="1.5 1" opacity="0.5" />
76
- </svg>
77
- );
78
- }
53
+ // ── Section title icons (centralized colored icons — Session 163) ──
54
+ import {
55
+ LayoutPresetIcon,
56
+ GridGapsIcon,
57
+ } from "../editors/section-icons";
79
58
 
80
59
  // ============================================
81
60
  // Preset Grid Component
@@ -278,7 +257,7 @@ export default function SectionV2Settings({ section }: { section: PageSectionV2
278
257
  )}
279
258
 
280
259
  {/* Gaps */}
281
- <SettingsSection title="Grid Gaps" defaultOpen icon={<GridGapIcon />}>
260
+ <SettingsSection title="Grid Gaps" defaultOpen icon={<GridGapsIcon />}>
282
261
  <SettingsField label={
283
262
  <span>
284
263
  Col Gap
@@ -6,7 +6,6 @@
6
6
  * RowLayoutPresetPicker, TRBLInputs.
7
7
  */
8
8
 
9
- export { LayoutTab } from "./LayoutTab";
10
9
  export { BlockLayoutTab } from "./BlockLayoutTab";
11
10
  export { TRBLInputs } from "./TRBLInputs";
12
11
  export { default as PageSettings, PageSeoSettings } from "./PageSettings";
@@ -1,60 +1,12 @@
1
1
  /**
2
- * Responsive helpers for section setting resolution.
2
+ * Responsive helpers for setting resolution.
3
3
  *
4
4
  * Session 64: Extracted from SettingsPanel.tsx.
5
- * Session 86: Removed V1 Row/Column types now uses generic interface
6
- * compatible with PageSection (settings + responsive shape).
5
+ * Session 166: Removed V1 PageSection helpers (getRowSettingValue, hasRowSettingOverride, setRowResponsiveOverride).
7
6
  */
8
7
 
9
- import type { PageSection } from "../../../lib/sanity/types";
10
8
  import type { DeviceViewport } from "../../../lib/builder/types";
11
9
 
12
- /**
13
- * Generic shape for items with settings + responsive overrides.
14
- * Compatible with PageSection (and formerly Row).
15
- * Uses `unknown` to accept any settings interface without index signature issues.
16
- */
17
- type SettingsItem = {
18
- settings?: unknown;
19
- responsive?: Record<string, Record<string, unknown>>;
20
- };
21
-
22
- /** Get effective value for a section setting, checking viewport overrides */
23
- export function getRowSettingValue<T>(item: SettingsItem, viewport: DeviceViewport, property: string, fallback: T): T {
24
- if (viewport === "desktop") {
25
- const val = (item.settings as Record<string, unknown> || {})[property];
26
- return (val !== undefined ? val : fallback) as T;
27
- }
28
- const override = item.responsive?.[viewport]?.[property];
29
- if (override !== undefined) return override as T;
30
- const base = (item.settings as Record<string, unknown> || {})[property];
31
- return (base !== undefined ? base : fallback) as T;
32
- }
33
-
34
- /** Check if a section setting has a responsive override */
35
- export function hasRowSettingOverride(item: SettingsItem, viewport: DeviceViewport, property: string): boolean {
36
- if (viewport === "desktop") return false;
37
- return item.responsive?.[viewport]?.[property] !== undefined;
38
- }
39
-
40
- /** Set a responsive override on a section setting, returning the updated fields */
41
- export function setRowResponsiveOverride(item: SettingsItem, viewport: DeviceViewport, property: string, value: unknown): Partial<PageSection> {
42
- if (viewport === "desktop") {
43
- return { settings: { ...(item.settings as Record<string, unknown> || {}), [property]: value } } as Partial<PageSection>;
44
- }
45
- const existing = item.responsive || {};
46
- const vp = viewport as "tablet" | "phone";
47
- const vpOverrides = { ...(existing[vp] || {}), [property]: value };
48
- if (value === undefined) {
49
- delete (vpOverrides as Record<string, unknown>)[property];
50
- }
51
- const responsive = { ...existing, [vp]: vpOverrides };
52
- if (Object.keys(vpOverrides).length === 0) {
53
- delete responsive[vp];
54
- }
55
- return { responsive: Object.keys(responsive).length ? responsive : undefined } as Partial<PageSection>;
56
- }
57
-
58
10
  // ============================================
59
11
  // Block Layout responsive helpers
60
12
  // ============================================
@@ -11,7 +11,6 @@ import { BLOCK_GRADIENTS, BLOCK_ICON_COMPONENTS } from "../blockStyles";
11
11
  import type {
12
12
  ContentBlock,
13
13
  ContentItem,
14
- PageSection,
15
14
  PageSectionV2,
16
15
  CustomSectionInstance,
17
16
  ParallaxGroup,
@@ -19,7 +18,6 @@ import type {
19
18
  SectionColumn,
20
19
  } from "../../../lib/sanity/types";
21
20
  import {
22
- isPageSection,
23
21
  isPageSectionV2,
24
22
  isCustomSectionInstance,
25
23
  isParallaxGroup,
@@ -43,7 +41,6 @@ export function useSettingsPanelSelection() {
43
41
 
44
42
  // Find selected elements — handle page sections, V2 sections, and parallax groups/slides
45
43
  const selectedItem: ContentItem | undefined = store.rows.find((r) => r._key === store.selectedRowKey);
46
- const selectedSection: PageSection | null = selectedItem && isPageSection(selectedItem) ? selectedItem : null;
47
44
  const selectedSectionV2: PageSectionV2 | null = selectedItem && isPageSectionV2(selectedItem) ? selectedItem : null;
48
45
  const selectedCustomSectionInstance: CustomSectionInstance | null = selectedItem && isCustomSectionInstance(selectedItem) ? selectedItem as CustomSectionInstance : null;
49
46
 
@@ -76,15 +73,8 @@ export function useSettingsPanelSelection() {
76
73
  ? effectiveSectionV2.columns.find((c) => c._key === store.selectedColumnKey) || null
77
74
  : null;
78
75
 
79
- // For PageSections, the "block" is section.block[0] — selected automatically
80
76
  const selectedBlock: SelectedBlockInfo | null = (() => {
81
- // If a PageSection is selected, its block is the section block
82
- if (selectedSection) {
83
- const block = selectedSection.block[0];
84
- if (block) return { block, rowKey: selectedSection._key, colKey: "", isSection: true };
85
- return null;
86
- }
87
- // Regular block search inside rows, V2 sections, and parallax slides
77
+ // Block search inside V2 sections and parallax slides
88
78
  if (!store.selectedBlockKey) return null;
89
79
  for (const item of store.rows) {
90
80
  // V2 sections: search inside columns
@@ -130,8 +120,6 @@ export function useSettingsPanelSelection() {
130
120
  ? (selectedCustomSectionInstance.custom_section_title || "Saved Section")
131
121
  : selectedSectionV2
132
122
  ? "Section"
133
- : selectedSection
134
- ? (selectedSection.section_type === "projectGrid" ? "Project Grid" : "Parallax Section")
135
123
  : "Page";
136
124
 
137
125
  // Resolve gradient + icon component for the header
@@ -145,8 +133,6 @@ export function useSettingsPanelSelection() {
145
133
  ? "customSectionInstance"
146
134
  : selectedSectionV2
147
135
  ? "row"
148
- : selectedSection
149
- ? (selectedSection.block[0]?._type || "row")
150
136
  : "page";
151
137
  const headerGradient = BLOCK_GRADIENTS[headerStyleKey] || BLOCK_GRADIENTS.page;
152
138
  const HeaderIconComponent = BLOCK_ICON_COMPONENTS[headerStyleKey];
@@ -163,7 +149,6 @@ export function useSettingsPanelSelection() {
163
149
 
164
150
  return {
165
151
  selectedItem,
166
- selectedSection,
167
152
  selectedSectionV2,
168
153
  selectedCustomSectionInstance,
169
154
  selectedParallaxGroup,