@morphika/andami 0.2.11 → 0.2.13

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 (49) hide show
  1. package/README.md +2 -1
  2. package/app/admin/pages/[slug]/page.tsx +39 -2
  3. package/components/blocks/BlockRenderer.tsx +0 -7
  4. package/components/blocks/CoverSectionRenderer.tsx +295 -0
  5. package/components/blocks/PageRenderer.tsx +13 -9
  6. package/components/builder/BlockLivePreview.tsx +0 -5
  7. package/components/builder/BlockTypePicker.tsx +0 -1
  8. package/components/builder/ColorSwatchPicker.tsx +2 -2
  9. package/components/builder/CoverRowResizeHandle.tsx +180 -0
  10. package/components/builder/CoverSectionCanvas.tsx +260 -0
  11. package/components/builder/ReadOnlyFrame.tsx +127 -3
  12. package/components/builder/SectionTypePicker.tsx +29 -0
  13. package/components/builder/SectionV2Canvas.tsx +4 -1
  14. package/components/builder/SectionV2Column.tsx +15 -20
  15. package/components/builder/SettingsPanel.tsx +14 -0
  16. package/components/builder/SortableRow.tsx +7 -21
  17. package/components/builder/blockStyles.tsx +13 -14
  18. package/components/builder/editors/index.ts +0 -1
  19. package/components/builder/index.ts +1 -0
  20. package/components/builder/live-preview/RichTextEditor.tsx +23 -2
  21. package/components/builder/live-preview/index.ts +0 -1
  22. package/components/builder/settings-panel/BlockSettings.tsx +0 -7
  23. package/components/builder/settings-panel/CoverSectionSettings.tsx +296 -0
  24. package/components/builder/settings-panel/index.ts +1 -0
  25. package/components/builder/settings-panel/useSettingsPanelSelection.ts +36 -2
  26. package/lib/animation/enter-types.ts +0 -1
  27. package/lib/animation/hover-effect-types.ts +0 -1
  28. package/lib/builder/defaults.ts +43 -22
  29. package/lib/builder/serializer/normalizers.ts +34 -1
  30. package/lib/builder/serializer/serializers.ts +39 -2
  31. package/lib/builder/store-blocks.ts +11 -3
  32. package/lib/builder/store-cover.ts +220 -0
  33. package/lib/builder/store-helpers.ts +81 -4
  34. package/lib/builder/store-sections.ts +12 -2
  35. package/lib/builder/store.ts +11 -2
  36. package/lib/builder/types.ts +15 -2
  37. package/lib/sanity/types.ts +79 -43
  38. package/lib/version.ts +1 -1
  39. package/package.json +1 -1
  40. package/sanity/schemas/blocks/index.ts +1 -2
  41. package/sanity/schemas/index.ts +5 -3
  42. package/sanity/schemas/objects/coverSection.ts +317 -0
  43. package/sanity/schemas/objects/parallaxSlide.ts +0 -1
  44. package/sanity/schemas/page.ts +1 -1
  45. package/sanity/schemas/pageSectionV2.ts +0 -1
  46. package/components/blocks/CoverBlockRenderer.tsx +0 -261
  47. package/components/builder/editors/CoverBlockEditor.tsx +0 -550
  48. package/components/builder/live-preview/LiveCoverPreview.tsx +0 -146
  49. package/sanity/schemas/blocks/coverBlock.ts +0 -229
@@ -15,8 +15,9 @@ import type {
15
15
  ParallaxSlideV2,
16
16
  SectionColumn,
17
17
  SectionV2Preset,
18
+ CoverSection,
18
19
  } from "../../lib/sanity/types";
19
- import { isPageSectionV2, isParallaxGroup } from "../../lib/sanity/types";
20
+ import { isPageSectionV2, isParallaxGroup, isCoverSection } from "../../lib/sanity/types";
20
21
  import { columnsFromPreset, detectPreset } from "./cascade";
21
22
  import { resizeColumnLeft as cascadeResizeLeft, moveColumn as cascadeMoveColumn, type ResizeLeftResult } from "./cascade";
22
23
  import { applyBlocksToColumns, toCascadeColumns, type CascadeColumn } from "./cascade-helpers";
@@ -74,6 +75,14 @@ export function moveBlockInState(
74
75
  );
75
76
  break;
76
77
  }
78
+ } else if (isCoverSection(item)) {
79
+ const updatedCols = removeFromColumns((item as CoverSection).columns);
80
+ if (movedBlock) {
81
+ rowsAfterRemove = rows.map((r, idx) =>
82
+ idx === i ? { ...r, columns: updatedCols } as ContentItem : r
83
+ );
84
+ break;
85
+ }
77
86
  } else if (isParallaxGroup(item)) {
78
87
  const group = item as ParallaxGroup;
79
88
  let foundInSlide = false;
@@ -217,8 +226,8 @@ export function addSectionV2InState(
217
226
  grid_columns: gridColumns,
218
227
  col_gap: 20,
219
228
  row_gap: 20,
220
- spacing_top: "32",
221
- spacing_bottom: "32",
229
+ spacing_top: "0",
230
+ spacing_bottom: "0",
222
231
  },
223
232
  };
224
233
 
@@ -369,7 +378,8 @@ export function moveColumnToGapV2InState(
369
378
 
370
379
  export type SectionPath =
371
380
  | { type: "v2"; index: number }
372
- | { type: "parallaxSlide"; groupIndex: number; slideIndex: number };
381
+ | { type: "parallaxSlide"; groupIndex: number; slideIndex: number }
382
+ | { type: "cover"; index: number };
373
383
 
374
384
  /**
375
385
  * Find a V2 section by key — searches both top-level PageSectionV2
@@ -388,6 +398,9 @@ export function findSectionPath(
388
398
  if (item._key === sectionKey && isPageSectionV2(item)) {
389
399
  return { type: "v2", index: i };
390
400
  }
401
+ if (item._key === sectionKey && isCoverSection(item)) {
402
+ return { type: "cover", index: i };
403
+ }
391
404
  if (isParallaxGroup(item)) {
392
405
  const group = item as ParallaxGroup;
393
406
  for (let j = 0; j < group.slides.length; j++) {
@@ -412,6 +425,29 @@ export function getSectionFromPath(
412
425
  const item = rows[path.index];
413
426
  return isPageSectionV2(item) ? (item as PageSectionV2) : null;
414
427
  }
428
+ if (path.type === "cover") {
429
+ const item = rows[path.index];
430
+ if (!isCoverSection(item)) return null;
431
+ const cover = item as CoverSection;
432
+ return {
433
+ _type: "pageSectionV2",
434
+ _key: cover._key,
435
+ section_type: "empty-v2",
436
+ columns: cover.columns,
437
+ settings: {
438
+ preset: "custom",
439
+ grid_columns: cover.settings.grid_columns,
440
+ col_gap: cover.settings.col_gap,
441
+ row_gap: cover.settings.row_gap,
442
+ spacing_top: cover.settings.spacing_top,
443
+ spacing_right: cover.settings.spacing_right,
444
+ spacing_bottom: cover.settings.spacing_bottom,
445
+ spacing_left: cover.settings.spacing_left,
446
+ enter_animation: cover.settings.enter_animation,
447
+ stagger: cover.settings.stagger,
448
+ },
449
+ };
450
+ }
415
451
  const group = rows[path.groupIndex];
416
452
  if (!isParallaxGroup(group)) return null;
417
453
  const slide = (group as ParallaxGroup).slides[path.slideIndex];
@@ -440,6 +476,47 @@ export function updateSectionAtPath(
440
476
  return updater(item as PageSectionV2) as ContentItem;
441
477
  });
442
478
  }
479
+ if (path.type === "cover") {
480
+ return rows.map((item, i) => {
481
+ if (i !== path.index || !isCoverSection(item)) return item;
482
+ const cover = item as CoverSection;
483
+ const virtualSection: PageSectionV2 = {
484
+ _type: "pageSectionV2",
485
+ _key: cover._key,
486
+ section_type: "empty-v2",
487
+ columns: cover.columns,
488
+ settings: {
489
+ preset: "custom",
490
+ grid_columns: cover.settings.grid_columns,
491
+ col_gap: cover.settings.col_gap,
492
+ row_gap: cover.settings.row_gap,
493
+ spacing_top: cover.settings.spacing_top,
494
+ spacing_right: cover.settings.spacing_right,
495
+ spacing_bottom: cover.settings.spacing_bottom,
496
+ spacing_left: cover.settings.spacing_left,
497
+ enter_animation: cover.settings.enter_animation,
498
+ stagger: cover.settings.stagger,
499
+ },
500
+ };
501
+ const updated = updater(virtualSection);
502
+ return {
503
+ ...cover,
504
+ columns: updated.columns,
505
+ settings: {
506
+ ...cover.settings,
507
+ grid_columns: updated.settings.grid_columns,
508
+ col_gap: updated.settings.col_gap,
509
+ row_gap: updated.settings.row_gap,
510
+ spacing_top: updated.settings.spacing_top,
511
+ spacing_right: updated.settings.spacing_right,
512
+ spacing_bottom: updated.settings.spacing_bottom,
513
+ spacing_left: updated.settings.spacing_left,
514
+ enter_animation: updated.settings.enter_animation,
515
+ stagger: updated.settings.stagger,
516
+ },
517
+ } as ContentItem;
518
+ });
519
+ }
443
520
  // parallaxSlide path
444
521
  return rows.map((item, i) => {
445
522
  if (i !== path.groupIndex || !isParallaxGroup(item)) return item;
@@ -7,6 +7,7 @@ import type {
7
7
  CustomSectionInstance,
8
8
  ParallaxGroup,
9
9
  ParallaxSlideV2,
10
+ CoverSection,
10
11
  SectionV2Preset,
11
12
  EnterAnimationConfig,
12
13
  } from "../../lib/sanity/types";
@@ -14,6 +15,7 @@ import {
14
15
  isPageSectionV2,
15
16
  isCustomSectionInstance,
16
17
  isParallaxGroup,
18
+ isCoverSection,
17
19
  } from "../../lib/sanity/types";
18
20
  import { createDefaultBlock, createDefaultParallaxSlide } from "./defaults";
19
21
  import { generateKey } from "./utils";
@@ -78,8 +80,8 @@ export function createSectionActions(set: StoreSet, get: StoreGet) {
78
80
  grid_columns: gridColumns,
79
81
  col_gap: 20,
80
82
  row_gap: 20,
81
- spacing_top: "32",
82
- spacing_bottom: "32",
83
+ spacing_top: "0",
84
+ spacing_bottom: "0",
83
85
  },
84
86
  };
85
87
 
@@ -141,6 +143,14 @@ export function createSectionActions(set: StoreSet, get: StoreGet) {
141
143
  blocks: col.blocks.map((b) => ({ ...b, _key: generateKey() })),
142
144
  })
143
145
  );
146
+ } else if (isCoverSection(clone)) {
147
+ const cover = clone as CoverSection;
148
+ cover.cover_rows = cover.cover_rows.map((r) => ({ ...r, _key: generateKey() }));
149
+ cover.columns = cover.columns.map((col) => ({
150
+ ...col,
151
+ _key: generateKey(),
152
+ blocks: col.blocks.map((b) => ({ ...b, _key: generateKey() })),
153
+ }));
144
154
  } else if (isParallaxGroup(clone)) {
145
155
  const group = clone as ParallaxGroup;
146
156
  group.slides = group.slides.map((slide) => ({
@@ -3,8 +3,8 @@ import type { BuilderStore, BuilderState, BlockType, PageSettings, CanvasTool, D
3
3
  import { DEFAULT_PAGE_SETTINGS, DEFAULT_GRID_SETTINGS, DEVICE_WIDTHS } from "./types";
4
4
  import { stateToDocument, documentToState } from "./serializer";
5
5
  import { generateKey } from "./utils";
6
- import type { ContentBlock, ContentItem, PageSectionV2, SectionV2Settings, PageMetadata, CustomSectionInstance, ParallaxGroup, ParallaxSlideV2 } from "../../lib/sanity/types";
7
- import { isPageSectionV2, isCustomSectionInstance, isParallaxGroup } from "../../lib/sanity/types";
6
+ import type { ContentBlock, ContentItem, PageSectionV2, SectionV2Settings, PageMetadata, CustomSectionInstance, ParallaxGroup, ParallaxSlideV2, CoverSection } from "../../lib/sanity/types";
7
+ import { isPageSectionV2, isCustomSectionInstance, isParallaxGroup, isCoverSection } from "../../lib/sanity/types";
8
8
  import { createDefaultBlock, createDefaultParallaxSlide } from "./defaults";
9
9
  import { MAX_HISTORY, pushSnapshot } from "./history";
10
10
  import {
@@ -33,6 +33,7 @@ import { revalidateSite } from "../../lib/revalidate";
33
33
  import { createSectionActions } from "./store-sections";
34
34
  import { createBlockActions } from "./store-blocks";
35
35
  import { createCanvasActions } from "./store-canvas";
36
+ import { createCoverActions } from "./store-cover";
36
37
 
37
38
  // ============================================
38
39
  // RC-003 fix: Block parent key cache — O(1) lookup in selectBlock().
@@ -55,6 +56,13 @@ function getBlockParentCache(rows: ContentItem[]): Map<string, BlockParent> {
55
56
  cache.set(b._key, { rowKey: item._key, colKey: col._key });
56
57
  }
57
58
  }
59
+ } else if (isCoverSection(item)) {
60
+ const cover = item as CoverSection;
61
+ for (const col of cover.columns) {
62
+ for (const b of col.blocks) {
63
+ cache.set(b._key, { rowKey: item._key, colKey: col._key });
64
+ }
65
+ }
58
66
  } else if (isParallaxGroup(item)) {
59
67
  const group = item as ParallaxGroup;
60
68
  for (const slide of group.slides) {
@@ -346,4 +354,5 @@ export const useBuilderStore = create<BuilderStore>((set, get) => ({
346
354
  ...createSectionActions(set, get),
347
355
  ...createBlockActions(set, get),
348
356
  ...createCanvasActions(set, get),
357
+ ...createCoverActions(set, get),
349
358
  }));
@@ -15,6 +15,9 @@ import type {
15
15
  SectionColumn,
16
16
  PageMetadata,
17
17
  ColorField,
18
+ CoverSection,
19
+ CoverSectionSettings,
20
+ CoverRow,
18
21
  } from "../../lib/sanity/types";
19
22
  import { DEFAULT_BG_COLOR, DEFAULT_TEXT_COLOR, DEFAULT_GRID_WIDTH } from "./constants";
20
23
 
@@ -48,7 +51,6 @@ export const BLOCK_TYPE_REGISTRY: BlockTypeInfo[] = [
48
51
  { type: "videoBlock", label: "Video", description: "Vimeo, YouTube, or MP4", group: "generic", icon: "▶", category: "content" },
49
52
  { type: "spacerBlock", label: "Spacer", description: "Vertical spacing", group: "generic", icon: "↕", category: "content" },
50
53
  { type: "buttonBlock", label: "Button", description: "Call-to-action button", group: "generic", icon: "▣", category: "content" },
51
- { type: "coverBlock", label: "Cover", description: "Full-screen hero section", group: "generic", icon: "◈", category: "content" },
52
54
  ];
53
55
 
54
56
  /**
@@ -90,7 +92,7 @@ export function isSectionBlockSection(section: { columns?: Array<{ blocks?: Arra
90
92
  return blocks.length === 1 && SECTION_BLOCK_TYPES.has(blocks[0]._type);
91
93
  }
92
94
 
93
- export type SectionType = "empty-v2" | "parallaxGroup" | SectionBlockType;
95
+ export type SectionType = "empty-v2" | "parallaxGroup" | "coverSection" | SectionBlockType;
94
96
 
95
97
  export interface SectionTypeInfo {
96
98
  type: SectionType;
@@ -103,6 +105,7 @@ export interface SectionTypeInfo {
103
105
 
104
106
  export const SECTION_TYPE_REGISTRY: SectionTypeInfo[] = [
105
107
  { type: "empty-v2", label: "Empty Section", description: "Grid section with flexible columns", icon: "⊞" },
108
+ { type: "coverSection", label: "Cover Section", description: "Full-viewport section with background and proportional rows", icon: "◆" },
106
109
  { type: "projectGridBlock", label: "Project Grid", description: "Staggered project showcase grid", icon: "⬡", blockType: "projectGridBlock" },
107
110
  { type: "parallaxGroup", label: "Parallax Section", description: "Full-screen parallax showcase with V2 slides", icon: "▽" },
108
111
  ];
@@ -374,6 +377,16 @@ export interface BuilderActions {
374
377
  /** Update group-level settings (transition effect, snap, etc.) */
375
378
  updateParallaxGroupSettings: (groupKey: string, fields: Partial<Pick<import("../../lib/sanity/types").ParallaxGroup, "transition_effect" | "snap_enabled" | "parallax_intensity">>) => void;
376
379
 
380
+ // ---- Cover Section operations (Session 176) ----
381
+ addCoverSection: (afterRowKey?: string | null) => void;
382
+ addCoverRow: (sectionKey: string) => void;
383
+ removeCoverRow: (sectionKey: string, rowKey: string) => void;
384
+ resizeCoverRow: (sectionKey: string, handleIndex: number, deltaPercent: number, startAbove: number, startBelow: number) => void;
385
+ updateCoverRowAlign: (sectionKey: string, rowKey: string, align: CoverRow["vertical_align"]) => void;
386
+ updateCoverBackground: (sectionKey: string, fields: Partial<Pick<CoverSection, "background_type" | "background_image" | "background_video" | "background_position" | "background_size" | "background_overlay_color" | "background_overlay_opacity">>) => void;
387
+ updateCoverSettings: (sectionKey: string, settings: Partial<CoverSectionSettings>) => void;
388
+ updateCoverHeight: (sectionKey: string, height: CoverSection["height"]) => void;
389
+
377
390
  // Page-level settings
378
391
  updatePageSettings: (settings: Partial<PageSettings>) => void;
379
392
  applyGlobalStyles: () => Promise<void>;
@@ -210,47 +210,6 @@ export interface ButtonBlock {
210
210
  responsive?: ResponsiveOverrides<ButtonBlock>;
211
211
  }
212
212
 
213
- export interface CoverBlock {
214
- _type: "coverBlock";
215
- _key: string;
216
- // Content
217
- headline?: string;
218
- subheadline?: string;
219
- cta_button?: {
220
- text?: string;
221
- url?: string;
222
- target_blank?: boolean;
223
- style?: "primary" | "secondary" | "outline" | "text";
224
- };
225
- // Media
226
- media_type?: "image" | "video";
227
- media_path?: string;
228
- video_poster?: string;
229
- background_size?: "cover" | "contain" | "none";
230
- background_position?: string;
231
- background_repeat?: "no-repeat" | "repeat" | "repeat-x" | "repeat-y";
232
- // Overlay
233
- overlay?: "none" | "dark" | "light" | "gradient-bottom" | "gradient-top";
234
- overlay_opacity?: number;
235
- /** Custom overlay gradient (Phase 4). JSON-serialized ColorField.
236
- * When set, takes precedence over overlay + overlay_opacity. */
237
- overlay_gradient?: string;
238
- // Layout
239
- content_align_h?: "left" | "center" | "right";
240
- content_align_v?: "top" | "center" | "bottom";
241
- content_max_width?: string;
242
- height?: "100vh" | "80vh" | "60vh" | "40vh" | "custom";
243
- custom_height?: string;
244
- mobile_height?: "same" | "100vh" | "80vh" | "60vh" | "500px" | "400px";
245
- // Appearance
246
- text_color?: string;
247
- show_scroll_indicator?: boolean;
248
- enter_animation?: import("../../lib/animation/enter-types").EnterAnimationConfig;
249
- hover_effect?: import("../../lib/animation/hover-effect-types").HoverEffectConfig;
250
- layout?: BlockLayout;
251
- responsive?: ResponsiveOverrides<CoverBlock>;
252
- }
253
-
254
213
  // ============================================
255
214
  // Project Grid Block v2 (template-only, Session 105)
256
215
  // ============================================
@@ -477,11 +436,84 @@ export interface CustomSectionInstance {
477
436
  responsive_overrides?: PageSectionV2["responsive"];
478
437
  }
479
438
 
439
+ // ============================================
440
+ // Cover Section — proportional rows (Session 176)
441
+ // ============================================
442
+ // Full-viewport section with fixed-height rows and background media.
443
+ // Uses the same SectionColumn/block system as V2 but with explicit
444
+ // row heights (percentages) instead of content-driven auto rows.
445
+
446
+ export type CoverSectionHeight = "100vh" | "80vh" | "50vh";
447
+
448
+ /** A single proportional row within a Cover Section */
449
+ export interface CoverRow {
450
+ _key: string;
451
+ height_percent: number; // 5–95, all rows must sum to 100
452
+ vertical_align: "start" | "center" | "end";
453
+ }
454
+
455
+ /** Cover Section settings (subset of SectionV2Settings — no background/border) */
456
+ export interface CoverSectionSettings {
457
+ grid_columns: number; // default 12
458
+ col_gap: number;
459
+ row_gap: number;
460
+ spacing_top?: string;
461
+ spacing_right?: string;
462
+ spacing_bottom?: string;
463
+ spacing_left?: string;
464
+ enter_animation?: import("../../lib/animation/enter-types").EnterAnimationConfig;
465
+ stagger?: {
466
+ enabled?: boolean;
467
+ delayPerChild?: number;
468
+ direction?: "left-to-right" | "right-to-left";
469
+ };
470
+ }
471
+
472
+ /** Responsive override for Cover Sections */
473
+ export interface CoverSectionResponsiveOverride {
474
+ columns?: ColumnOverride[];
475
+ cover_rows?: Array<{ _key: string; height_percent?: number }>;
476
+ settings?: Partial<CoverSectionSettings>;
477
+ }
478
+
479
+ /** Cover Section — full-viewport section with background and proportional rows */
480
+ export interface CoverSection {
481
+ _type: "coverSection";
482
+ _key: string;
483
+
484
+ // Background
485
+ background_type: "image" | "video";
486
+ background_image?: string;
487
+ background_video?: string;
488
+ background_position?: string;
489
+ background_size?: "cover" | "contain" | "auto";
490
+ background_overlay_color?: string;
491
+ background_overlay_opacity?: number; // 0–100
492
+
493
+ // Height
494
+ height: CoverSectionHeight;
495
+
496
+ // Rows (explicit proportional heights)
497
+ cover_rows: CoverRow[];
498
+
499
+ // Columns (same as V2 — flat array with grid_row referencing cover_rows index)
500
+ columns: SectionColumn[];
501
+
502
+ // Settings
503
+ settings: CoverSectionSettings;
504
+
505
+ // Responsive
506
+ responsive?: {
507
+ tablet?: CoverSectionResponsiveOverride;
508
+ phone?: CoverSectionResponsiveOverride;
509
+ };
510
+ }
511
+
480
512
  // ============================================
481
513
  // Content Item — union of section types in content_rows
482
514
  // ============================================
483
515
 
484
- export type ContentItem = PageSectionV2 | CustomSectionInstance | ParallaxGroup;
516
+ export type ContentItem = PageSectionV2 | CustomSectionInstance | ParallaxGroup | CoverSection;
485
517
 
486
518
  /** Type guard: check if a content item is a PageSectionV2 */
487
519
  export function isPageSectionV2(item: ContentItem): item is PageSectionV2 {
@@ -498,6 +530,11 @@ export function isParallaxGroup(item: ContentItem): item is ParallaxGroup {
498
530
  return (item as ParallaxGroup)._type === "parallaxGroup";
499
531
  }
500
532
 
533
+ /** Type guard: check if a content item is a CoverSection (Session 176) */
534
+ export function isCoverSection(item: ContentItem): item is CoverSection {
535
+ return (item as CoverSection)._type === "coverSection";
536
+ }
537
+
501
538
  // ============================================
502
539
  // Shared references
503
540
  // ============================================
@@ -520,7 +557,6 @@ export type ContentBlock =
520
557
  | VideoBlock
521
558
  | SpacerBlock
522
559
  | ButtonBlock
523
- | CoverBlock
524
560
  | ProjectGridBlock;
525
561
 
526
562
  // ============================================
package/lib/version.ts CHANGED
@@ -6,4 +6,4 @@
6
6
  * Exposed as a plain constant so it can be imported without reading
7
7
  * package.json at runtime.
8
8
  */
9
- export const ANDAMI_VERSION = "0.2.11";
9
+ export const ANDAMI_VERSION = "0.2.13";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morphika/andami",
3
- "version": "0.2.11",
3
+ "version": "0.2.13",
4
4
  "description": "Visual Page Builder — core library. A reusable website builder with visual editing, CMS integration, and asset management.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,9 +1,8 @@
1
- // Block schemas (8)
1
+ // Block schemas (7)
2
2
  export { textBlock } from "./textBlock";
3
3
  export { imageBlock } from "./imageBlock";
4
4
  export { imageGridBlock } from "./imageGridBlock";
5
5
  export { videoBlock } from "./videoBlock";
6
6
  export { spacerBlock } from "./spacerBlock";
7
7
  export { buttonBlock } from "./buttonBlock";
8
- export { coverBlock } from "./coverBlock";
9
8
  export { projectGridBlock } from "./projectGridBlock";
@@ -10,6 +10,7 @@ import hoverEffectConfig from "./objects/hoverEffectConfig";
10
10
  import typewriterConfig from "./objects/typewriterConfig";
11
11
  import parallaxSlide from "./objects/parallaxSlide";
12
12
  import parallaxGroup from "./objects/parallaxGroup";
13
+ import coverSection from "./objects/coverSection";
13
14
  import {
14
15
  textBlock,
15
16
  imageBlock,
@@ -17,7 +18,6 @@ import {
17
18
  videoBlock,
18
19
  spacerBlock,
19
20
  buttonBlock,
20
- coverBlock,
21
21
  projectGridBlock,
22
22
  } from "./blocks";
23
23
 
@@ -58,6 +58,9 @@ export {
58
58
  export {
59
59
  default as parallaxGroup,
60
60
  } from "./objects/parallaxGroup";
61
+ export {
62
+ default as coverSection,
63
+ } from "./objects/coverSection";
61
64
  export {
62
65
  textBlock,
63
66
  imageBlock,
@@ -65,7 +68,6 @@ export {
65
68
  videoBlock,
66
69
  spacerBlock,
67
70
  buttonBlock,
68
- coverBlock,
69
71
  projectGridBlock,
70
72
  } from "./blocks";
71
73
 
@@ -87,6 +89,7 @@ export const schemaTypes = [
87
89
  typewriterConfig, // Typewriter config for textBlock (Session 117)
88
90
  parallaxSlide, // Parallax V2 slide (Session 123)
89
91
  parallaxGroup, // Parallax V2 group (Session 123)
92
+ coverSection, // Cover Section — proportional rows (Session 176)
90
93
 
91
94
  // Blocks (8)
92
95
  textBlock,
@@ -95,7 +98,6 @@ export const schemaTypes = [
95
98
  videoBlock,
96
99
  spacerBlock,
97
100
  buttonBlock,
98
- coverBlock,
99
101
  projectGridBlock,
100
102
  ];
101
103