@onexapis/cli 1.1.16 → 1.1.18

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 (63) hide show
  1. package/README.md +117 -51
  2. package/bin/onexthm.js +4 -0
  3. package/dist/cli.js +750 -328
  4. package/dist/cli.js.map +1 -1
  5. package/dist/cli.mjs +747 -325
  6. package/dist/cli.mjs.map +1 -1
  7. package/dist/index.js +162 -299
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.mjs +162 -299
  10. package/dist/index.mjs.map +1 -1
  11. package/dist/preview/preview-app.tsx +175 -53
  12. package/package.json +14 -12
  13. package/templates/default/.env.example +1 -1
  14. package/templates/default/.mcp.json +8 -0
  15. package/templates/default/CLAUDE.md +941 -0
  16. package/templates/default/bundle-entry.ts +18 -0
  17. package/templates/default/index.ts +26 -0
  18. package/templates/default/package.json +37 -0
  19. package/templates/default/pages/about.ts +66 -0
  20. package/templates/default/pages/home.ts +93 -0
  21. package/templates/default/pages/showcase.ts +146 -0
  22. package/templates/default/sections/about/about-default.tsx +237 -0
  23. package/templates/default/sections/about/about.schema.ts +259 -0
  24. package/templates/default/sections/about/index.ts +15 -0
  25. package/templates/default/sections/cta/cta-default.tsx +180 -0
  26. package/templates/default/sections/cta/cta.schema.ts +210 -0
  27. package/templates/default/sections/cta/index.ts +11 -0
  28. package/templates/default/sections/features/features-default.tsx +154 -0
  29. package/templates/default/sections/features/features.schema.ts +330 -0
  30. package/templates/default/sections/features/index.ts +11 -0
  31. package/templates/default/sections/gallery/gallery-default.tsx +134 -0
  32. package/templates/default/sections/gallery/gallery.schema.ts +397 -0
  33. package/templates/default/sections/gallery/index.ts +11 -0
  34. package/templates/default/sections/hero/hero-default.tsx +212 -0
  35. package/templates/default/sections/hero/hero.schema.ts +273 -0
  36. package/templates/default/sections/hero/index.ts +15 -0
  37. package/templates/default/sections/stats/index.ts +11 -0
  38. package/templates/default/sections/stats/stats-default.tsx +103 -0
  39. package/templates/default/sections/stats/stats.schema.ts +266 -0
  40. package/templates/default/sections/testimonials/index.ts +11 -0
  41. package/templates/default/sections/testimonials/testimonials-default.tsx +130 -0
  42. package/templates/default/sections/testimonials/testimonials.schema.ts +371 -0
  43. package/templates/default/sections-registry.ts +32 -0
  44. package/templates/default/theme.config.ts +107 -0
  45. package/templates/default/theme.layout.ts +21 -0
  46. package/templates/default/tsconfig.json +16 -7
  47. package/templates/default/README.md.ejs +0 -129
  48. package/templates/default/esbuild.config.js +0 -81
  49. package/templates/default/package.json.ejs +0 -31
  50. package/templates/default/src/config.ts.ejs +0 -98
  51. package/templates/default/src/index.ts.ejs +0 -11
  52. package/templates/default/src/layout.ts +0 -23
  53. package/templates/default/src/manifest.ts.ejs +0 -47
  54. package/templates/default/src/pages/home.ts.ejs +0 -37
  55. package/templates/default/src/sections/footer/footer-default.tsx +0 -28
  56. package/templates/default/src/sections/footer/footer.schema.ts +0 -45
  57. package/templates/default/src/sections/footer/index.ts +0 -2
  58. package/templates/default/src/sections/header/header-default.tsx +0 -61
  59. package/templates/default/src/sections/header/header.schema.ts +0 -46
  60. package/templates/default/src/sections/header/index.ts +0 -2
  61. package/templates/default/src/sections/hero/hero-default.tsx +0 -52
  62. package/templates/default/src/sections/hero/hero.schema.ts +0 -52
  63. package/templates/default/src/sections/hero/index.ts +0 -2
@@ -0,0 +1,259 @@
1
+ import type { SectionSchema, FieldDefinition } from "@onexapis/core/types";
2
+
3
+ const commonSettings: FieldDefinition[] = [
4
+ {
5
+ id: "heading",
6
+ type: "text",
7
+ label: "Heading",
8
+ default: "About Us",
9
+ required: true,
10
+ },
11
+ {
12
+ id: "subheading",
13
+ type: "text",
14
+ label: "Subheading",
15
+ default: "Our Story",
16
+ },
17
+ {
18
+ id: "description",
19
+ type: "textarea",
20
+ label: "Description",
21
+ default:
22
+ "We create simple and elegant solutions for your business needs. Our focus is on clean design and user experience.",
23
+ maxLength: 500,
24
+ },
25
+ {
26
+ id: "secondaryDescription",
27
+ type: "textarea",
28
+ label: "Secondary Description",
29
+ default:
30
+ "Founded with a vision to simplify the digital experience, we have grown into a team of passionate creators dedicated to excellence.",
31
+ maxLength: 500,
32
+ },
33
+ {
34
+ id: "badgeText",
35
+ type: "text",
36
+ label: "Badge Text",
37
+ default: "About Us",
38
+ },
39
+ {
40
+ id: "showImage",
41
+ type: "checkbox",
42
+ label: "Show Image",
43
+ default: true,
44
+ },
45
+ {
46
+ id: "layout",
47
+ type: "select",
48
+ label: "Layout",
49
+ default: "centered",
50
+ options: [
51
+ { label: "Centered", value: "centered" },
52
+ { label: "Image Left", value: "image-left" },
53
+ { label: "Image Right", value: "image-right" },
54
+ ],
55
+ },
56
+ ];
57
+
58
+ export const aboutSchema: SectionSchema = {
59
+ type: "my-simple-about",
60
+ name: "Simple About",
61
+ description:
62
+ "About section with badge, heading, subheading, descriptions, divider, and image",
63
+ category: "content",
64
+ icon: "text",
65
+ settings: commonSettings,
66
+ templates: [
67
+ {
68
+ id: "default",
69
+ name: "Default About",
70
+ description: "An about section with rich content and layout options",
71
+ },
72
+ ],
73
+ blocks: [
74
+ {
75
+ type: "about-content",
76
+ name: "About Content",
77
+ description:
78
+ "About content block with badge, heading, descriptions, and image",
79
+ icon: "text",
80
+ settings: [
81
+ {
82
+ id: "contentAlignment",
83
+ type: "select",
84
+ label: "Content Alignment",
85
+ default: "center",
86
+ options: [
87
+ { label: "Left", value: "left" },
88
+ { label: "Center", value: "center" },
89
+ { label: "Right", value: "right" },
90
+ ],
91
+ },
92
+ {
93
+ id: "contentWidth",
94
+ type: "select",
95
+ label: "Content Width",
96
+ default: "lg",
97
+ options: [
98
+ { label: "Small", value: "sm" },
99
+ { label: "Medium", value: "md" },
100
+ { label: "Large", value: "lg" },
101
+ { label: "Full", value: "full" },
102
+ ],
103
+ },
104
+ ],
105
+ defaults: {
106
+ contentAlignment: "center",
107
+ contentWidth: "lg",
108
+ },
109
+ limit: 1,
110
+ },
111
+ ],
112
+ maxBlocks: 1,
113
+ defaults: {
114
+ settings: {
115
+ heading: "About Us",
116
+ subheading: "Our Story",
117
+ description:
118
+ "We create simple and elegant solutions for your business needs. Our focus is on clean design and user experience.",
119
+ secondaryDescription:
120
+ "Founded with a vision to simplify the digital experience, we have grown into a team of passionate creators dedicated to excellence.",
121
+ badgeText: "About Us",
122
+ showImage: true,
123
+ layout: "centered",
124
+ },
125
+ blocks: [
126
+ {
127
+ id: "about-content-1",
128
+ type: "about-content",
129
+ order: 0,
130
+ enabled: true,
131
+ settings: {},
132
+ components: [
133
+ {
134
+ id: "about-badge",
135
+ type: "badge",
136
+ slot: "badge",
137
+ order: 0,
138
+ content: { text: "About Us" },
139
+ style: {
140
+ fontSize: "sm",
141
+ fontWeight: "semibold",
142
+ color: "#3B82F6",
143
+ backgroundColor: "#EFF6FF",
144
+ padding: "0.25rem 0.75rem",
145
+ borderRadius: "9999px",
146
+ },
147
+ styleMode: "advanced",
148
+ enabled: true,
149
+ },
150
+ {
151
+ id: "about-heading",
152
+ type: "heading",
153
+ slot: "heading",
154
+ order: 1,
155
+ content: {
156
+ text: "About Us",
157
+ tag: "h2",
158
+ },
159
+ style: {
160
+ fontSize: "4xl",
161
+ fontWeight: "bold",
162
+ color: "#1F2937",
163
+ marginBottom: "0.5rem",
164
+ textAlign: "center",
165
+ },
166
+ styleMode: "advanced",
167
+ enabled: true,
168
+ },
169
+ {
170
+ id: "about-subheading",
171
+ type: "heading",
172
+ slot: "subheading",
173
+ order: 2,
174
+ content: {
175
+ text: "Our Story",
176
+ tag: "h3",
177
+ },
178
+ style: {
179
+ fontSize: "xl",
180
+ fontWeight: "medium",
181
+ color: "#6B7280",
182
+ marginBottom: "1rem",
183
+ textAlign: "center",
184
+ },
185
+ styleMode: "advanced",
186
+ enabled: true,
187
+ },
188
+ {
189
+ id: "about-divider",
190
+ type: "divider",
191
+ slot: "divider",
192
+ order: 3,
193
+ content: {},
194
+ style: {
195
+ borderColor: "#E5E7EB",
196
+ marginTop: "0.5rem",
197
+ marginBottom: "1.5rem",
198
+ },
199
+ styleMode: "advanced",
200
+ enabled: true,
201
+ },
202
+ {
203
+ id: "about-description",
204
+ type: "paragraph",
205
+ slot: "description",
206
+ order: 4,
207
+ content: {
208
+ text: "We create simple and elegant solutions for your business needs. Our focus is on clean design and user experience.",
209
+ },
210
+ style: {
211
+ fontSize: "lg",
212
+ color: "#4B5563",
213
+ textAlign: "center",
214
+ lineHeight: "1.75",
215
+ marginBottom: "1rem",
216
+ },
217
+ styleMode: "advanced",
218
+ enabled: true,
219
+ },
220
+ {
221
+ id: "about-secondary-description",
222
+ type: "paragraph",
223
+ slot: "secondary-description",
224
+ order: 5,
225
+ content: {
226
+ text: "Founded with a vision to simplify the digital experience, we have grown into a team of passionate creators dedicated to excellence.",
227
+ },
228
+ style: {
229
+ fontSize: "base",
230
+ color: "#6B7280",
231
+ textAlign: "center",
232
+ lineHeight: "1.75",
233
+ },
234
+ styleMode: "advanced",
235
+ enabled: true,
236
+ },
237
+ {
238
+ id: "about-image",
239
+ type: "image",
240
+ slot: "image",
241
+ order: 6,
242
+ content: {
243
+ src: "https://picsum.photos/seed/about/800/500",
244
+ alt: "About us image",
245
+ },
246
+ style: {
247
+ width: "100%",
248
+ height: "auto",
249
+ borderRadius: "0.75rem",
250
+ marginTop: "2rem",
251
+ },
252
+ styleMode: "advanced",
253
+ enabled: true,
254
+ },
255
+ ],
256
+ },
257
+ ],
258
+ },
259
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Simple About Section Registry
3
+ */
4
+
5
+ import type { SectionComponentProps } from "@onexapis/core/types";
6
+ import { AboutDefault } from "./about-default";
7
+
8
+ export const aboutComponents: Record<
9
+ string,
10
+ React.ComponentType<SectionComponentProps>
11
+ > = {
12
+ default: AboutDefault,
13
+ };
14
+
15
+ export { aboutSchema } from "./about.schema";
@@ -0,0 +1,180 @@
1
+ "use client";
2
+
3
+ import type { SectionComponentProps } from "@onexapis/core/types";
4
+ import coreRenderers from "@onexapis/core/renderers";
5
+ import coreUtils from "@onexapis/core/utils";
6
+
7
+ const { ComponentRenderer } = coreRenderers;
8
+ const { toComponentInstance, getSectionValues, filterEnabledComponents } =
9
+ coreUtils;
10
+
11
+ export function CtaDefault({
12
+ section,
13
+ schema,
14
+ isEditing,
15
+ }: SectionComponentProps) {
16
+ // Get components from the first block (preferred) or fallback to section.components
17
+ const contentBlock = (section.blocks || [])[0];
18
+ const components = contentBlock?.components
19
+ ? filterEnabledComponents(contentBlock.components)
20
+ : filterEnabledComponents(section.components || []);
21
+
22
+ const badgeComp = components.find(
23
+ (c) => c.slot === "badge" || c.id === "cta-badge"
24
+ );
25
+ const headingComp = components.find(
26
+ (c) => c.slot === "heading" || c.id === "cta-heading"
27
+ );
28
+ const descriptionComp = components.find(
29
+ (c) => c.slot === "description" || c.id === "cta-description"
30
+ );
31
+ const dividerComp = components.find(
32
+ (c) => c.slot === "divider" || c.id === "cta-divider"
33
+ );
34
+ const primaryButtonComp = components.find(
35
+ (c) => c.slot === "primary-button" || c.id === "cta-primary-button"
36
+ );
37
+ const secondaryButtonComp = components.find(
38
+ (c) => c.slot === "secondary-button" || c.id === "cta-secondary-button"
39
+ );
40
+ const imageComp = components.find(
41
+ (c) => c.slot === "image" || c.id === "cta-image"
42
+ );
43
+
44
+ const { settings } = getSectionValues(section, schema);
45
+ const { backgroundColor, layout } = settings;
46
+
47
+ const isSplit = layout === "split";
48
+
49
+ // Block-level settings
50
+ const blockSettings = contentBlock?.settings || {};
51
+ const alignMap: Record<string, string> = {
52
+ left: "text-left",
53
+ center: "text-center",
54
+ right: "text-right",
55
+ };
56
+ const widthMap: Record<string, string> = {
57
+ sm: "max-w-2xl",
58
+ md: "max-w-3xl",
59
+ lg: "max-w-4xl",
60
+ full: "max-w-6xl",
61
+ };
62
+ const blockAlign =
63
+ alignMap[blockSettings.contentAlignment as string] || "text-center";
64
+ const blockWidth =
65
+ widthMap[blockSettings.contentWidth as string] || "max-w-3xl";
66
+
67
+ return (
68
+ <section
69
+ className="py-20"
70
+ style={{ backgroundColor: String(backgroundColor || "#3B82F6") }}
71
+ data-section="cta"
72
+ data-section-id={section.id}
73
+ data-section-template="default"
74
+ data-section-name="Simple CTA"
75
+ >
76
+ <div
77
+ className="container mx-auto px-4 max-w-6xl"
78
+ data-section-id={section.id}
79
+ data-block-id={contentBlock?.id || "cta-content-1"}
80
+ data-block-type="cta-content"
81
+ >
82
+ <div
83
+ className={
84
+ isSplit
85
+ ? "grid grid-cols-1 md:grid-cols-2 gap-12 items-center"
86
+ : `${blockAlign} ${blockWidth} mx-auto`
87
+ }
88
+ >
89
+ {/* Content Side */}
90
+ <div>
91
+ {badgeComp && (
92
+ <div
93
+ key="badge-wrapper"
94
+ className={isSplit ? "mb-4" : "mb-4 inline-block"}
95
+ >
96
+ <ComponentRenderer
97
+ instance={toComponentInstance(badgeComp)}
98
+ sectionId={section.id}
99
+ isEditing={isEditing}
100
+ />
101
+ </div>
102
+ )}
103
+
104
+ {headingComp ? (
105
+ <ComponentRenderer
106
+ key="heading"
107
+ instance={toComponentInstance(headingComp)}
108
+ sectionId={section.id}
109
+ isEditing={isEditing}
110
+ />
111
+ ) : (
112
+ <h2
113
+ key="heading-fallback"
114
+ className="text-4xl font-bold text-white mb-4"
115
+ >
116
+ Ready to Get Started?
117
+ </h2>
118
+ )}
119
+
120
+ {descriptionComp && (
121
+ <ComponentRenderer
122
+ key="description"
123
+ instance={toComponentInstance(descriptionComp)}
124
+ sectionId={section.id}
125
+ isEditing={isEditing}
126
+ />
127
+ )}
128
+
129
+ {dividerComp && (
130
+ <ComponentRenderer
131
+ key="divider"
132
+ instance={toComponentInstance(dividerComp)}
133
+ sectionId={section.id}
134
+ isEditing={isEditing}
135
+ />
136
+ )}
137
+
138
+ {/* Button Row */}
139
+ {(primaryButtonComp || secondaryButtonComp) && (
140
+ <div
141
+ key="button-row"
142
+ className={`flex gap-4 ${isSplit ? "" : "justify-center"} flex-wrap`}
143
+ >
144
+ {primaryButtonComp && (
145
+ <ComponentRenderer
146
+ key={primaryButtonComp.id}
147
+ instance={toComponentInstance(primaryButtonComp)}
148
+ sectionId={section.id}
149
+ isEditing={isEditing}
150
+ />
151
+ )}
152
+ {secondaryButtonComp && (
153
+ <ComponentRenderer
154
+ key={secondaryButtonComp.id}
155
+ instance={toComponentInstance(secondaryButtonComp)}
156
+ sectionId={section.id}
157
+ isEditing={isEditing}
158
+ />
159
+ )}
160
+ </div>
161
+ )}
162
+ </div>
163
+
164
+ {/* Image Side (split layout only) */}
165
+ {isSplit && imageComp && (
166
+ <div key="image-wrapper">
167
+ <ComponentRenderer
168
+ instance={toComponentInstance(imageComp)}
169
+ sectionId={section.id}
170
+ isEditing={isEditing}
171
+ />
172
+ </div>
173
+ )}
174
+ </div>
175
+ </div>
176
+ </section>
177
+ );
178
+ }
179
+
180
+ export default CtaDefault;
@@ -0,0 +1,210 @@
1
+ import type { SectionSchema, FieldDefinition } from "@onexapis/core/types";
2
+
3
+ const commonSettings: FieldDefinition[] = [
4
+ {
5
+ id: "backgroundColor",
6
+ type: "color",
7
+ label: "Background Color",
8
+ default: "#3B82F6",
9
+ },
10
+ {
11
+ id: "layout",
12
+ type: "select",
13
+ label: "Layout",
14
+ default: "centered",
15
+ options: [
16
+ { label: "Centered", value: "centered" },
17
+ { label: "Split", value: "split" },
18
+ ],
19
+ },
20
+ ];
21
+
22
+ export const ctaSchema: SectionSchema = {
23
+ type: "my-simple-cta",
24
+ name: "Simple CTA",
25
+ description:
26
+ "Call-to-action section with badge, heading, text, buttons, and optional image",
27
+ category: "cta",
28
+ icon: "megaphone",
29
+ settings: commonSettings,
30
+ templates: [
31
+ {
32
+ id: "default",
33
+ name: "Default CTA",
34
+ description: "A bold call-to-action section",
35
+ },
36
+ ],
37
+ blocks: [
38
+ {
39
+ type: "cta-content",
40
+ name: "CTA Content",
41
+ description:
42
+ "CTA content block with badge, heading, text, buttons, and image",
43
+ icon: "megaphone",
44
+ settings: [
45
+ {
46
+ id: "contentAlignment",
47
+ type: "select",
48
+ label: "Content Alignment",
49
+ default: "center",
50
+ options: [
51
+ { label: "Left", value: "left" },
52
+ { label: "Center", value: "center" },
53
+ { label: "Right", value: "right" },
54
+ ],
55
+ },
56
+ {
57
+ id: "contentWidth",
58
+ type: "select",
59
+ label: "Content Width",
60
+ default: "lg",
61
+ options: [
62
+ { label: "Small", value: "sm" },
63
+ { label: "Medium", value: "md" },
64
+ { label: "Large", value: "lg" },
65
+ { label: "Full", value: "full" },
66
+ ],
67
+ },
68
+ ],
69
+ defaults: {
70
+ contentAlignment: "center",
71
+ contentWidth: "lg",
72
+ },
73
+ limit: 1,
74
+ },
75
+ ],
76
+ maxBlocks: 1,
77
+ defaults: {
78
+ settings: {
79
+ backgroundColor: "#3B82F6",
80
+ layout: "centered",
81
+ },
82
+ blocks: [
83
+ {
84
+ id: "cta-content-1",
85
+ type: "cta-content",
86
+ order: 0,
87
+ enabled: true,
88
+ settings: {},
89
+ components: [
90
+ {
91
+ id: "cta-badge",
92
+ type: "badge",
93
+ slot: "badge",
94
+ order: 0,
95
+ content: { text: "Limited Time" },
96
+ style: {
97
+ fontSize: "sm",
98
+ fontWeight: "semibold",
99
+ color: "#3B82F6",
100
+ backgroundColor: "#FFFFFF",
101
+ padding: "0.25rem 0.75rem",
102
+ borderRadius: "9999px",
103
+ },
104
+ styleMode: "advanced",
105
+ enabled: true,
106
+ },
107
+ {
108
+ id: "cta-heading",
109
+ type: "heading",
110
+ slot: "heading",
111
+ order: 1,
112
+ content: { text: "Ready to Get Started?", tag: "h2" },
113
+ style: {
114
+ fontSize: "4xl",
115
+ fontWeight: "bold",
116
+ color: "#FFFFFF",
117
+ marginBottom: "1rem",
118
+ },
119
+ styleMode: "advanced",
120
+ enabled: true,
121
+ },
122
+ {
123
+ id: "cta-description",
124
+ type: "paragraph",
125
+ slot: "description",
126
+ order: 2,
127
+ content: {
128
+ text: "Join thousands of satisfied customers and take your business to the next level. Start your free trial today.",
129
+ },
130
+ style: {
131
+ fontSize: "lg",
132
+ color: "rgba(255,255,255,0.9)",
133
+ marginBottom: "1rem",
134
+ lineHeight: "1.6",
135
+ },
136
+ styleMode: "advanced",
137
+ enabled: true,
138
+ },
139
+ {
140
+ id: "cta-divider",
141
+ type: "divider",
142
+ slot: "divider",
143
+ order: 3,
144
+ content: {},
145
+ style: {
146
+ borderColor: "rgba(255,255,255,0.3)",
147
+ marginTop: "1rem",
148
+ marginBottom: "1.5rem",
149
+ },
150
+ styleMode: "advanced",
151
+ enabled: true,
152
+ },
153
+ {
154
+ id: "cta-primary-button",
155
+ type: "button",
156
+ slot: "primary-button",
157
+ order: 4,
158
+ content: { text: "Start Free Trial", href: "/register" },
159
+ style: {
160
+ fontSize: "base",
161
+ fontWeight: "semibold",
162
+ color: "#3B82F6",
163
+ backgroundColor: "#FFFFFF",
164
+ padding: "0.75rem 2rem",
165
+ borderRadius: "0.5rem",
166
+ },
167
+ styleMode: "advanced",
168
+ enabled: true,
169
+ },
170
+ {
171
+ id: "cta-secondary-button",
172
+ type: "button",
173
+ slot: "secondary-button",
174
+ order: 5,
175
+ content: { text: "Learn More", href: "/about" },
176
+ style: {
177
+ fontSize: "base",
178
+ fontWeight: "semibold",
179
+ color: "#FFFFFF",
180
+ backgroundColor: "transparent",
181
+ padding: "0.75rem 2rem",
182
+ borderRadius: "0.5rem",
183
+ borderWidth: "2px",
184
+ borderColor: "#FFFFFF",
185
+ },
186
+ styleMode: "advanced",
187
+ enabled: true,
188
+ },
189
+ {
190
+ id: "cta-image",
191
+ type: "image",
192
+ slot: "image",
193
+ order: 6,
194
+ content: {
195
+ src: "https://picsum.photos/seed/cta/600/400",
196
+ alt: "Get started illustration",
197
+ },
198
+ style: {
199
+ width: "100%",
200
+ height: "auto",
201
+ borderRadius: "0.75rem",
202
+ },
203
+ styleMode: "advanced",
204
+ enabled: true,
205
+ },
206
+ ],
207
+ },
208
+ ],
209
+ },
210
+ };
@@ -0,0 +1,11 @@
1
+ import type { SectionComponentProps } from "@onexapis/core/types";
2
+ import { CtaDefault } from "./cta-default";
3
+
4
+ export const ctaComponents: Record<
5
+ string,
6
+ React.ComponentType<SectionComponentProps>
7
+ > = {
8
+ default: CtaDefault,
9
+ };
10
+
11
+ export { ctaSchema } from "./cta.schema";