@onexapis/cli 1.1.17 → 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 (61) hide show
  1. package/README.md +82 -16
  2. package/dist/cli.js +522 -286
  3. package/dist/cli.js.map +1 -1
  4. package/dist/cli.mjs +519 -283
  5. package/dist/cli.mjs.map +1 -1
  6. package/dist/index.js +47 -270
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.mjs +47 -270
  9. package/dist/index.mjs.map +1 -1
  10. package/package.json +1 -1
  11. package/templates/default/.env.example +1 -1
  12. package/templates/default/.mcp.json +8 -0
  13. package/templates/default/CLAUDE.md +941 -0
  14. package/templates/default/bundle-entry.ts +18 -0
  15. package/templates/default/index.ts +26 -0
  16. package/templates/default/package.json +37 -0
  17. package/templates/default/pages/about.ts +66 -0
  18. package/templates/default/pages/home.ts +93 -0
  19. package/templates/default/pages/showcase.ts +146 -0
  20. package/templates/default/sections/about/about-default.tsx +237 -0
  21. package/templates/default/sections/about/about.schema.ts +259 -0
  22. package/templates/default/sections/about/index.ts +15 -0
  23. package/templates/default/sections/cta/cta-default.tsx +180 -0
  24. package/templates/default/sections/cta/cta.schema.ts +210 -0
  25. package/templates/default/sections/cta/index.ts +11 -0
  26. package/templates/default/sections/features/features-default.tsx +154 -0
  27. package/templates/default/sections/features/features.schema.ts +330 -0
  28. package/templates/default/sections/features/index.ts +11 -0
  29. package/templates/default/sections/gallery/gallery-default.tsx +134 -0
  30. package/templates/default/sections/gallery/gallery.schema.ts +397 -0
  31. package/templates/default/sections/gallery/index.ts +11 -0
  32. package/templates/default/sections/hero/hero-default.tsx +212 -0
  33. package/templates/default/sections/hero/hero.schema.ts +273 -0
  34. package/templates/default/sections/hero/index.ts +15 -0
  35. package/templates/default/sections/stats/index.ts +11 -0
  36. package/templates/default/sections/stats/stats-default.tsx +103 -0
  37. package/templates/default/sections/stats/stats.schema.ts +266 -0
  38. package/templates/default/sections/testimonials/index.ts +11 -0
  39. package/templates/default/sections/testimonials/testimonials-default.tsx +130 -0
  40. package/templates/default/sections/testimonials/testimonials.schema.ts +371 -0
  41. package/templates/default/sections-registry.ts +32 -0
  42. package/templates/default/theme.config.ts +107 -0
  43. package/templates/default/theme.layout.ts +21 -0
  44. package/templates/default/tsconfig.json +16 -7
  45. package/templates/default/README.md.ejs +0 -129
  46. package/templates/default/esbuild.config.js +0 -81
  47. package/templates/default/package.json.ejs +0 -31
  48. package/templates/default/src/config.ts.ejs +0 -98
  49. package/templates/default/src/index.ts.ejs +0 -11
  50. package/templates/default/src/layout.ts +0 -23
  51. package/templates/default/src/manifest.ts.ejs +0 -47
  52. package/templates/default/src/pages/home.ts.ejs +0 -37
  53. package/templates/default/src/sections/footer/footer-default.tsx +0 -28
  54. package/templates/default/src/sections/footer/footer.schema.ts +0 -45
  55. package/templates/default/src/sections/footer/index.ts +0 -2
  56. package/templates/default/src/sections/header/header-default.tsx +0 -61
  57. package/templates/default/src/sections/header/header.schema.ts +0 -46
  58. package/templates/default/src/sections/header/index.ts +0 -2
  59. package/templates/default/src/sections/hero/hero-default.tsx +0 -52
  60. package/templates/default/src/sections/hero/hero.schema.ts +0 -52
  61. package/templates/default/src/sections/hero/index.ts +0 -2
@@ -0,0 +1,154 @@
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, BlockRenderer } = coreRenderers;
8
+ const { toComponentInstance, getSectionValues, filterEnabledComponents } =
9
+ coreUtils;
10
+
11
+ export function FeaturesDefault({
12
+ section,
13
+ schema,
14
+ isEditing,
15
+ }: SectionComponentProps) {
16
+ const { settings } = getSectionValues(section, schema);
17
+ const { sectionTitle, sectionSubtitle, backgroundColor } = settings;
18
+
19
+ // Section-level components (title, subtitle)
20
+ const components = filterEnabledComponents(section.components || []);
21
+ const titleComp = components.find(
22
+ (c) => c.slot === "section-title" || c.id === "features-title"
23
+ );
24
+ const subtitleComp = components.find(
25
+ (c) => c.slot === "section-subtitle" || c.id === "features-subtitle"
26
+ );
27
+
28
+ // Parent container block (optional — data may use container or flat structure)
29
+ const containerBlock = (section.blocks || []).find(
30
+ (b) => b.type === "features-container"
31
+ );
32
+ const containerSettings = containerBlock?.settings || {};
33
+ const columns = containerSettings.columns || settings.columns || "3";
34
+ const gap = containerSettings.gap || settings.gap || "lg";
35
+
36
+ // Support both: nested blocks inside container, or flat feature-item blocks directly on section
37
+ const rawBlocks = containerBlock?.blocks || section.blocks || [];
38
+ const featureBlocks = rawBlocks
39
+ .filter((b) => b.type === "feature-item" && b.enabled !== false)
40
+ .sort((a, b) => (a.order || 0) - (b.order || 0));
41
+
42
+ const colClass =
43
+ columns === "2"
44
+ ? "md:grid-cols-2"
45
+ : columns === "4"
46
+ ? "md:grid-cols-2 lg:grid-cols-4"
47
+ : "md:grid-cols-3";
48
+
49
+ const gapClass = gap === "sm" ? "gap-4" : gap === "md" ? "gap-6" : "gap-8";
50
+
51
+ return (
52
+ <section
53
+ className="py-16"
54
+ style={{ backgroundColor: String(backgroundColor || "#F9FAFB") }}
55
+ data-section="features"
56
+ data-section-id={section.id}
57
+ data-section-template="default"
58
+ data-section-name="Simple Features"
59
+ >
60
+ <div className="container mx-auto px-4 max-w-6xl">
61
+ {/* Section Header (section-level components) */}
62
+ <div className="text-center mb-12">
63
+ {titleComp ? (
64
+ <ComponentRenderer
65
+ key="section-title"
66
+ instance={toComponentInstance(titleComp)}
67
+ sectionId={section.id}
68
+ isEditing={isEditing}
69
+ />
70
+ ) : sectionTitle ? (
71
+ <h2
72
+ key="section-title-fallback"
73
+ className="text-3xl font-bold text-gray-900 mb-2"
74
+ >
75
+ {String(sectionTitle)}
76
+ </h2>
77
+ ) : null}
78
+
79
+ {subtitleComp ? (
80
+ <ComponentRenderer
81
+ key="section-subtitle"
82
+ instance={toComponentInstance(subtitleComp)}
83
+ sectionId={section.id}
84
+ isEditing={isEditing}
85
+ />
86
+ ) : sectionSubtitle ? (
87
+ <p
88
+ key="section-subtitle-fallback"
89
+ className="text-lg text-gray-500 mb-12"
90
+ >
91
+ {String(sectionSubtitle)}
92
+ </p>
93
+ ) : null}
94
+ </div>
95
+
96
+ {/* Features Grid (parent container block → nested feature-item blocks) */}
97
+ <div
98
+ className={`grid grid-cols-1 ${colClass} ${gapClass}`}
99
+ data-section-id={section.id}
100
+ data-block-id={containerBlock?.id || "features-container-1"}
101
+ data-block-type="features-container"
102
+ >
103
+ {featureBlocks.map((block) => {
104
+ const bs = block.settings || {};
105
+ const radiusMap: Record<string, string> = {
106
+ none: "rounded-none",
107
+ sm: "rounded-sm",
108
+ md: "rounded-md",
109
+ xl: "rounded-xl",
110
+ };
111
+ const paddingMap: Record<string, string> = {
112
+ sm: "p-4",
113
+ md: "p-6",
114
+ lg: "p-8",
115
+ };
116
+ const radius = radiusMap[bs.borderRadius as string] || "rounded-xl";
117
+ const padding = paddingMap[bs.padding as string] || "p-6";
118
+ const shadow =
119
+ bs.showShadow !== false ? "shadow-sm hover:shadow-md" : "";
120
+ return (
121
+ <div
122
+ key={block.id}
123
+ className={`${radius} ${padding} ${shadow} transition-shadow`}
124
+ style={{
125
+ backgroundColor: String(bs.backgroundColor || "#FFFFFF"),
126
+ }}
127
+ data-section-id={section.id}
128
+ data-block-id={block.id}
129
+ data-block-type={block.type}
130
+ >
131
+ <BlockRenderer
132
+ block={block}
133
+ sectionId={section.id}
134
+ isEditing={isEditing}
135
+ />
136
+ </div>
137
+ );
138
+ })}
139
+ </div>
140
+
141
+ {/* Empty state for editor */}
142
+ {featureBlocks.length === 0 && isEditing && (
143
+ <div className="text-center py-12 border-2 border-dashed border-gray-300 rounded-lg">
144
+ <p className="text-gray-500">
145
+ Add feature blocks to populate this section
146
+ </p>
147
+ </div>
148
+ )}
149
+ </div>
150
+ </section>
151
+ );
152
+ }
153
+
154
+ export default FeaturesDefault;
@@ -0,0 +1,330 @@
1
+ import type { SectionSchema, FieldDefinition } from "@onexapis/core/types";
2
+
3
+ const sectionSettings: FieldDefinition[] = [
4
+ {
5
+ id: "sectionTitle",
6
+ type: "text",
7
+ label: "Section Title",
8
+ default: "Our Features",
9
+ },
10
+ {
11
+ id: "sectionSubtitle",
12
+ type: "textarea",
13
+ label: "Section Subtitle",
14
+ default: "Everything you need to build something great",
15
+ },
16
+ {
17
+ id: "backgroundColor",
18
+ type: "color",
19
+ label: "Background Color",
20
+ default: "#F9FAFB",
21
+ },
22
+ ];
23
+
24
+ export const featuresSchema: SectionSchema = {
25
+ type: "my-simple-features",
26
+ name: "Simple Features",
27
+ description: "Feature grid with icon, heading, and description blocks",
28
+ category: "features",
29
+ icon: "grid",
30
+ settings: sectionSettings,
31
+ templates: [
32
+ {
33
+ id: "default",
34
+ name: "Default Features",
35
+ description: "A grid of feature blocks with icons",
36
+ },
37
+ ],
38
+ blocks: [
39
+ {
40
+ type: "features-container",
41
+ name: "Features Grid",
42
+ description: "Grid container for feature items",
43
+ icon: "grid",
44
+ settings: [
45
+ {
46
+ id: "columns",
47
+ type: "select",
48
+ label: "Columns",
49
+ default: "3",
50
+ options: [
51
+ { label: "2 Columns", value: "2" },
52
+ { label: "3 Columns", value: "3" },
53
+ { label: "4 Columns", value: "4" },
54
+ ],
55
+ },
56
+ {
57
+ id: "gap",
58
+ type: "select",
59
+ label: "Gap Size",
60
+ default: "lg",
61
+ options: [
62
+ { label: "Small", value: "sm" },
63
+ { label: "Medium", value: "md" },
64
+ { label: "Large", value: "lg" },
65
+ ],
66
+ },
67
+ ],
68
+ defaults: {
69
+ columns: "3",
70
+ gap: "lg",
71
+ },
72
+ limit: 1,
73
+ },
74
+ {
75
+ type: "feature-item",
76
+ name: "Feature Item",
77
+ description: "A single feature with icon, title, and description",
78
+ icon: "star",
79
+ settings: [
80
+ {
81
+ id: "backgroundColor",
82
+ type: "color",
83
+ label: "Background Color",
84
+ default: "#FFFFFF",
85
+ },
86
+ {
87
+ id: "borderRadius",
88
+ type: "select",
89
+ label: "Border Radius",
90
+ default: "xl",
91
+ options: [
92
+ { label: "None", value: "none" },
93
+ { label: "Small", value: "sm" },
94
+ { label: "Medium", value: "md" },
95
+ { label: "Large", value: "xl" },
96
+ ],
97
+ },
98
+ {
99
+ id: "padding",
100
+ type: "select",
101
+ label: "Padding",
102
+ default: "md",
103
+ options: [
104
+ { label: "Small", value: "sm" },
105
+ { label: "Medium", value: "md" },
106
+ { label: "Large", value: "lg" },
107
+ ],
108
+ },
109
+ {
110
+ id: "showShadow",
111
+ type: "checkbox",
112
+ label: "Show Shadow",
113
+ default: true,
114
+ },
115
+ ],
116
+ defaults: {
117
+ backgroundColor: "#FFFFFF",
118
+ borderRadius: "xl",
119
+ padding: "md",
120
+ showShadow: true,
121
+ },
122
+ limit: 12,
123
+ },
124
+ ],
125
+ maxBlocks: 13,
126
+ defaults: {
127
+ settings: {
128
+ sectionTitle: "Our Features",
129
+ sectionSubtitle: "Everything you need to build something great",
130
+ backgroundColor: "#F9FAFB",
131
+ },
132
+ components: [
133
+ {
134
+ id: "features-title",
135
+ type: "heading",
136
+ slot: "section-title",
137
+ order: 0,
138
+ content: { text: "Our Features", tag: "h2" },
139
+ style: {
140
+ fontSize: "3xl",
141
+ fontWeight: "bold",
142
+ color: "#111827",
143
+ textAlign: "center",
144
+ marginBottom: "0.5rem",
145
+ },
146
+ styleMode: "advanced",
147
+ enabled: true,
148
+ },
149
+ {
150
+ id: "features-subtitle",
151
+ type: "paragraph",
152
+ slot: "section-subtitle",
153
+ order: 1,
154
+ content: { text: "Everything you need to build something great" },
155
+ style: {
156
+ fontSize: "lg",
157
+ color: "#6B7280",
158
+ textAlign: "center",
159
+ marginBottom: "3rem",
160
+ },
161
+ styleMode: "advanced",
162
+ enabled: true,
163
+ },
164
+ ],
165
+ blocks: [
166
+ {
167
+ id: "features-container-1",
168
+ type: "features-container",
169
+ order: 0,
170
+ enabled: true,
171
+ settings: {
172
+ columns: "3",
173
+ gap: "lg",
174
+ },
175
+ blocks: [
176
+ {
177
+ id: "feature-1",
178
+ type: "feature-item",
179
+ order: 0,
180
+ enabled: true,
181
+ settings: {},
182
+ components: [
183
+ {
184
+ id: "feature-1-icon",
185
+ type: "icon",
186
+ slot: "icon",
187
+ order: 0,
188
+ content: { icon: "zap", text: "" },
189
+ style: { fontSize: "2xl", color: "#3B82F6" },
190
+ styleMode: "advanced",
191
+ enabled: true,
192
+ },
193
+ {
194
+ id: "feature-1-title",
195
+ type: "heading",
196
+ slot: "title",
197
+ order: 1,
198
+ content: { text: "Lightning Fast", tag: "h3" },
199
+ style: {
200
+ fontSize: "xl",
201
+ fontWeight: "semibold",
202
+ color: "#111827",
203
+ marginBottom: "0.5rem",
204
+ },
205
+ styleMode: "advanced",
206
+ enabled: true,
207
+ },
208
+ {
209
+ id: "feature-1-desc",
210
+ type: "paragraph",
211
+ slot: "description",
212
+ order: 2,
213
+ content: {
214
+ text: "Built for speed with optimized performance at every level.",
215
+ },
216
+ style: {
217
+ fontSize: "base",
218
+ color: "#6B7280",
219
+ lineHeight: "1.6",
220
+ },
221
+ styleMode: "advanced",
222
+ enabled: true,
223
+ },
224
+ ],
225
+ },
226
+ {
227
+ id: "feature-2",
228
+ type: "feature-item",
229
+ order: 1,
230
+ enabled: true,
231
+ settings: {},
232
+ components: [
233
+ {
234
+ id: "feature-2-icon",
235
+ type: "icon",
236
+ slot: "icon",
237
+ order: 0,
238
+ content: { icon: "shield", text: "" },
239
+ style: { fontSize: "2xl", color: "#3B82F6" },
240
+ styleMode: "advanced",
241
+ enabled: true,
242
+ },
243
+ {
244
+ id: "feature-2-title",
245
+ type: "heading",
246
+ slot: "title",
247
+ order: 1,
248
+ content: { text: "Secure by Default", tag: "h3" },
249
+ style: {
250
+ fontSize: "xl",
251
+ fontWeight: "semibold",
252
+ color: "#111827",
253
+ marginBottom: "0.5rem",
254
+ },
255
+ styleMode: "advanced",
256
+ enabled: true,
257
+ },
258
+ {
259
+ id: "feature-2-desc",
260
+ type: "paragraph",
261
+ slot: "description",
262
+ order: 2,
263
+ content: {
264
+ text: "Enterprise-grade security built into every feature.",
265
+ },
266
+ style: {
267
+ fontSize: "base",
268
+ color: "#6B7280",
269
+ lineHeight: "1.6",
270
+ },
271
+ styleMode: "advanced",
272
+ enabled: true,
273
+ },
274
+ ],
275
+ },
276
+ {
277
+ id: "feature-3",
278
+ type: "feature-item",
279
+ order: 2,
280
+ enabled: true,
281
+ settings: {},
282
+ components: [
283
+ {
284
+ id: "feature-3-icon",
285
+ type: "icon",
286
+ slot: "icon",
287
+ order: 0,
288
+ content: { icon: "palette", text: "" },
289
+ style: { fontSize: "2xl", color: "#3B82F6" },
290
+ styleMode: "advanced",
291
+ enabled: true,
292
+ },
293
+ {
294
+ id: "feature-3-title",
295
+ type: "heading",
296
+ slot: "title",
297
+ order: 1,
298
+ content: { text: "Beautiful Design", tag: "h3" },
299
+ style: {
300
+ fontSize: "xl",
301
+ fontWeight: "semibold",
302
+ color: "#111827",
303
+ marginBottom: "0.5rem",
304
+ },
305
+ styleMode: "advanced",
306
+ enabled: true,
307
+ },
308
+ {
309
+ id: "feature-3-desc",
310
+ type: "paragraph",
311
+ slot: "description",
312
+ order: 2,
313
+ content: {
314
+ text: "Pixel-perfect designs that look great on any device.",
315
+ },
316
+ style: {
317
+ fontSize: "base",
318
+ color: "#6B7280",
319
+ lineHeight: "1.6",
320
+ },
321
+ styleMode: "advanced",
322
+ enabled: true,
323
+ },
324
+ ],
325
+ },
326
+ ],
327
+ },
328
+ ],
329
+ },
330
+ };
@@ -0,0 +1,11 @@
1
+ import type { SectionComponentProps } from "@onexapis/core/types";
2
+ import { FeaturesDefault } from "./features-default";
3
+
4
+ export const featuresComponents: Record<
5
+ string,
6
+ React.ComponentType<SectionComponentProps>
7
+ > = {
8
+ default: FeaturesDefault,
9
+ };
10
+
11
+ export { featuresSchema } from "./features.schema";
@@ -0,0 +1,134 @@
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, BlockRenderer } = coreRenderers;
8
+ const { toComponentInstance, getSectionValues, filterEnabledComponents } =
9
+ coreUtils;
10
+
11
+ export function GalleryDefault({
12
+ section,
13
+ schema,
14
+ isEditing,
15
+ }: SectionComponentProps) {
16
+ const components = filterEnabledComponents(section.components || []);
17
+ const titleComp = components.find(
18
+ (c) => c.slot === "section-title" || c.id === "gallery-title"
19
+ );
20
+ const subtitleComp = components.find(
21
+ (c) => c.slot === "section-subtitle" || c.id === "gallery-subtitle"
22
+ );
23
+
24
+ const { settings } = getSectionValues(section, schema);
25
+ const { sectionTitle, sectionSubtitle, columns, gap, backgroundColor } =
26
+ settings;
27
+
28
+ const colClass =
29
+ columns === "2"
30
+ ? "md:grid-cols-2"
31
+ : columns === "4"
32
+ ? "md:grid-cols-2 lg:grid-cols-4"
33
+ : "md:grid-cols-3";
34
+
35
+ const gapClass = gap === "sm" ? "gap-4" : gap === "lg" ? "gap-8" : "gap-6";
36
+
37
+ const blocks = (section.blocks || [])
38
+ .filter((b) => b.enabled !== false)
39
+ .sort((a, b) => (a.order || 0) - (b.order || 0));
40
+
41
+ return (
42
+ <section
43
+ className="py-16"
44
+ style={{ backgroundColor: String(backgroundColor || "#FFFFFF") }}
45
+ data-section="gallery"
46
+ data-section-id={section.id}
47
+ data-section-template="default"
48
+ data-section-name="Simple Gallery"
49
+ >
50
+ <div className="container mx-auto px-4 max-w-6xl">
51
+ {/* Section Header */}
52
+ <div className="text-center mb-12">
53
+ {titleComp ? (
54
+ <ComponentRenderer
55
+ key="section-title"
56
+ instance={toComponentInstance(titleComp)}
57
+ sectionId={section.id}
58
+ isEditing={isEditing}
59
+ />
60
+ ) : sectionTitle ? (
61
+ <h2
62
+ key="section-title-fallback"
63
+ className="text-3xl font-bold text-gray-900 mb-2"
64
+ >
65
+ {String(sectionTitle)}
66
+ </h2>
67
+ ) : null}
68
+
69
+ {subtitleComp ? (
70
+ <ComponentRenderer
71
+ key="section-subtitle"
72
+ instance={toComponentInstance(subtitleComp)}
73
+ sectionId={section.id}
74
+ isEditing={isEditing}
75
+ />
76
+ ) : sectionSubtitle ? (
77
+ <p
78
+ key="section-subtitle-fallback"
79
+ className="text-lg text-gray-500 mb-12"
80
+ >
81
+ {String(sectionSubtitle)}
82
+ </p>
83
+ ) : null}
84
+ </div>
85
+
86
+ {/* Gallery Grid */}
87
+ <div className={`grid grid-cols-1 ${colClass} ${gapClass}`}>
88
+ {blocks.map((block) => {
89
+ const bs = block.settings || {};
90
+ const radiusMap: Record<string, string> = {
91
+ none: "rounded-none",
92
+ sm: "rounded-sm",
93
+ md: "rounded-md",
94
+ lg: "rounded-lg",
95
+ };
96
+ const radius = radiusMap[bs.borderRadius as string] || "rounded-lg";
97
+ const aspectMap: Record<string, string> = {
98
+ square: "aspect-square",
99
+ landscape: "aspect-[4/3]",
100
+ wide: "aspect-video",
101
+ };
102
+ const aspect = aspectMap[bs.aspectRatio as string] || "";
103
+ return (
104
+ <div
105
+ key={block.id}
106
+ className={`overflow-hidden ${radius} ${aspect} group`}
107
+ data-section-id={section.id}
108
+ data-block-id={block.id}
109
+ data-block-type={block.type}
110
+ >
111
+ <BlockRenderer
112
+ block={block}
113
+ sectionId={section.id}
114
+ isEditing={isEditing}
115
+ />
116
+ </div>
117
+ );
118
+ })}
119
+ </div>
120
+
121
+ {/* Empty state for editor */}
122
+ {blocks.length === 0 && isEditing && (
123
+ <div className="text-center py-12 border-2 border-dashed border-gray-300 rounded-lg">
124
+ <p className="text-gray-500">
125
+ Add gallery items to populate this section
126
+ </p>
127
+ </div>
128
+ )}
129
+ </div>
130
+ </section>
131
+ );
132
+ }
133
+
134
+ export default GalleryDefault;