@onexapis/cli 1.1.16 → 1.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -46
- package/bin/onexthm.js +4 -0
- package/dist/cli.js +230 -44
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +230 -44
- package/dist/cli.mjs.map +1 -1
- package/dist/index.js +115 -29
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +115 -29
- package/dist/index.mjs.map +1 -1
- package/dist/preview/preview-app.tsx +175 -53
- package/package.json +14 -12
|
@@ -171,7 +171,102 @@ function toPascalCase(str: string): string {
|
|
|
171
171
|
.join("");
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
-
// ===== 4.
|
|
174
|
+
// ===== 4. THEME CSS VARIABLE INJECTION =====
|
|
175
|
+
|
|
176
|
+
const PALETTE_TO_CSS_VAR: Record<string, string> = {
|
|
177
|
+
primary: "--primary",
|
|
178
|
+
secondary: "--secondary",
|
|
179
|
+
accent: "--accent",
|
|
180
|
+
background: "--background",
|
|
181
|
+
foreground: "--foreground",
|
|
182
|
+
muted: "--muted",
|
|
183
|
+
mutedForeground: "--muted-foreground",
|
|
184
|
+
card: "--card",
|
|
185
|
+
cardForeground: "--card-foreground",
|
|
186
|
+
popover: "--popover",
|
|
187
|
+
popoverForeground: "--popover-foreground",
|
|
188
|
+
border: "--border",
|
|
189
|
+
input: "--input",
|
|
190
|
+
ring: "--ring",
|
|
191
|
+
destructive: "--destructive",
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
function hexToHsl(hex: string): string {
|
|
195
|
+
const cleaned = hex.replace(/^#/, "");
|
|
196
|
+
let r: number, g: number, b: number;
|
|
197
|
+
if (cleaned.length === 3) {
|
|
198
|
+
r = parseInt(cleaned[0] + cleaned[0], 16) / 255;
|
|
199
|
+
g = parseInt(cleaned[1] + cleaned[1], 16) / 255;
|
|
200
|
+
b = parseInt(cleaned[2] + cleaned[2], 16) / 255;
|
|
201
|
+
} else {
|
|
202
|
+
r = parseInt(cleaned.substring(0, 2), 16) / 255;
|
|
203
|
+
g = parseInt(cleaned.substring(2, 4), 16) / 255;
|
|
204
|
+
b = parseInt(cleaned.substring(4, 6), 16) / 255;
|
|
205
|
+
}
|
|
206
|
+
const max = Math.max(r, g, b);
|
|
207
|
+
const min = Math.min(r, g, b);
|
|
208
|
+
const l = (max + min) / 2;
|
|
209
|
+
if (max === min) return `0 0% ${Math.round(l * 100)}%`;
|
|
210
|
+
const d = max - min;
|
|
211
|
+
const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
212
|
+
let h = 0;
|
|
213
|
+
if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
|
|
214
|
+
else if (max === g) h = ((b - r) / d + 2) / 6;
|
|
215
|
+
else h = ((r - g) / d + 4) / 6;
|
|
216
|
+
return `${Math.round(h * 360)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function paletteToCSS(palette: Record<string, string>): string {
|
|
220
|
+
const lines: string[] = [];
|
|
221
|
+
for (const [field, cssVar] of Object.entries(PALETTE_TO_CSS_VAR)) {
|
|
222
|
+
const value = palette[field];
|
|
223
|
+
if (value && value.startsWith("#")) {
|
|
224
|
+
lines.push(` ${cssVar}: ${hexToHsl(value)};`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return lines.join("\n");
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function buildThemeStyleCSS(themeConfig: any): string | null {
|
|
231
|
+
if (!themeConfig?.colors?.light) return null;
|
|
232
|
+
const lightCSS = paletteToCSS(themeConfig.colors.light);
|
|
233
|
+
const darkCSS = themeConfig.colors.dark
|
|
234
|
+
? paletteToCSS(themeConfig.colors.dark)
|
|
235
|
+
: "";
|
|
236
|
+
if (!lightCSS && !darkCSS) return null;
|
|
237
|
+
return [
|
|
238
|
+
lightCSS ? `:root {\n${lightCSS}\n}` : "",
|
|
239
|
+
darkCSS ? `.dark {\n${darkCSS}\n}` : "",
|
|
240
|
+
]
|
|
241
|
+
.filter(Boolean)
|
|
242
|
+
.join("\n");
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ===== 5. RESOLVE SECTION LIST =====
|
|
246
|
+
|
|
247
|
+
function resolveSections(
|
|
248
|
+
sectionConfigs: any[],
|
|
249
|
+
themeExports: ThemeExports,
|
|
250
|
+
themePrefix: string
|
|
251
|
+
) {
|
|
252
|
+
return (sectionConfigs || [])
|
|
253
|
+
.filter((s: any) => s.enabled !== false)
|
|
254
|
+
.sort((a: any, b: any) => a.order - b.order)
|
|
255
|
+
.map((section: any) => {
|
|
256
|
+
const reg = getSectionComponent(
|
|
257
|
+
themeExports,
|
|
258
|
+
themePrefix,
|
|
259
|
+
section.type,
|
|
260
|
+
section.template || "default"
|
|
261
|
+
);
|
|
262
|
+
const enriched = reg?.schema
|
|
263
|
+
? enrichSectionWithDefaults(section, reg.schema)
|
|
264
|
+
: section;
|
|
265
|
+
return { section: enriched, registration: reg };
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// ===== 6. SECTION DATA ENRICHMENT =====
|
|
175
270
|
|
|
176
271
|
/**
|
|
177
272
|
* Merge schema defaults into section instances from page config.
|
|
@@ -199,7 +294,7 @@ function enrichSectionWithDefaults(section: any, schema: any): any {
|
|
|
199
294
|
};
|
|
200
295
|
}
|
|
201
296
|
|
|
202
|
-
// =====
|
|
297
|
+
// ===== 7. PAGE CONFIG DISCOVERY =====
|
|
203
298
|
|
|
204
299
|
function discoverPageConfigs(
|
|
205
300
|
themeExports: ThemeExports
|
|
@@ -231,7 +326,7 @@ function discoverPageConfigs(
|
|
|
231
326
|
return pages;
|
|
232
327
|
}
|
|
233
328
|
|
|
234
|
-
// =====
|
|
329
|
+
// ===== 8. PREVIEW APP COMPONENT =====
|
|
235
330
|
|
|
236
331
|
/**
|
|
237
332
|
* Match URL pathname to a page index.
|
|
@@ -297,7 +392,6 @@ function PreviewApp() {
|
|
|
297
392
|
|
|
298
393
|
ws.onopen = () => {
|
|
299
394
|
setWsStatus("connected");
|
|
300
|
-
|
|
301
395
|
};
|
|
302
396
|
|
|
303
397
|
ws.onmessage = (event) => {
|
|
@@ -306,7 +400,6 @@ function PreviewApp() {
|
|
|
306
400
|
setWsStatus("rebuilding");
|
|
307
401
|
loadTheme(msg.timestamp).then(() => {
|
|
308
402
|
setWsStatus("connected");
|
|
309
|
-
|
|
310
403
|
});
|
|
311
404
|
} else if (msg.type === "error") {
|
|
312
405
|
setError(msg.message);
|
|
@@ -437,62 +530,91 @@ function PreviewApp() {
|
|
|
437
530
|
);
|
|
438
531
|
}
|
|
439
532
|
|
|
440
|
-
//
|
|
441
|
-
const
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
533
|
+
// Build section data (Gap 4)
|
|
534
|
+
const sectionData = {
|
|
535
|
+
theme: themeExports.themeConfig || {},
|
|
536
|
+
page: currentPage.config,
|
|
537
|
+
products: [],
|
|
538
|
+
blogs: [],
|
|
539
|
+
settings: {},
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
// Resolve layout sections (Gap 1)
|
|
543
|
+
const layoutConfig = themeExports.layoutConfig;
|
|
544
|
+
const headerSections = resolveSections(
|
|
545
|
+
layoutConfig?.headerSections || [],
|
|
546
|
+
themeExports,
|
|
547
|
+
themePrefix
|
|
548
|
+
);
|
|
549
|
+
const footerSections = resolveSections(
|
|
550
|
+
layoutConfig?.footerSections || [],
|
|
551
|
+
themeExports,
|
|
552
|
+
themePrefix
|
|
553
|
+
);
|
|
554
|
+
|
|
555
|
+
// Resolve page sections
|
|
556
|
+
const pageSections = resolveSections(
|
|
557
|
+
currentPage.config.sections || [],
|
|
558
|
+
themeExports,
|
|
559
|
+
themePrefix
|
|
560
|
+
);
|
|
561
|
+
|
|
562
|
+
// Build theme CSS (Gap 2)
|
|
563
|
+
const themeCSS = buildThemeStyleCSS(themeExports.themeConfig);
|
|
564
|
+
|
|
565
|
+
const renderSection = ({ section, registration }: any) => {
|
|
566
|
+
if (!registration) {
|
|
567
|
+
return (
|
|
568
|
+
<div
|
|
569
|
+
key={section.id}
|
|
570
|
+
style={{
|
|
571
|
+
padding: "2rem",
|
|
572
|
+
border: "2px dashed #f59e0b",
|
|
573
|
+
margin: "1rem 0",
|
|
574
|
+
background: "#fffbeb",
|
|
575
|
+
}}
|
|
576
|
+
>
|
|
577
|
+
<h3 style={{ margin: 0, fontSize: "1.2rem", color: "#d97706" }}>
|
|
578
|
+
Section Not Found: {section.type}
|
|
579
|
+
</h3>
|
|
580
|
+
</div>
|
|
450
581
|
);
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
582
|
+
}
|
|
583
|
+
const { Component, schema, template } = registration;
|
|
584
|
+
return (
|
|
585
|
+
<Component
|
|
586
|
+
key={section.id}
|
|
587
|
+
section={section}
|
|
588
|
+
schema={schema}
|
|
589
|
+
template={template}
|
|
590
|
+
isEditing={false}
|
|
591
|
+
data={sectionData}
|
|
592
|
+
/>
|
|
593
|
+
);
|
|
594
|
+
};
|
|
456
595
|
|
|
457
596
|
return (
|
|
458
597
|
<>
|
|
459
|
-
{/*
|
|
460
|
-
{
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
</h3>
|
|
475
|
-
</div>
|
|
476
|
-
);
|
|
477
|
-
}
|
|
478
|
-
const { Component, schema, template } = registration;
|
|
479
|
-
return (
|
|
480
|
-
<Component
|
|
481
|
-
key={section.id}
|
|
482
|
-
section={section}
|
|
483
|
-
schema={schema}
|
|
484
|
-
template={template}
|
|
485
|
-
isEditing={false}
|
|
486
|
-
data={{}}
|
|
487
|
-
/>
|
|
488
|
-
);
|
|
489
|
-
})}
|
|
598
|
+
{/* Inject theme CSS variables (Gap 2) */}
|
|
599
|
+
{themeCSS && <style dangerouslySetInnerHTML={{ __html: themeCSS }} />}
|
|
600
|
+
|
|
601
|
+
{/* Header (Gap 1) */}
|
|
602
|
+
{headerSections.length > 0 && (
|
|
603
|
+
<header>{headerSections.map(renderSection)}</header>
|
|
604
|
+
)}
|
|
605
|
+
|
|
606
|
+
{/* Page sections */}
|
|
607
|
+
<main>{pageSections.map(renderSection)}</main>
|
|
608
|
+
|
|
609
|
+
{/* Footer (Gap 1) */}
|
|
610
|
+
{footerSections.length > 0 && (
|
|
611
|
+
<footer>{footerSections.map(renderSection)}</footer>
|
|
612
|
+
)}
|
|
490
613
|
</>
|
|
491
614
|
);
|
|
492
615
|
}
|
|
493
616
|
|
|
494
|
-
|
|
495
|
-
// ===== 7. MOUNT =====
|
|
617
|
+
// ===== 9. MOUNT =====
|
|
496
618
|
|
|
497
619
|
const queryClient = new QueryClient({
|
|
498
620
|
defaultOptions: {
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onexapis/cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.17",
|
|
4
4
|
"description": "CLI tool for OneX theme development - scaffolds themes using @onexapis/core",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"bin": {
|
|
9
|
-
"
|
|
9
|
+
"onexthm": "./bin/onexthm.js"
|
|
10
10
|
},
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
@@ -15,6 +15,13 @@
|
|
|
15
15
|
"require": "./dist/index.js"
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup",
|
|
20
|
+
"dev": "tsup --watch",
|
|
21
|
+
"type-check": "tsc --noEmit",
|
|
22
|
+
"lint": "eslint src --ext .ts",
|
|
23
|
+
"prepublishOnly": "pnpm run type-check && pnpm run build"
|
|
24
|
+
},
|
|
18
25
|
"keywords": [
|
|
19
26
|
"onex",
|
|
20
27
|
"cli",
|
|
@@ -41,8 +48,9 @@
|
|
|
41
48
|
"registry": "https://registry.npmjs.org/"
|
|
42
49
|
},
|
|
43
50
|
"dependencies": {
|
|
44
|
-
"@tanstack/react-query": "^5.90.16",
|
|
45
51
|
"@aws-sdk/client-s3": "^3.470.0",
|
|
52
|
+
"@onexapis/core": "workspace:*",
|
|
53
|
+
"@tanstack/react-query": "^5.90.16",
|
|
46
54
|
"adm-zip": "^0.5.16",
|
|
47
55
|
"archiver": "^7.0.1",
|
|
48
56
|
"chalk": "^5.3.0",
|
|
@@ -52,6 +60,7 @@
|
|
|
52
60
|
"ejs": "^3.1.10",
|
|
53
61
|
"esbuild": "^0.25.0",
|
|
54
62
|
"form-data": "^4.0.5",
|
|
63
|
+
"framer-motion": "^12.23.26",
|
|
55
64
|
"fs-extra": "^11.2.0",
|
|
56
65
|
"glob": "^10.3.10",
|
|
57
66
|
"inquirer": "^9.2.12",
|
|
@@ -59,8 +68,7 @@
|
|
|
59
68
|
"node-fetch": "^3.3.2",
|
|
60
69
|
"open": "^10.1.0",
|
|
61
70
|
"ora": "^8.0.1",
|
|
62
|
-
"ws": "^8.18.0"
|
|
63
|
-
"@onexapis/core": "1.0.2"
|
|
71
|
+
"ws": "^8.18.0"
|
|
64
72
|
},
|
|
65
73
|
"devDependencies": {
|
|
66
74
|
"@types/adm-zip": "^0.5.7",
|
|
@@ -80,11 +88,5 @@
|
|
|
80
88
|
],
|
|
81
89
|
"engines": {
|
|
82
90
|
"node": ">=18.0.0"
|
|
83
|
-
},
|
|
84
|
-
"scripts": {
|
|
85
|
-
"build": "tsup",
|
|
86
|
-
"dev": "tsup --watch",
|
|
87
|
-
"type-check": "tsc --noEmit",
|
|
88
|
-
"lint": "eslint src --ext .ts"
|
|
89
91
|
}
|
|
90
|
-
}
|
|
92
|
+
}
|