@morphika/andami 0.1.7 → 0.1.9
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/README.md +3 -0
- package/app/(site)/[slug]/page.tsx +3 -2
- package/app/(site)/page.tsx +3 -2
- package/app/(site)/work/[slug]/page.tsx +3 -3
- package/app/robots.ts +38 -1
- package/components/builder/SettingsPanel.tsx +29 -543
- package/components/builder/live-preview/GhostCard.tsx +84 -0
- package/components/builder/live-preview/LiveProjectGridPreview.tsx +294 -1010
- package/components/builder/live-preview/ProjectCardWrapper.tsx +291 -0
- package/components/builder/live-preview/drag-utils.tsx +89 -0
- package/components/builder/live-preview/useDragReorder.ts +370 -0
- package/components/builder/settings-panel/AnimationTab.tsx +152 -0
- package/components/builder/settings-panel/CardEntranceSection.tsx +114 -0
- package/components/builder/settings-panel/ColumnV2AnimationTab.tsx +32 -0
- package/components/builder/settings-panel/CustomSectionSettings.tsx +150 -0
- package/components/builder/settings-panel/index.ts +6 -0
- package/components/builder/settings-panel/useSettingsPanelSelection.ts +184 -0
- package/lib/bot-guard.ts +138 -0
- package/lib/builder/serializer/migrations.ts +107 -0
- package/lib/builder/serializer/normalizers.ts +278 -0
- package/lib/builder/serializer/serializers.ts +393 -0
- package/lib/builder/serializer/shared.ts +102 -0
- package/lib/builder/serializer.ts +11 -846
- package/package.json +10 -9
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities used by both Document→State (normalizers) and State→Document (serializers).
|
|
3
|
+
*
|
|
4
|
+
* Extracted from serializer.ts in Session 162.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { generateKey } from "../utils";
|
|
8
|
+
|
|
9
|
+
// ============================================
|
|
10
|
+
// Constants
|
|
11
|
+
// ============================================
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Map block types to section_type values.
|
|
15
|
+
* Used during migration and validation to ensure consistent section type naming.
|
|
16
|
+
*/
|
|
17
|
+
export const SECTION_TYPE_MAP: Record<string, string> = {
|
|
18
|
+
projectGridBlock: "projectGrid",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// ============================================
|
|
22
|
+
// Utility Functions
|
|
23
|
+
// ============================================
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Ensure every item has a _key.
|
|
27
|
+
* Sanity sometimes omits _key on newly created objects.
|
|
28
|
+
*/
|
|
29
|
+
export function ensureKeys<T extends { _key?: string }>(items: T[] | undefined): (T & { _key: string })[] {
|
|
30
|
+
if (!items) return [];
|
|
31
|
+
return items.map((item) => ({
|
|
32
|
+
...item,
|
|
33
|
+
_key: item._key || generateKey(),
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Strip undefined values from an object (Sanity rejects undefined).
|
|
39
|
+
*/
|
|
40
|
+
export function stripUndefined<T extends Record<string, unknown>>(obj: T): T {
|
|
41
|
+
const result = {} as T;
|
|
42
|
+
for (const key of Object.keys(obj) as (keyof T)[]) {
|
|
43
|
+
if (obj[key] !== undefined) {
|
|
44
|
+
result[key] = obj[key];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Clean a layout object by removing empty, null, and empty-string values.
|
|
52
|
+
* Returns undefined if the cleaned object has no keys.
|
|
53
|
+
*/
|
|
54
|
+
export function cleanLayoutObject(obj: Record<string, unknown>): Record<string, unknown> | undefined {
|
|
55
|
+
const cleaned: Record<string, unknown> = {};
|
|
56
|
+
for (const [key, val] of Object.entries(obj)) {
|
|
57
|
+
if (val !== undefined && val !== null && val !== "") {
|
|
58
|
+
cleaned[key] = val;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return Object.keys(cleaned).length > 0 ? cleaned : undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Normalize block layout responsive overrides.
|
|
66
|
+
* Cleans up empty/invalid values within responsive.tablet.layout and responsive.phone.layout.
|
|
67
|
+
* Strips empty viewport objects and empty layout sub-objects.
|
|
68
|
+
*/
|
|
69
|
+
export function normalizeBlockResponsive(
|
|
70
|
+
responsive: Record<string, Record<string, unknown>> | undefined
|
|
71
|
+
): Record<string, Record<string, unknown>> | undefined {
|
|
72
|
+
if (!responsive) return undefined;
|
|
73
|
+
|
|
74
|
+
const result: Record<string, Record<string, unknown>> = {};
|
|
75
|
+
|
|
76
|
+
for (const vp of ["tablet", "phone"] as const) {
|
|
77
|
+
const vpOverrides = responsive[vp];
|
|
78
|
+
if (!vpOverrides || typeof vpOverrides !== "object") continue;
|
|
79
|
+
|
|
80
|
+
const cleaned: Record<string, unknown> = {};
|
|
81
|
+
|
|
82
|
+
for (const [key, val] of Object.entries(vpOverrides)) {
|
|
83
|
+
if (val === undefined || val === null) continue;
|
|
84
|
+
|
|
85
|
+
if (key === "layout" && typeof val === "object" && val !== null) {
|
|
86
|
+
const layoutCleaned = cleanLayoutObject(val as Record<string, unknown>);
|
|
87
|
+
if (layoutCleaned) cleaned.layout = layoutCleaned;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Other block properties (non-layout)
|
|
92
|
+
if (typeof val === "string" && val.trim() === "") continue;
|
|
93
|
+
cleaned[key] = val;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (Object.keys(cleaned).length > 0) {
|
|
97
|
+
result[vp] = cleaned;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
102
|
+
}
|