@morphika/andami 0.1.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 (319) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +50 -0
  3. package/admin/assets.ts +4 -0
  4. package/admin/database.ts +4 -0
  5. package/admin/index.ts +6 -0
  6. package/admin/login.ts +4 -0
  7. package/admin/navigation.ts +4 -0
  8. package/admin/pages-editor.ts +4 -0
  9. package/admin/pages.ts +4 -0
  10. package/admin/projects-editor.ts +4 -0
  11. package/admin/projects.ts +4 -0
  12. package/admin/settings.ts +4 -0
  13. package/admin/setup.ts +4 -0
  14. package/admin/storage.ts +4 -0
  15. package/admin/styles.ts +4 -0
  16. package/app/(site)/[slug]/loading.tsx +20 -0
  17. package/app/(site)/[slug]/page.tsx +83 -0
  18. package/app/(site)/error.tsx +32 -0
  19. package/app/(site)/layout.tsx +53 -0
  20. package/app/(site)/loading.tsx +20 -0
  21. package/app/(site)/not-found.tsx +41 -0
  22. package/app/(site)/page.tsx +43 -0
  23. package/app/(site)/preview/page.tsx +99 -0
  24. package/app/(site)/work/[slug]/loading.tsx +23 -0
  25. package/app/(site)/work/[slug]/page.tsx +84 -0
  26. package/app/admin/assets/page.tsx +573 -0
  27. package/app/admin/database/page.tsx +302 -0
  28. package/app/admin/error.tsx +53 -0
  29. package/app/admin/layout.tsx +273 -0
  30. package/app/admin/login/page.tsx +88 -0
  31. package/app/admin/navigation/page.tsx +157 -0
  32. package/app/admin/page.tsx +17 -0
  33. package/app/admin/pages/[slug]/page.tsx +849 -0
  34. package/app/admin/pages/page.tsx +588 -0
  35. package/app/admin/projects/[slug]/page.tsx +3 -0
  36. package/app/admin/projects/page.tsx +669 -0
  37. package/app/admin/settings/page.tsx +132 -0
  38. package/app/admin/setup/page.tsx +64 -0
  39. package/app/admin/storage/page.tsx +518 -0
  40. package/app/admin/styles/page.tsx +243 -0
  41. package/app/api/admin/assets/file/route.ts +81 -0
  42. package/app/api/admin/assets/health/route.ts +170 -0
  43. package/app/api/admin/assets/register/route.ts +163 -0
  44. package/app/api/admin/assets/registry/route.ts +98 -0
  45. package/app/api/admin/assets/relink/confirm/route.ts +242 -0
  46. package/app/api/admin/assets/relink/route.ts +202 -0
  47. package/app/api/admin/assets/scan/route.ts +271 -0
  48. package/app/api/admin/auth/route.ts +160 -0
  49. package/app/api/admin/custom-sections/[slug]/route.ts +159 -0
  50. package/app/api/admin/custom-sections/route.ts +127 -0
  51. package/app/api/admin/database/route.ts +53 -0
  52. package/app/api/admin/pages/[slug]/duplicate/route.ts +91 -0
  53. package/app/api/admin/pages/[slug]/route.ts +617 -0
  54. package/app/api/admin/pages/[slug]/set-home/route.ts +76 -0
  55. package/app/api/admin/pages/route.ts +129 -0
  56. package/app/api/admin/preview/route.ts +53 -0
  57. package/app/api/admin/r2/connect/route.ts +181 -0
  58. package/app/api/admin/r2/delete/route.ts +198 -0
  59. package/app/api/admin/r2/disconnect/route.ts +42 -0
  60. package/app/api/admin/r2/rename/route.ts +265 -0
  61. package/app/api/admin/r2/status/route.ts +106 -0
  62. package/app/api/admin/r2/upload-url/route.ts +148 -0
  63. package/app/api/admin/revalidate/route.ts +55 -0
  64. package/app/api/admin/settings/route.ts +279 -0
  65. package/app/api/admin/setup/complete/route.ts +51 -0
  66. package/app/api/admin/setup/route.ts +118 -0
  67. package/app/api/admin/storage/switch/route.ts +117 -0
  68. package/app/api/admin/styles/fonts/route.ts +97 -0
  69. package/app/api/admin/styles/route.ts +304 -0
  70. package/app/api/assets/[...path]/route.ts +98 -0
  71. package/app/api/custom-sections/[id]/route.ts +43 -0
  72. package/app/api/draft-mode/disable/route.ts +10 -0
  73. package/app/api/draft-mode/enable/route.ts +26 -0
  74. package/app/api/projects/route.ts +42 -0
  75. package/app/api/styles/route.ts +88 -0
  76. package/app/favicon.ico +0 -0
  77. package/app/globals.css +7 -0
  78. package/app/layout.tsx +53 -0
  79. package/app/robots.ts +17 -0
  80. package/app/sitemap.ts +48 -0
  81. package/app/studio/[[...index]]/page.tsx +8 -0
  82. package/components/admin/MetadataEditor.tsx +173 -0
  83. package/components/admin/PublishToggle.tsx +130 -0
  84. package/components/admin/icons.tsx +40 -0
  85. package/components/admin/nav-builder/NavBuilder.tsx +182 -0
  86. package/components/admin/nav-builder/NavBuilderGrid.tsx +326 -0
  87. package/components/admin/nav-builder/NavGeneralSettings.tsx +275 -0
  88. package/components/admin/nav-builder/NavGridCell.tsx +48 -0
  89. package/components/admin/nav-builder/NavGridItem.tsx +189 -0
  90. package/components/admin/nav-builder/NavItemSettings.tsx +288 -0
  91. package/components/admin/nav-builder/NavItemTypePicker.tsx +102 -0
  92. package/components/admin/nav-builder/NavLivePreview.tsx +125 -0
  93. package/components/admin/nav-builder/NavSettingsFields.tsx +248 -0
  94. package/components/admin/nav-builder/NavSettingsPanel.tsx +127 -0
  95. package/components/admin/nav-builder/index.ts +10 -0
  96. package/components/admin/nav-builder/nav-builder-utils.ts +238 -0
  97. package/components/admin/setup-wizard/BrandingStep.tsx +218 -0
  98. package/components/admin/setup-wizard/DatabaseStep.tsx +331 -0
  99. package/components/admin/setup-wizard/DoneStep.tsx +187 -0
  100. package/components/admin/setup-wizard/SetupWizard.tsx +166 -0
  101. package/components/admin/setup-wizard/StorageStep.tsx +308 -0
  102. package/components/admin/setup-wizard/WelcomeStep.tsx +96 -0
  103. package/components/admin/setup-wizard/index.ts +9 -0
  104. package/components/admin/styles/ColorsEditor.tsx +214 -0
  105. package/components/admin/styles/FontsEditor.tsx +258 -0
  106. package/components/admin/styles/GridLayoutEditor.tsx +292 -0
  107. package/components/admin/styles/LinksButtonsEditor.tsx +120 -0
  108. package/components/admin/styles/TypographyEditor.tsx +266 -0
  109. package/components/admin/styles/index.ts +9 -0
  110. package/components/admin/styles/shared.tsx +68 -0
  111. package/components/blocks/BlockRenderer.tsx +404 -0
  112. package/components/blocks/ButtonBlockRenderer.tsx +52 -0
  113. package/components/blocks/CoverBlockRenderer.tsx +239 -0
  114. package/components/blocks/CustomSectionInstanceRenderer.tsx +82 -0
  115. package/components/blocks/EnterAnimationWrapper.tsx +140 -0
  116. package/components/blocks/HoverAnimationWrapper.tsx +308 -0
  117. package/components/blocks/ImageBlockRenderer.tsx +61 -0
  118. package/components/blocks/ImageGridBlockRenderer.tsx +545 -0
  119. package/components/blocks/PageBackground.tsx +28 -0
  120. package/components/blocks/PageNavAnimation.tsx +35 -0
  121. package/components/blocks/PageNavColor.tsx +24 -0
  122. package/components/blocks/PageRenderer.tsx +142 -0
  123. package/components/blocks/ParallaxGroupRenderer.tsx +448 -0
  124. package/components/blocks/ParallaxSlideRenderer.tsx +175 -0
  125. package/components/blocks/ProjectGridBlockRenderer.tsx +556 -0
  126. package/components/blocks/SectionRenderer.tsx +170 -0
  127. package/components/blocks/SectionV2Renderer.tsx +330 -0
  128. package/components/blocks/ShaderCanvas.tsx +392 -0
  129. package/components/blocks/SpacerBlockRenderer.tsx +17 -0
  130. package/components/blocks/TextBlockRenderer.tsx +87 -0
  131. package/components/blocks/TypewriterRichText.tsx +464 -0
  132. package/components/blocks/TypewriterWrapper.tsx +149 -0
  133. package/components/blocks/VideoBlockRenderer.tsx +304 -0
  134. package/components/blocks/index.ts +2 -0
  135. package/components/builder/AssetBrowser.tsx +2 -0
  136. package/components/builder/BlockLivePreview.tsx +101 -0
  137. package/components/builder/BlockTypePicker.tsx +178 -0
  138. package/components/builder/BuilderCanvas.tsx +354 -0
  139. package/components/builder/CanvasMinimap.tsx +200 -0
  140. package/components/builder/CanvasToolbar.tsx +202 -0
  141. package/components/builder/ColorPicker.tsx +243 -0
  142. package/components/builder/ColorSwatchPicker.tsx +274 -0
  143. package/components/builder/ColumnDragContext.tsx +51 -0
  144. package/components/builder/ColumnDragOverlay.tsx +110 -0
  145. package/components/builder/CustomSectionInstanceCard.tsx +97 -0
  146. package/components/builder/DeviceFrame.tsx +123 -0
  147. package/components/builder/DndWrapper.tsx +337 -0
  148. package/components/builder/InsertionLines.tsx +186 -0
  149. package/components/builder/ParallaxGroupCanvas.tsx +228 -0
  150. package/components/builder/ParallaxSlideHeader.tsx +113 -0
  151. package/components/builder/ReadOnlyFrame.tsx +417 -0
  152. package/components/builder/SectionEditorBar.tsx +288 -0
  153. package/components/builder/SectionTypePicker.tsx +422 -0
  154. package/components/builder/SectionV2Canvas.tsx +297 -0
  155. package/components/builder/SectionV2Column.tsx +488 -0
  156. package/components/builder/SettingsPanel.tsx +911 -0
  157. package/components/builder/SortableBlock.tsx +230 -0
  158. package/components/builder/SortableRow.tsx +362 -0
  159. package/components/builder/VirtualAssetGrid.tsx +397 -0
  160. package/components/builder/asset-browser/AssetBrowser.tsx +178 -0
  161. package/components/builder/asset-browser/FileLightbox.tsx +116 -0
  162. package/components/builder/asset-browser/FolderTreeItem.tsx +55 -0
  163. package/components/builder/asset-browser/R2BrowserContent.tsx +436 -0
  164. package/components/builder/asset-browser/R2ContextMenu.tsx +98 -0
  165. package/components/builder/asset-browser/VideoThumbnail.tsx +63 -0
  166. package/components/builder/asset-browser/helpers.ts +88 -0
  167. package/components/builder/asset-browser/index.ts +1 -0
  168. package/components/builder/asset-browser/types.ts +49 -0
  169. package/components/builder/asset-browser/useAssetBrowser.ts +344 -0
  170. package/components/builder/asset-browser/useR2DragDrop.ts +116 -0
  171. package/components/builder/asset-browser/useR2Operations.ts +189 -0
  172. package/components/builder/blockStyles.tsx +295 -0
  173. package/components/builder/editors/ButtonBlockEditor.tsx +184 -0
  174. package/components/builder/editors/CoverBlockEditor.tsx +488 -0
  175. package/components/builder/editors/EnterAnimationPicker.tsx +297 -0
  176. package/components/builder/editors/HoverEffectPicker.tsx +209 -0
  177. package/components/builder/editors/ImageBlockEditor.tsx +206 -0
  178. package/components/builder/editors/ImageGridBlockEditor.tsx +386 -0
  179. package/components/builder/editors/ProjectGridEditor.tsx +648 -0
  180. package/components/builder/editors/SpacerBlockEditor.tsx +167 -0
  181. package/components/builder/editors/StaggerSettings.tsx +108 -0
  182. package/components/builder/editors/TextAlignmentIcons.tsx +39 -0
  183. package/components/builder/editors/TextBlockEditor.tsx +462 -0
  184. package/components/builder/editors/TextStylePicker.tsx +183 -0
  185. package/components/builder/editors/VideoBlockEditor.tsx +278 -0
  186. package/components/builder/editors/index.ts +10 -0
  187. package/components/builder/editors/shared.tsx +345 -0
  188. package/components/builder/hooks/useColumnDrag.ts +472 -0
  189. package/components/builder/hooks/useColumnResize.ts +221 -0
  190. package/components/builder/index.ts +12 -0
  191. package/components/builder/live-preview/LiveButtonPreview.tsx +38 -0
  192. package/components/builder/live-preview/LiveCoverPreview.tsx +146 -0
  193. package/components/builder/live-preview/LiveImageGridPreview.tsx +123 -0
  194. package/components/builder/live-preview/LiveImagePreview.tsx +107 -0
  195. package/components/builder/live-preview/LiveProjectGridPreview.tsx +1010 -0
  196. package/components/builder/live-preview/LiveSpacerPreview.tsx +9 -0
  197. package/components/builder/live-preview/LiveTextEditor.tsx +198 -0
  198. package/components/builder/live-preview/LiveVideoPreview.tsx +98 -0
  199. package/components/builder/live-preview/index.ts +10 -0
  200. package/components/builder/live-preview/shared.tsx +153 -0
  201. package/components/builder/settings-panel/BlockLayoutTab.tsx +532 -0
  202. package/components/builder/settings-panel/BlockSettings.tsx +94 -0
  203. package/components/builder/settings-panel/ColumnV2Settings.tsx +160 -0
  204. package/components/builder/settings-panel/LayoutTab.tsx +310 -0
  205. package/components/builder/settings-panel/PageSettings.tsx +200 -0
  206. package/components/builder/settings-panel/ParallaxGroupSettings.tsx +118 -0
  207. package/components/builder/settings-panel/ParallaxSlideSettings.tsx +178 -0
  208. package/components/builder/settings-panel/SectionV2AnimationTab.tsx +103 -0
  209. package/components/builder/settings-panel/SectionV2LayoutTab.tsx +312 -0
  210. package/components/builder/settings-panel/SectionV2Settings.tsx +323 -0
  211. package/components/builder/settings-panel/TRBLInputs.tsx +51 -0
  212. package/components/builder/settings-panel/index.ts +19 -0
  213. package/components/builder/settings-panel/responsive-helpers.ts +524 -0
  214. package/components/ui/CustomCursor.tsx +118 -0
  215. package/components/ui/NavContentLightbox.tsx +152 -0
  216. package/components/ui/Navbar.tsx +582 -0
  217. package/components/ui/PortfolioTracker.tsx +87 -0
  218. package/components/ui/ScrollToTop.tsx +47 -0
  219. package/lib/animation/enter-presets.ts +147 -0
  220. package/lib/animation/enter-resolve.ts +90 -0
  221. package/lib/animation/enter-types.ts +128 -0
  222. package/lib/animation/hover-effect-presets.ts +210 -0
  223. package/lib/animation/hover-effect-types.ts +126 -0
  224. package/lib/asset-retry.ts +111 -0
  225. package/lib/assets.ts +92 -0
  226. package/lib/audit.ts +35 -0
  227. package/lib/auth-token.ts +94 -0
  228. package/lib/auth.ts +13 -0
  229. package/lib/builder/cascade-helpers.ts +51 -0
  230. package/lib/builder/cascade.ts +533 -0
  231. package/lib/builder/constants.ts +103 -0
  232. package/lib/builder/defaults.ts +182 -0
  233. package/lib/builder/history.ts +48 -0
  234. package/lib/builder/index.ts +21 -0
  235. package/lib/builder/layout-styles.ts +344 -0
  236. package/lib/builder/masonry.ts +166 -0
  237. package/lib/builder/responsive.ts +156 -0
  238. package/lib/builder/serializer.ts +845 -0
  239. package/lib/builder/store-blocks.ts +193 -0
  240. package/lib/builder/store-canvas.ts +319 -0
  241. package/lib/builder/store-helpers.ts +490 -0
  242. package/lib/builder/store-sections.ts +709 -0
  243. package/lib/builder/store.ts +333 -0
  244. package/lib/builder/templates.ts +297 -0
  245. package/lib/builder/types.ts +374 -0
  246. package/lib/builder/utils.ts +37 -0
  247. package/lib/color-utils.ts +116 -0
  248. package/lib/config/index.ts +57 -0
  249. package/lib/config/types.ts +122 -0
  250. package/lib/contexts/AssetContext.tsx +79 -0
  251. package/lib/contexts/NavAnimationContext.tsx +44 -0
  252. package/lib/contexts/NavColorContext.tsx +38 -0
  253. package/lib/contexts/PageExitContext.tsx +194 -0
  254. package/lib/contexts/ThumbStatusContext.tsx +83 -0
  255. package/lib/csrf-client.ts +34 -0
  256. package/lib/csrf.ts +68 -0
  257. package/lib/format-utils.ts +24 -0
  258. package/lib/hooks/useViewport.ts +42 -0
  259. package/lib/logger.ts +81 -0
  260. package/lib/revalidate.ts +23 -0
  261. package/lib/sanitize.ts +91 -0
  262. package/lib/sanity/client.ts +8 -0
  263. package/lib/sanity/queries.ts +486 -0
  264. package/lib/sanity/types.ts +869 -0
  265. package/lib/sanity/writeClient.ts +24 -0
  266. package/lib/security.ts +402 -0
  267. package/lib/setup/detect.ts +156 -0
  268. package/lib/shader/glsl/index.ts +27 -0
  269. package/lib/shader/glsl/pixelate.ts +51 -0
  270. package/lib/shader/glsl/rgb-shift.ts +45 -0
  271. package/lib/shader/glsl/ripple.ts +46 -0
  272. package/lib/shader/glsl/vertex.ts +14 -0
  273. package/lib/storage/index.ts +211 -0
  274. package/lib/storage/r2-adapter.ts +286 -0
  275. package/lib/storage/types.ts +125 -0
  276. package/lib/styles/provider.tsx +267 -0
  277. package/lib/thumbnails/generate.ts +151 -0
  278. package/lib/utils.ts +6 -0
  279. package/package.json +212 -0
  280. package/sanity/compose.ts +65 -0
  281. package/sanity/sanity.config.ts +126 -0
  282. package/sanity/schemas/assetRegistry.ts +301 -0
  283. package/sanity/schemas/blocks/blockLayout.ts +90 -0
  284. package/sanity/schemas/blocks/buttonBlock.ts +82 -0
  285. package/sanity/schemas/blocks/coverBlock.ts +229 -0
  286. package/sanity/schemas/blocks/imageBlock.ts +58 -0
  287. package/sanity/schemas/blocks/imageGridBlock.ts +112 -0
  288. package/sanity/schemas/blocks/index.ts +9 -0
  289. package/sanity/schemas/blocks/projectGridBlock.ts +251 -0
  290. package/sanity/schemas/blocks/spacerBlock.ts +41 -0
  291. package/sanity/schemas/blocks/textBlock.ts +139 -0
  292. package/sanity/schemas/blocks/videoBlock.ts +80 -0
  293. package/sanity/schemas/customSection.ts +69 -0
  294. package/sanity/schemas/customSectionInstance.ts +163 -0
  295. package/sanity/schemas/index.ts +111 -0
  296. package/sanity/schemas/objects/enterAnimationConfig.ts +72 -0
  297. package/sanity/schemas/objects/hoverEffectConfig.ts +90 -0
  298. package/sanity/schemas/objects/parallaxGroup.ts +66 -0
  299. package/sanity/schemas/objects/parallaxSlide.ts +217 -0
  300. package/sanity/schemas/objects/typewriterConfig.ts +38 -0
  301. package/sanity/schemas/page.ts +162 -0
  302. package/sanity/schemas/pageSection.ts +157 -0
  303. package/sanity/schemas/pageSectionV2.ts +269 -0
  304. package/sanity/schemas/siteSettings.ts +256 -0
  305. package/sanity/schemas/siteStyles.ts +212 -0
  306. package/site/error.ts +4 -0
  307. package/site/index.ts +8 -0
  308. package/site/not-found.ts +4 -0
  309. package/site/page.ts +4 -0
  310. package/site/preview.ts +4 -0
  311. package/site/robots.ts +4 -0
  312. package/site/sitemap.ts +4 -0
  313. package/site/work.ts +4 -0
  314. package/studio/index.ts +4 -0
  315. package/styles/admin.css +85 -0
  316. package/styles/animations.css +237 -0
  317. package/styles/base.css +148 -0
  318. package/styles/globals.css +10 -0
  319. package/tsconfig.json +25 -0
@@ -0,0 +1,269 @@
1
+ import { defineField, defineType } from "sanity";
2
+
3
+ /**
4
+ * pageSectionV2 — V2 Grid Section.
5
+ *
6
+ * Flat list of columns with explicit grid positions. No "row" objects —
7
+ * rows are a visual artifact derived from `grid_row` values.
8
+ * The serializer stores exactly what the builder computes.
9
+ *
10
+ * Session 83: V2 Grid System — Phase 1 (Data Layer & Core Engine).
11
+ */
12
+ export default defineType({
13
+ name: "pageSectionV2",
14
+ title: "Page Section V2",
15
+ type: "object",
16
+ fields: [
17
+ defineField({
18
+ name: "section_type",
19
+ title: "Section Type",
20
+ type: "string",
21
+ options: {
22
+ list: [{ title: "Empty V2", value: "empty-v2" }],
23
+ },
24
+ validation: (Rule) => Rule.required(),
25
+ }),
26
+
27
+ // ---- Columns: flat array with explicit grid positions ----
28
+ defineField({
29
+ name: "columns",
30
+ title: "Columns",
31
+ type: "array",
32
+ of: [
33
+ {
34
+ type: "object",
35
+ name: "sectionColumn",
36
+ fields: [
37
+ defineField({
38
+ name: "grid_column",
39
+ title: "Grid Column",
40
+ type: "number",
41
+ description: "1-based start position (1–12)",
42
+ validation: (Rule) => Rule.required().min(1).max(12),
43
+ }),
44
+ defineField({
45
+ name: "grid_row",
46
+ title: "Grid Row",
47
+ type: "number",
48
+ description: "1-based row (computed by builder)",
49
+ validation: (Rule) => Rule.required().min(1),
50
+ }),
51
+ defineField({
52
+ name: "span",
53
+ title: "Column Span",
54
+ type: "number",
55
+ description: "How many grid columns (1–12)",
56
+ validation: (Rule) => Rule.required().min(1).max(12),
57
+ }),
58
+ defineField({
59
+ name: "blocks",
60
+ title: "Blocks",
61
+ type: "array",
62
+ of: [
63
+ { type: "textBlock" },
64
+ { type: "imageBlock" },
65
+ { type: "imageGridBlock" },
66
+ { type: "videoBlock" },
67
+ { type: "spacerBlock" },
68
+ { type: "buttonBlock" },
69
+ { type: "coverBlock" },
70
+ ],
71
+ }),
72
+ // Column-level enter animation (Session 117)
73
+ defineField({
74
+ name: "enter_animation",
75
+ title: "Enter Animation",
76
+ type: "enterAnimationConfig",
77
+ }),
78
+ ],
79
+ },
80
+ ],
81
+ }),
82
+
83
+ // ---- Section Settings ----
84
+ defineField({
85
+ name: "settings",
86
+ title: "Section Settings",
87
+ type: "object",
88
+ fields: [
89
+ // Grid
90
+ defineField({
91
+ name: "preset",
92
+ title: "Layout Preset",
93
+ type: "string",
94
+ options: {
95
+ list: ["full", "halves", "thirds", "quarters", "1/3+2/3", "2/3+1/3", "custom"],
96
+ },
97
+ }),
98
+ defineField({ name: "grid_columns", title: "Grid Columns", type: "number" }),
99
+ defineField({ name: "col_gap", title: "Column Gap", type: "number" }),
100
+ defineField({ name: "row_gap", title: "Row Gap", type: "number" }),
101
+ // Spacing (padding TRBL)
102
+ defineField({ name: "spacing_top", title: "Spacing Top", type: "string" }),
103
+ defineField({ name: "spacing_right", title: "Spacing Right", type: "string" }),
104
+ defineField({ name: "spacing_bottom", title: "Spacing Bottom", type: "string" }),
105
+ defineField({ name: "spacing_left", title: "Spacing Left", type: "string" }),
106
+ // Offset (margin TRBL)
107
+ defineField({ name: "offset_top", title: "Offset Top", type: "string" }),
108
+ defineField({ name: "offset_right", title: "Offset Right", type: "string" }),
109
+ defineField({ name: "offset_bottom", title: "Offset Bottom", type: "string" }),
110
+ defineField({ name: "offset_left", title: "Offset Left", type: "string" }),
111
+ // Background
112
+ defineField({ name: "background_color", title: "Background Color", type: "string" }),
113
+ defineField({ name: "background_opacity", title: "Background Opacity", type: "number" }),
114
+ defineField({ name: "background_image", title: "Background Image", type: "string" }),
115
+ defineField({
116
+ name: "background_size",
117
+ title: "Background Size",
118
+ type: "string",
119
+ options: { list: ["cover", "contain", "auto"] },
120
+ }),
121
+ defineField({ name: "background_position", title: "Background Position", type: "string" }),
122
+ defineField({
123
+ name: "background_repeat",
124
+ title: "Background Repeat",
125
+ type: "string",
126
+ options: { list: ["no-repeat", "repeat", "repeat-x", "repeat-y"] },
127
+ }),
128
+ // Border
129
+ defineField({ name: "border_color", title: "Border Color", type: "string" }),
130
+ defineField({ name: "border_width", title: "Border Width", type: "string" }),
131
+ defineField({
132
+ name: "border_style",
133
+ title: "Border Style",
134
+ type: "string",
135
+ options: { list: ["none", "solid", "dashed", "dotted"] },
136
+ }),
137
+ defineField({
138
+ name: "border_sides",
139
+ title: "Border Sides",
140
+ type: "string",
141
+ options: { list: ["all", "top", "right", "bottom", "left", "top-bottom", "left-right"] },
142
+ }),
143
+ defineField({ name: "border_radius", title: "Border Radius", type: "string" }),
144
+ // Animation
145
+ defineField({
146
+ name: "enter_animation",
147
+ title: "Enter Animation",
148
+ type: "enterAnimationConfig",
149
+ }),
150
+ // Stagger
151
+ defineField({
152
+ name: "stagger",
153
+ title: "Stagger",
154
+ type: "object",
155
+ fields: [
156
+ defineField({ name: "enabled", title: "Enabled", type: "boolean" }),
157
+ defineField({ name: "delayPerChild", title: "Delay Per Child", type: "number" }),
158
+ defineField({
159
+ name: "direction",
160
+ title: "Direction",
161
+ type: "string",
162
+ options: { list: ["left-to-right", "right-to-left"] },
163
+ }),
164
+ ],
165
+ }),
166
+ ],
167
+ }),
168
+
169
+ // ---- Responsive Overrides ----
170
+ defineField({
171
+ name: "responsive",
172
+ title: "Responsive Overrides",
173
+ type: "object",
174
+ hidden: true, // Managed by the visual builder
175
+ fields: [
176
+ defineField({
177
+ name: "tablet",
178
+ title: "Tablet",
179
+ type: "object",
180
+ fields: [
181
+ // Column overrides
182
+ defineField({
183
+ name: "columns",
184
+ title: "Column Overrides",
185
+ type: "array",
186
+ of: [
187
+ {
188
+ type: "object",
189
+ name: "columnOverride",
190
+ fields: [
191
+ defineField({ name: "grid_column", title: "Grid Column", type: "number" }),
192
+ defineField({ name: "grid_row", title: "Grid Row", type: "number" }),
193
+ defineField({ name: "span", title: "Span", type: "number" }),
194
+ ],
195
+ },
196
+ ],
197
+ }),
198
+ // Section setting overrides
199
+ defineField({ name: "col_gap", title: "Column Gap", type: "number" }),
200
+ defineField({ name: "row_gap", title: "Row Gap", type: "number" }),
201
+ defineField({ name: "spacing_top", type: "string", title: "Spacing Top" }),
202
+ defineField({ name: "spacing_right", type: "string", title: "Spacing Right" }),
203
+ defineField({ name: "spacing_bottom", type: "string", title: "Spacing Bottom" }),
204
+ defineField({ name: "spacing_left", type: "string", title: "Spacing Left" }),
205
+ defineField({ name: "offset_top", type: "string", title: "Offset Top" }),
206
+ defineField({ name: "offset_right", type: "string", title: "Offset Right" }),
207
+ defineField({ name: "offset_bottom", type: "string", title: "Offset Bottom" }),
208
+ defineField({ name: "offset_left", type: "string", title: "Offset Left" }),
209
+ defineField({ name: "background_color", type: "string", title: "Background Color" }),
210
+ defineField({ name: "background_opacity", type: "number", title: "Background Opacity" }),
211
+ defineField({ name: "border_color", type: "string", title: "Border Color" }),
212
+ defineField({ name: "border_width", type: "string", title: "Border Width" }),
213
+ defineField({ name: "border_style", type: "string", title: "Border Style" }),
214
+ defineField({ name: "border_sides", type: "string", title: "Border Sides" }),
215
+ defineField({ name: "border_radius", type: "string", title: "Border Radius" }),
216
+ ],
217
+ }),
218
+ defineField({
219
+ name: "phone",
220
+ title: "Phone",
221
+ type: "object",
222
+ fields: [
223
+ // Column overrides
224
+ defineField({
225
+ name: "columns",
226
+ title: "Column Overrides",
227
+ type: "array",
228
+ of: [
229
+ {
230
+ type: "object",
231
+ name: "columnOverride",
232
+ fields: [
233
+ defineField({ name: "grid_column", title: "Grid Column", type: "number" }),
234
+ defineField({ name: "grid_row", title: "Grid Row", type: "number" }),
235
+ defineField({ name: "span", title: "Span", type: "number" }),
236
+ ],
237
+ },
238
+ ],
239
+ }),
240
+ // Section setting overrides
241
+ defineField({ name: "col_gap", title: "Column Gap", type: "number" }),
242
+ defineField({ name: "row_gap", title: "Row Gap", type: "number" }),
243
+ defineField({ name: "spacing_top", type: "string", title: "Spacing Top" }),
244
+ defineField({ name: "spacing_right", type: "string", title: "Spacing Right" }),
245
+ defineField({ name: "spacing_bottom", type: "string", title: "Spacing Bottom" }),
246
+ defineField({ name: "spacing_left", type: "string", title: "Spacing Left" }),
247
+ defineField({ name: "offset_top", type: "string", title: "Offset Top" }),
248
+ defineField({ name: "offset_right", type: "string", title: "Offset Right" }),
249
+ defineField({ name: "offset_bottom", type: "string", title: "Offset Bottom" }),
250
+ defineField({ name: "offset_left", type: "string", title: "Offset Left" }),
251
+ defineField({ name: "background_color", type: "string", title: "Background Color" }),
252
+ defineField({ name: "background_opacity", type: "number", title: "Background Opacity" }),
253
+ defineField({ name: "border_color", type: "string", title: "Border Color" }),
254
+ defineField({ name: "border_width", type: "string", title: "Border Width" }),
255
+ defineField({ name: "border_style", type: "string", title: "Border Style" }),
256
+ defineField({ name: "border_sides", type: "string", title: "Border Sides" }),
257
+ defineField({ name: "border_radius", type: "string", title: "Border Radius" }),
258
+ ],
259
+ }),
260
+ ],
261
+ }),
262
+ ],
263
+ preview: {
264
+ select: { section_type: "section_type" },
265
+ prepare({ section_type }) {
266
+ return { title: section_type === "empty-v2" ? "Section V2" : "Section" };
267
+ },
268
+ },
269
+ });
@@ -0,0 +1,256 @@
1
+ import { defineType, defineField } from "sanity";
2
+ import { getSiteConfig } from "../../lib/config";
3
+
4
+ const _cfg = getSiteConfig();
5
+
6
+ export default defineType({
7
+ name: "siteSettings",
8
+ title: "Site Settings",
9
+ type: "document",
10
+ groups: [
11
+ { name: "nav", title: "Navigation", default: true },
12
+ { name: "nav_design", title: "Nav Design" },
13
+ { name: "meta", title: "Metadata" },
14
+ { name: "assets", title: "Assets" },
15
+ ],
16
+ fields: [
17
+ // === NAVIGATION ===
18
+ defineField({
19
+ name: "nav_items",
20
+ title: "Nav Items",
21
+ type: "array",
22
+ group: "nav",
23
+ of: [
24
+ {
25
+ type: "object",
26
+ fields: [
27
+ defineField({
28
+ name: "type",
29
+ title: "Item Type",
30
+ type: "string",
31
+ options: { list: [{ title: "Logo", value: "logo" }, { title: "Menu Item", value: "menu-item" }] },
32
+ initialValue: "menu-item",
33
+ }),
34
+ defineField({ name: "label", title: "Label", type: "string", validation: (Rule) => Rule.required() }),
35
+ defineField({ name: "logo_image", title: "Logo Image", type: "string", description: "Asset path for logo image (optional)" }),
36
+ defineField({
37
+ name: "link_type",
38
+ title: "Link Type",
39
+ type: "string",
40
+ options: {
41
+ list: [
42
+ { title: "Internal Page", value: "internal" },
43
+ { title: "External URL", value: "external" },
44
+ { title: "Content (Lightbox)", value: "content" },
45
+ ],
46
+ },
47
+ initialValue: "internal",
48
+ }),
49
+ defineField({
50
+ name: "internal_page",
51
+ title: "Internal Page",
52
+ type: "reference",
53
+ to: [{ type: "page" }],
54
+ hidden: ({ parent }) => parent?.link_type !== "internal",
55
+ }),
56
+ defineField({
57
+ name: "external_url",
58
+ title: "External URL",
59
+ type: "url",
60
+ hidden: ({ parent }) => parent?.link_type !== "external",
61
+ }),
62
+ defineField({
63
+ name: "content_type",
64
+ title: "Content Type",
65
+ type: "string",
66
+ options: {
67
+ list: [
68
+ { title: "Image", value: "image" },
69
+ { title: "Video File", value: "video-file" },
70
+ { title: "Video Embed", value: "video-embed" },
71
+ ],
72
+ },
73
+ initialValue: "image",
74
+ hidden: ({ parent }) => parent?.link_type !== "content",
75
+ }),
76
+ defineField({
77
+ name: "content_asset",
78
+ title: "Content Asset",
79
+ type: "string",
80
+ description: "Asset path for image or video file",
81
+ hidden: ({ parent }) => parent?.link_type !== "content" || parent?.content_type === "video-embed",
82
+ }),
83
+ defineField({
84
+ name: "content_url",
85
+ title: "Video Embed URL",
86
+ type: "url",
87
+ description: "YouTube or Vimeo URL",
88
+ hidden: ({ parent }) => parent?.link_type !== "content" || parent?.content_type !== "video-embed",
89
+ }),
90
+ defineField({ name: "visible", title: "Visible", type: "boolean", initialValue: true }),
91
+ defineField({ name: "grid_column", title: "Grid Column", type: "number", description: "Which of the 12 grid columns this item sits in (1–12)", initialValue: 1 }),
92
+ defineField({ name: "column_span", title: "Column Span", type: "number", description: "How many columns this item occupies (1–12)", initialValue: 1 }),
93
+ defineField({
94
+ name: "style_overrides",
95
+ title: "Style Overrides",
96
+ type: "object",
97
+ fields: [
98
+ defineField({ name: "font_size", title: "Font Size (px)", type: "number" }),
99
+ defineField({ name: "font_weight", title: "Font Weight", type: "string" }),
100
+ defineField({ name: "font_family", title: "Font Family", type: "string" }),
101
+ defineField({ name: "color", title: "Color", type: "string" }),
102
+ defineField({
103
+ name: "text_transform",
104
+ title: "Text Transform",
105
+ type: "string",
106
+ options: { list: [{ title: "None", value: "none" }, { title: "Uppercase", value: "uppercase" }, { title: "Lowercase", value: "lowercase" }, { title: "Capitalize", value: "capitalize" }] },
107
+ }),
108
+ defineField({
109
+ name: "vertical_align",
110
+ title: "Vertical Align",
111
+ type: "string",
112
+ options: { list: [{ title: "Top", value: "top" }, { title: "Middle", value: "middle" }, { title: "Bottom", value: "bottom" }] },
113
+ }),
114
+ ],
115
+ }),
116
+ ],
117
+ preview: {
118
+ select: { label: "label", itemType: "type", visible: "visible" },
119
+ prepare({ label, itemType, visible }: { label?: string; itemType?: string; visible?: boolean }) {
120
+ return {
121
+ title: `${label || "Untitled"}${visible === false ? " (hidden)" : ""}`,
122
+ subtitle: itemType === "logo" ? "Logo" : "Menu Item",
123
+ };
124
+ },
125
+ },
126
+ },
127
+ ],
128
+ }),
129
+
130
+ // === NAV DESIGN ===
131
+ defineField({
132
+ name: "nav_design",
133
+ title: "Navigation Design",
134
+ type: "object",
135
+ group: "nav_design",
136
+ fields: [
137
+ defineField({ name: "logo_text", title: "Logo Text", type: "string", initialValue: _cfg.defaults.logoText }),
138
+ defineField({
139
+ name: "color",
140
+ title: "Nav Color",
141
+ type: "string",
142
+ options: {
143
+ list: [
144
+ { title: "Yellow-Lime", value: "yellow-lime" },
145
+ { title: "Yellow", value: "yellow" },
146
+ { title: "Red / Coral", value: "red-coral" },
147
+ { title: "Blue", value: "blue" },
148
+ { title: "Green", value: "green" },
149
+ { title: "White", value: "white" },
150
+ ],
151
+ },
152
+ initialValue: "yellow-lime",
153
+ }),
154
+ defineField({
155
+ name: "position",
156
+ title: "Position",
157
+ type: "string",
158
+ options: {
159
+ list: [
160
+ { title: "Fixed (stays on top)", value: "fixed" },
161
+ { title: "Sticky", value: "sticky" },
162
+ { title: "Static (scrolls away)", value: "static" },
163
+ ],
164
+ },
165
+ initialValue: "fixed",
166
+ }),
167
+ defineField({ name: "hide_on_scroll", title: "Hide on Scroll Down", type: "boolean", initialValue: true }),
168
+ defineField({ name: "font_size", title: "Font Size (px)", type: "number", initialValue: 14 }),
169
+ defineField({ name: "font_weight", title: "Font Weight", type: "string", initialValue: "400" }),
170
+ defineField({ name: "font_family", title: "Font Family", type: "string" }),
171
+ defineField({
172
+ name: "text_align",
173
+ title: "Text Align",
174
+ type: "string",
175
+ options: { list: [{ title: "Left", value: "left" }, { title: "Center", value: "center" }, { title: "Right", value: "right" }] },
176
+ initialValue: "left",
177
+ }),
178
+ defineField({
179
+ name: "text_transform",
180
+ title: "Text Transform",
181
+ type: "string",
182
+ options: { list: [{ title: "None", value: "none" }, { title: "Uppercase", value: "uppercase" }, { title: "Lowercase", value: "lowercase" }, { title: "Capitalize", value: "capitalize" }] },
183
+ initialValue: "uppercase",
184
+ }),
185
+ defineField({ name: "padding_h", title: "Horizontal Padding (px)", type: "number", initialValue: 24 }),
186
+ defineField({ name: "padding_v", title: "Vertical Padding (px)", type: "number", initialValue: 27 }),
187
+ defineField({ name: "margin_h", title: "Horizontal Margin (px)", type: "number", initialValue: 0 }),
188
+ defineField({ name: "margin_v", title: "Vertical Margin (px)", type: "number", initialValue: 0 }),
189
+ defineField({ name: "background_color", title: "Background Color", type: "string" }),
190
+ defineField({ name: "background_opacity", title: "Background Opacity (%)", type: "number", initialValue: 0 }),
191
+ defineField({ name: "backdrop_blur", title: "Backdrop Blur", type: "boolean", initialValue: false }),
192
+ defineField({ name: "items_gap", title: "Items Gap (px)", type: "number", initialValue: 32 }),
193
+ defineField({ name: "vertical_align", title: "Vertical Align", type: "string", description: "Vertical alignment of nav items", initialValue: "top", options: { list: [{ title: "Top", value: "top" }, { title: "Middle", value: "middle" }, { title: "Bottom", value: "bottom" }] } }),
194
+ defineField({ name: "logo_columns", title: "Logo Column Span", type: "number", description: "How many grid columns the logo occupies (1–6)", initialValue: 3 }),
195
+ // ── Entrance Animation ──
196
+ defineField({
197
+ name: "entrance_animation",
198
+ title: "Entrance Animation",
199
+ type: "string",
200
+ options: {
201
+ list: [
202
+ { title: "None", value: "" },
203
+ { title: "Fade In", value: "fade-in" },
204
+ { title: "Slide Down", value: "slide-down" },
205
+ { title: "Blur In", value: "blur-in" },
206
+ ],
207
+ },
208
+ }),
209
+ defineField({ name: "entrance_duration", title: "Entrance Duration (ms)", type: "number", description: "Default: 600" }),
210
+ defineField({ name: "entrance_delay", title: "Entrance Delay (ms)", type: "number", description: "Delay before animation starts. Default: 0" }),
211
+ defineField({ name: "entrance_stagger", title: "Stagger Items", type: "boolean", description: "Animate items one by one", initialValue: false }),
212
+ defineField({ name: "entrance_stagger_delay", title: "Stagger Delay (ms)", type: "number", description: "Delay between items. Default: 80" }),
213
+ ],
214
+ }),
215
+
216
+ // === METADATA ===
217
+ defineField({ name: "default_title", title: "Default Title", type: "string", group: "meta", initialValue: _cfg.defaults.metaTitle }),
218
+ defineField({ name: "default_description", title: "Default Description", type: "text", rows: 3, group: "meta" }),
219
+ defineField({ name: "default_og_image", title: "Default OG Image Path", type: "string", group: "meta" }),
220
+ defineField({ name: "favicon_path", title: "Favicon Path", type: "string", group: "meta" }),
221
+ defineField({ name: "analytics_id", title: "Analytics ID", type: "string", group: "meta" }),
222
+
223
+ // === SETUP ===
224
+ defineField({
225
+ name: "setup_complete",
226
+ title: "Setup Complete",
227
+ type: "boolean",
228
+ description: "Set to true when the onboarding wizard finishes. Prevents the wizard from re-triggering.",
229
+ initialValue: false,
230
+ hidden: true,
231
+ }),
232
+
233
+ // === ASSETS ===
234
+ defineField({ name: "seed_url", title: "Asset Seed URL", type: "url", group: "assets", description: "Base URL for asset resolution" }),
235
+ defineField({ name: "last_scanned_at", title: "Last Scanned At", type: "datetime", group: "assets", readOnly: true }),
236
+ defineField({
237
+ name: "asset_status",
238
+ title: "Asset Status",
239
+ type: "string",
240
+ group: "assets",
241
+ options: {
242
+ list: [
243
+ { title: "OK", value: "ok" },
244
+ { title: "Scanning", value: "scanning" },
245
+ { title: "Error", value: "error" },
246
+ ],
247
+ },
248
+ readOnly: true,
249
+ }),
250
+ ],
251
+ preview: {
252
+ prepare() {
253
+ return { title: "Site Settings" };
254
+ },
255
+ },
256
+ });