@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,397 @@
1
+ import type { SectionSchema, FieldDefinition } from "@onexapis/core/types";
2
+
3
+ const commonSettings: FieldDefinition[] = [
4
+ {
5
+ id: "sectionTitle",
6
+ type: "text",
7
+ label: "Section Title",
8
+ default: "Gallery",
9
+ },
10
+ {
11
+ id: "sectionSubtitle",
12
+ type: "textarea",
13
+ label: "Section Subtitle",
14
+ default: "A showcase of our finest work",
15
+ },
16
+ {
17
+ id: "columns",
18
+ type: "select",
19
+ label: "Columns",
20
+ default: "3",
21
+ options: [
22
+ { label: "2 Columns", value: "2" },
23
+ { label: "3 Columns", value: "3" },
24
+ { label: "4 Columns", value: "4" },
25
+ ],
26
+ },
27
+ {
28
+ id: "gap",
29
+ type: "select",
30
+ label: "Gap Size",
31
+ default: "md",
32
+ options: [
33
+ { label: "Small", value: "sm" },
34
+ { label: "Medium", value: "md" },
35
+ { label: "Large", value: "lg" },
36
+ ],
37
+ },
38
+ {
39
+ id: "backgroundColor",
40
+ type: "color",
41
+ label: "Background Color",
42
+ default: "#FFFFFF",
43
+ },
44
+ ];
45
+
46
+ export const gallerySchema: SectionSchema = {
47
+ type: "my-simple-gallery",
48
+ name: "Simple Gallery",
49
+ description: "Responsive image gallery with captions",
50
+ category: "gallery",
51
+ icon: "image",
52
+ settings: commonSettings,
53
+ templates: [
54
+ {
55
+ id: "default",
56
+ name: "Default Gallery",
57
+ description: "A responsive grid of image cards with captions",
58
+ },
59
+ ],
60
+ blocks: [
61
+ {
62
+ type: "gallery-item",
63
+ name: "Gallery Item",
64
+ description: "A single gallery image with optional caption",
65
+ icon: "image",
66
+ settings: [
67
+ {
68
+ id: "aspectRatio",
69
+ type: "select",
70
+ label: "Aspect Ratio",
71
+ default: "auto",
72
+ options: [
73
+ { label: "Auto", value: "auto" },
74
+ { label: "Square (1:1)", value: "square" },
75
+ { label: "Landscape (4:3)", value: "landscape" },
76
+ { label: "Wide (16:9)", value: "wide" },
77
+ ],
78
+ },
79
+ {
80
+ id: "borderRadius",
81
+ type: "select",
82
+ label: "Border Radius",
83
+ default: "lg",
84
+ options: [
85
+ { label: "None", value: "none" },
86
+ { label: "Small", value: "sm" },
87
+ { label: "Medium", value: "md" },
88
+ { label: "Large", value: "lg" },
89
+ ],
90
+ },
91
+ {
92
+ id: "showCaption",
93
+ type: "checkbox",
94
+ label: "Show Caption",
95
+ default: true,
96
+ },
97
+ ],
98
+ defaults: {
99
+ aspectRatio: "auto",
100
+ borderRadius: "lg",
101
+ showCaption: true,
102
+ },
103
+ limit: 24,
104
+ },
105
+ ],
106
+ maxBlocks: 24,
107
+ defaults: {
108
+ settings: {
109
+ sectionTitle: "Gallery",
110
+ sectionSubtitle: "A showcase of our finest work",
111
+ columns: "3",
112
+ gap: "md",
113
+ backgroundColor: "#FFFFFF",
114
+ },
115
+ components: [
116
+ {
117
+ id: "gallery-title",
118
+ type: "heading",
119
+ slot: "section-title",
120
+ order: 0,
121
+ content: { text: "Gallery", tag: "h2" },
122
+ style: {
123
+ fontSize: "3xl",
124
+ fontWeight: "bold",
125
+ color: "#111827",
126
+ textAlign: "center",
127
+ marginBottom: "0.5rem",
128
+ },
129
+ styleMode: "advanced",
130
+ enabled: true,
131
+ },
132
+ {
133
+ id: "gallery-subtitle",
134
+ type: "paragraph",
135
+ slot: "section-subtitle",
136
+ order: 1,
137
+ content: { text: "A showcase of our finest work" },
138
+ style: {
139
+ fontSize: "lg",
140
+ color: "#6B7280",
141
+ textAlign: "center",
142
+ marginBottom: "3rem",
143
+ },
144
+ styleMode: "advanced",
145
+ enabled: true,
146
+ },
147
+ ],
148
+ blocks: [
149
+ {
150
+ id: "gallery-1",
151
+ type: "gallery-item",
152
+ order: 0,
153
+ enabled: true,
154
+ settings: {},
155
+ components: [
156
+ {
157
+ id: "gallery-1-image",
158
+ type: "image",
159
+ slot: "image",
160
+ order: 0,
161
+ content: {
162
+ src: "https://picsum.photos/seed/gallery1/600/400",
163
+ alt: "Gallery image 1",
164
+ },
165
+ style: {
166
+ width: "100%",
167
+ height: "auto",
168
+ borderRadius: "0.5rem",
169
+ },
170
+ styleMode: "advanced",
171
+ enabled: true,
172
+ },
173
+ {
174
+ id: "gallery-1-caption",
175
+ type: "paragraph",
176
+ slot: "caption",
177
+ order: 1,
178
+ content: { text: "Creative workspace design" },
179
+ style: {
180
+ fontSize: "sm",
181
+ color: "#6B7280",
182
+ textAlign: "center",
183
+ marginTop: "0.5rem",
184
+ },
185
+ styleMode: "advanced",
186
+ enabled: true,
187
+ },
188
+ ],
189
+ },
190
+ {
191
+ id: "gallery-2",
192
+ type: "gallery-item",
193
+ order: 1,
194
+ enabled: true,
195
+ settings: {},
196
+ components: [
197
+ {
198
+ id: "gallery-2-image",
199
+ type: "image",
200
+ slot: "image",
201
+ order: 0,
202
+ content: {
203
+ src: "https://picsum.photos/seed/gallery2/600/400",
204
+ alt: "Gallery image 2",
205
+ },
206
+ style: {
207
+ width: "100%",
208
+ height: "auto",
209
+ borderRadius: "0.5rem",
210
+ },
211
+ styleMode: "advanced",
212
+ enabled: true,
213
+ },
214
+ {
215
+ id: "gallery-2-caption",
216
+ type: "paragraph",
217
+ slot: "caption",
218
+ order: 1,
219
+ content: { text: "Modern architecture" },
220
+ style: {
221
+ fontSize: "sm",
222
+ color: "#6B7280",
223
+ textAlign: "center",
224
+ marginTop: "0.5rem",
225
+ },
226
+ styleMode: "advanced",
227
+ enabled: true,
228
+ },
229
+ ],
230
+ },
231
+ {
232
+ id: "gallery-3",
233
+ type: "gallery-item",
234
+ order: 2,
235
+ enabled: true,
236
+ settings: {},
237
+ components: [
238
+ {
239
+ id: "gallery-3-image",
240
+ type: "image",
241
+ slot: "image",
242
+ order: 0,
243
+ content: {
244
+ src: "https://picsum.photos/seed/gallery3/600/400",
245
+ alt: "Gallery image 3",
246
+ },
247
+ style: {
248
+ width: "100%",
249
+ height: "auto",
250
+ borderRadius: "0.5rem",
251
+ },
252
+ styleMode: "advanced",
253
+ enabled: true,
254
+ },
255
+ {
256
+ id: "gallery-3-caption",
257
+ type: "paragraph",
258
+ slot: "caption",
259
+ order: 1,
260
+ content: { text: "Nature photography" },
261
+ style: {
262
+ fontSize: "sm",
263
+ color: "#6B7280",
264
+ textAlign: "center",
265
+ marginTop: "0.5rem",
266
+ },
267
+ styleMode: "advanced",
268
+ enabled: true,
269
+ },
270
+ ],
271
+ },
272
+ {
273
+ id: "gallery-4",
274
+ type: "gallery-item",
275
+ order: 3,
276
+ enabled: true,
277
+ settings: {},
278
+ components: [
279
+ {
280
+ id: "gallery-4-image",
281
+ type: "image",
282
+ slot: "image",
283
+ order: 0,
284
+ content: {
285
+ src: "https://picsum.photos/seed/gallery4/600/400",
286
+ alt: "Gallery image 4",
287
+ },
288
+ style: {
289
+ width: "100%",
290
+ height: "auto",
291
+ borderRadius: "0.5rem",
292
+ },
293
+ styleMode: "advanced",
294
+ enabled: true,
295
+ },
296
+ {
297
+ id: "gallery-4-caption",
298
+ type: "paragraph",
299
+ slot: "caption",
300
+ order: 1,
301
+ content: { text: "Urban landscape" },
302
+ style: {
303
+ fontSize: "sm",
304
+ color: "#6B7280",
305
+ textAlign: "center",
306
+ marginTop: "0.5rem",
307
+ },
308
+ styleMode: "advanced",
309
+ enabled: true,
310
+ },
311
+ ],
312
+ },
313
+ {
314
+ id: "gallery-5",
315
+ type: "gallery-item",
316
+ order: 4,
317
+ enabled: true,
318
+ settings: {},
319
+ components: [
320
+ {
321
+ id: "gallery-5-image",
322
+ type: "image",
323
+ slot: "image",
324
+ order: 0,
325
+ content: {
326
+ src: "https://picsum.photos/seed/gallery5/600/400",
327
+ alt: "Gallery image 5",
328
+ },
329
+ style: {
330
+ width: "100%",
331
+ height: "auto",
332
+ borderRadius: "0.5rem",
333
+ },
334
+ styleMode: "advanced",
335
+ enabled: true,
336
+ },
337
+ {
338
+ id: "gallery-5-caption",
339
+ type: "paragraph",
340
+ slot: "caption",
341
+ order: 1,
342
+ content: { text: "Abstract patterns" },
343
+ style: {
344
+ fontSize: "sm",
345
+ color: "#6B7280",
346
+ textAlign: "center",
347
+ marginTop: "0.5rem",
348
+ },
349
+ styleMode: "advanced",
350
+ enabled: true,
351
+ },
352
+ ],
353
+ },
354
+ {
355
+ id: "gallery-6",
356
+ type: "gallery-item",
357
+ order: 5,
358
+ enabled: true,
359
+ settings: {},
360
+ components: [
361
+ {
362
+ id: "gallery-6-image",
363
+ type: "image",
364
+ slot: "image",
365
+ order: 0,
366
+ content: {
367
+ src: "https://picsum.photos/seed/gallery6/600/400",
368
+ alt: "Gallery image 6",
369
+ },
370
+ style: {
371
+ width: "100%",
372
+ height: "auto",
373
+ borderRadius: "0.5rem",
374
+ },
375
+ styleMode: "advanced",
376
+ enabled: true,
377
+ },
378
+ {
379
+ id: "gallery-6-caption",
380
+ type: "paragraph",
381
+ slot: "caption",
382
+ order: 1,
383
+ content: { text: "Minimalist interior" },
384
+ style: {
385
+ fontSize: "sm",
386
+ color: "#6B7280",
387
+ textAlign: "center",
388
+ marginTop: "0.5rem",
389
+ },
390
+ styleMode: "advanced",
391
+ enabled: true,
392
+ },
393
+ ],
394
+ },
395
+ ],
396
+ },
397
+ };
@@ -0,0 +1,11 @@
1
+ import type { SectionComponentProps } from "@onexapis/core/types";
2
+ import { GalleryDefault } from "./gallery-default";
3
+
4
+ export const galleryComponents: Record<
5
+ string,
6
+ React.ComponentType<SectionComponentProps>
7
+ > = {
8
+ default: GalleryDefault,
9
+ };
10
+
11
+ export { gallerySchema } from "./gallery.schema";
@@ -0,0 +1,212 @@
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 HeroDefault({
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
+ // Find components by slot (preferred) OR legacy ID (backward compatibility)
23
+ const badgeComp = components.find(
24
+ (c) => c.slot === "badge" || c.id === "hero-badge"
25
+ );
26
+ const titleComp = components.find(
27
+ (c) => c.slot === "title" || c.id === "hero-title"
28
+ );
29
+ const subtitleComp = components.find(
30
+ (c) => c.slot === "subtitle" || c.id === "hero-subtitle"
31
+ );
32
+ const dividerComp = components.find(
33
+ (c) => c.slot === "divider" || c.id === "hero-divider"
34
+ );
35
+ const ctaComp = components.find(
36
+ (c) => c.slot === "cta" || c.id === "hero-cta"
37
+ );
38
+ const secondaryCtaComp = components.find(
39
+ (c) => c.slot === "secondary-cta" || c.id === "hero-secondary-cta"
40
+ );
41
+ const imageComp = components.find(
42
+ (c) => c.slot === "image" || c.id === "hero-image"
43
+ );
44
+
45
+ const { settings } = getSectionValues(section, schema);
46
+ const {
47
+ title,
48
+ subtitle,
49
+ buttonText,
50
+ buttonLink,
51
+ secondaryButtonText,
52
+ secondaryButtonLink,
53
+ badgeText,
54
+ showBadge,
55
+ showImage,
56
+ backgroundColor,
57
+ } = settings;
58
+
59
+ // Block-level settings
60
+ const blockSettings = contentBlock?.settings || {};
61
+ const alignMap: Record<string, string> = {
62
+ left: "text-left",
63
+ center: "text-center",
64
+ right: "text-right",
65
+ };
66
+ const widthMap: Record<string, string> = {
67
+ sm: "max-w-2xl",
68
+ md: "max-w-3xl",
69
+ lg: "max-w-4xl",
70
+ full: "max-w-6xl",
71
+ };
72
+ const blockAlign =
73
+ alignMap[blockSettings.contentAlignment as string] || "text-center";
74
+ const blockWidth =
75
+ widthMap[blockSettings.contentWidth as string] || "max-w-4xl";
76
+
77
+ return (
78
+ <section
79
+ className="relative py-20 bg-gradient-to-br from-blue-500 to-purple-600"
80
+ style={
81
+ backgroundColor
82
+ ? {
83
+ background: `linear-gradient(135deg, ${String(backgroundColor)}, ${String(backgroundColor)}dd)`,
84
+ }
85
+ : undefined
86
+ }
87
+ data-section="hero"
88
+ data-section-id={section.id}
89
+ data-section-template="default"
90
+ data-section-name="Simple Hero"
91
+ >
92
+ <div
93
+ className={`container mx-auto px-4 text-white ${blockAlign} ${blockWidth}`}
94
+ data-section-id={section.id}
95
+ data-block-id={contentBlock?.id || "hero-content-1"}
96
+ data-block-type="hero-content"
97
+ >
98
+ {/* Badge */}
99
+ {showBadge !== false &&
100
+ (badgeComp ? (
101
+ <div key="badge-wrapper" className="mb-4 inline-block">
102
+ <ComponentRenderer
103
+ instance={toComponentInstance(badgeComp)}
104
+ sectionId={section.id}
105
+ isEditing={isEditing}
106
+ />
107
+ </div>
108
+ ) : badgeText ? (
109
+ <span
110
+ key="badge-fallback"
111
+ className="inline-block mb-4 px-3 py-1 text-sm font-semibold bg-white/20 rounded-full text-white"
112
+ >
113
+ {String(badgeText)}
114
+ </span>
115
+ ) : null)}
116
+
117
+ {/* Title */}
118
+ {titleComp ? (
119
+ <ComponentRenderer
120
+ key="title"
121
+ instance={toComponentInstance(titleComp)}
122
+ sectionId={section.id}
123
+ isEditing={isEditing}
124
+ />
125
+ ) : title ? (
126
+ <h1
127
+ key="title-fallback"
128
+ className="text-5xl font-bold mb-4 text-white"
129
+ >
130
+ {String(title)}
131
+ </h1>
132
+ ) : null}
133
+
134
+ {/* Subtitle */}
135
+ {subtitleComp ? (
136
+ <ComponentRenderer
137
+ key="subtitle"
138
+ instance={toComponentInstance(subtitleComp)}
139
+ sectionId={section.id}
140
+ isEditing={isEditing}
141
+ />
142
+ ) : subtitle ? (
143
+ <p key="subtitle-fallback" className="text-xl mb-6 text-white/90">
144
+ {String(subtitle)}
145
+ </p>
146
+ ) : null}
147
+
148
+ {/* Divider */}
149
+ {dividerComp && (
150
+ <ComponentRenderer
151
+ key="divider"
152
+ instance={toComponentInstance(dividerComp)}
153
+ sectionId={section.id}
154
+ isEditing={isEditing}
155
+ />
156
+ )}
157
+
158
+ {/* Button Row */}
159
+ <div key="button-row" className="flex gap-4 justify-center flex-wrap">
160
+ {ctaComp ? (
161
+ <ComponentRenderer
162
+ key={ctaComp.id}
163
+ instance={toComponentInstance(ctaComp)}
164
+ sectionId={section.id}
165
+ isEditing={isEditing}
166
+ />
167
+ ) : buttonText ? (
168
+ <a
169
+ key="cta-fallback"
170
+ href={String(buttonLink || "#")}
171
+ className="inline-block px-8 py-3 bg-white text-blue-600 font-semibold rounded-lg hover:bg-gray-100 transition"
172
+ >
173
+ {String(buttonText)}
174
+ </a>
175
+ ) : null}
176
+
177
+ {secondaryCtaComp ? (
178
+ <ComponentRenderer
179
+ key={secondaryCtaComp.id}
180
+ instance={toComponentInstance(secondaryCtaComp)}
181
+ sectionId={section.id}
182
+ isEditing={isEditing}
183
+ />
184
+ ) : secondaryButtonText ? (
185
+ <a
186
+ key="secondary-cta-fallback"
187
+ href={String(secondaryButtonLink || "#")}
188
+ className="inline-block px-8 py-3 border-2 border-white text-white font-semibold rounded-lg hover:bg-white/10 transition"
189
+ >
190
+ {String(secondaryButtonText)}
191
+ </a>
192
+ ) : null}
193
+ </div>
194
+
195
+ {/* Hero Image */}
196
+ {showImage !== false &&
197
+ (imageComp ? (
198
+ <div key="image-wrapper" className="mt-8">
199
+ <ComponentRenderer
200
+ key={imageComp.id}
201
+ instance={toComponentInstance(imageComp)}
202
+ sectionId={section.id}
203
+ isEditing={isEditing}
204
+ />
205
+ </div>
206
+ ) : null)}
207
+ </div>
208
+ </section>
209
+ );
210
+ }
211
+
212
+ export default HeroDefault;