desen-cli 1.0.0-draft.6 → 1.0.0-draft.8
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/.turbo/turbo-build.log +1 -1
- package/dist/index.js +45 -91
- package/package.json +24 -21
- package/src/index.ts +44 -91
package/.turbo/turbo-build.log
CHANGED
package/dist/index.js
CHANGED
|
@@ -188,32 +188,43 @@ program
|
|
|
188
188
|
if (!payloads || payloads.length === 0 || !payloads[0].path) {
|
|
189
189
|
return res.status(400).json({ error: "Missing payloads or path in request body" });
|
|
190
190
|
}
|
|
191
|
-
//
|
|
191
|
+
// ─────────────────────────────────────────────────────────
|
|
192
|
+
// VALIDATION (Warn-and-Proceed for Development)
|
|
193
|
+
// Daemon is a dev tool — strict fail-closed enforcement
|
|
194
|
+
// belongs in `desen validate` (CI/CD pipeline).
|
|
195
|
+
// Here we log warnings but NEVER block the sync.
|
|
196
|
+
// ─────────────────────────────────────────────────────────
|
|
197
|
+
let validationWarnings = 0;
|
|
192
198
|
for (const item of payloads) {
|
|
193
199
|
if (!item.path || !item.ast)
|
|
194
200
|
continue;
|
|
195
201
|
let result;
|
|
196
|
-
if (item.path.
|
|
202
|
+
if (item.path.includes('surfaces/')) {
|
|
197
203
|
result = desen_core_1.surfaceSpec.safeParse(item.ast);
|
|
198
204
|
}
|
|
199
|
-
else if (item.path.
|
|
205
|
+
else if (item.path.includes('elements/') || item.path.includes('compositions/')) {
|
|
200
206
|
result = desen_core_1.nodeSpec.safeParse(item.ast);
|
|
201
207
|
}
|
|
202
|
-
else if (item.path.
|
|
203
|
-
result = { success: true };
|
|
208
|
+
else if (item.path.includes('themes/')) {
|
|
209
|
+
result = { success: true };
|
|
204
210
|
}
|
|
205
211
|
else {
|
|
206
212
|
result = desen_core_1.nodeSpec.safeParse(item.ast);
|
|
207
213
|
}
|
|
208
214
|
if (!result.success) {
|
|
209
|
-
|
|
210
|
-
console.
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
});
|
|
215
|
+
validationWarnings++;
|
|
216
|
+
console.warn(chalk_1.default.yellow(`⚠️ [Validation Warning] ${item.path}`));
|
|
217
|
+
const formatted = result.error.format();
|
|
218
|
+
// Log a concise summary instead of the full error tree
|
|
219
|
+
const issues = result.error.errors.map((e) => ` → [${e.path.join('.')}] ${e.message}`).join('\n');
|
|
220
|
+
console.warn(chalk_1.default.yellow(issues));
|
|
216
221
|
}
|
|
222
|
+
else {
|
|
223
|
+
console.log(chalk_1.default.green(` ✓ ${item.path}`));
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (validationWarnings > 0) {
|
|
227
|
+
console.warn(chalk_1.default.yellow(`\n⚠️ ${validationWarnings} file(s) have validation warnings. Run 'desen validate' for strict checks.`));
|
|
217
228
|
}
|
|
218
229
|
const projectRoot = process.cwd();
|
|
219
230
|
const workspaceDir = path_1.default.join(projectRoot, "desen-workspace");
|
|
@@ -249,8 +260,8 @@ program
|
|
|
249
260
|
"start": "next start"
|
|
250
261
|
},
|
|
251
262
|
dependencies: {
|
|
252
|
-
"desen-core": "1.0.0-draft.
|
|
253
|
-
"desen": "1.0.0-draft.
|
|
263
|
+
"desen-core": "1.0.0-draft.7",
|
|
264
|
+
"desen": "1.0.0-draft.7",
|
|
254
265
|
"next": "14.2.3",
|
|
255
266
|
"react": "18.3.1",
|
|
256
267
|
"react-dom": "18.3.1"
|
|
@@ -288,7 +299,7 @@ program
|
|
|
288
299
|
const appDir = path_1.default.join(workspaceDir, "src", "app");
|
|
289
300
|
fs_1.default.mkdirSync(appDir, { recursive: true });
|
|
290
301
|
// Find first surface directly
|
|
291
|
-
const firstSurface = payloads.find((p) => p.path.
|
|
302
|
+
const firstSurface = payloads.find((p) => p.path.includes('surfaces/'))?.path || 'desen/surfaces/frame-1.desen.json';
|
|
292
303
|
// API Route to load local .desen.json dynamically
|
|
293
304
|
const apiDir = path_1.default.join(appDir, "api", "surface", "route");
|
|
294
305
|
fs_1.default.mkdirSync(apiDir, { recursive: true });
|
|
@@ -413,67 +424,6 @@ export default function Page() {
|
|
|
413
424
|
fs_1.default.writeFileSync(path_1.default.join(libDir, "desenRegistry.tsx"), `
|
|
414
425
|
import React from 'react';
|
|
415
426
|
|
|
416
|
-
function resolveToken(tokenStr: string): string | undefined {
|
|
417
|
-
if (!tokenStr) return undefined;
|
|
418
|
-
const match = tokenStr.match(/t_([a-fA-F0-9]{3,8})/);
|
|
419
|
-
return match ? \`#\${match[1]}\` : undefined;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
function resolveColor(tokenStr?: string, hexStr?: string): string | undefined {
|
|
423
|
-
if (tokenStr) return resolveToken(tokenStr);
|
|
424
|
-
if (hexStr) return hexStr;
|
|
425
|
-
return undefined;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
function buildCssFromNode(layout: any, style: any, opts?: { isText?: boolean; isSurfaceRoot?: boolean }): React.CSSProperties {
|
|
429
|
-
const css: any = { boxSizing: 'border-box' };
|
|
430
|
-
|
|
431
|
-
if (layout) {
|
|
432
|
-
css.display = 'flex';
|
|
433
|
-
css.flexDirection = layout.direction === 'row' ? 'row' : 'column';
|
|
434
|
-
if (layout.gap !== undefined && layout.gap !== 0) css.gap = layout.gap;
|
|
435
|
-
|
|
436
|
-
const am: Record<string, string> = { start:'flex-start', end:'flex-end', center:'center', 'space-between':'space-between', 'space-around':'space-around', 'space-evenly':'space-evenly' };
|
|
437
|
-
css.alignItems = am[layout.align_items] || 'stretch';
|
|
438
|
-
css.justifyContent = am[layout.align_content] || 'flex-start';
|
|
439
|
-
|
|
440
|
-
if (layout.padding !== undefined) {
|
|
441
|
-
css.padding = Array.isArray(layout.padding) ? layout.padding.map((p:number)=>p+'px').join(' ') : layout.padding !== 0 ? layout.padding+'px' : undefined;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
if (opts?.isSurfaceRoot) {
|
|
445
|
-
css.width = '100%'; css.minHeight = '100vh';
|
|
446
|
-
} else {
|
|
447
|
-
if (layout.sizing_h === 'FILL') css.width = '100%';
|
|
448
|
-
else if (layout.sizing_h === 'FIXED' && style?.width !== undefined) css.width = style.width;
|
|
449
|
-
if (layout.sizing_v === 'FILL') css.height = '100%';
|
|
450
|
-
else if (layout.sizing_v === 'FIXED' && style?.height !== undefined) css.height = style.height;
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
if (style) {
|
|
455
|
-
const bgColor = resolveColor(style.bg_color_token, style.bg_color);
|
|
456
|
-
if (bgColor) { if (opts?.isText) css.color = bgColor; else css.backgroundColor = bgColor; }
|
|
457
|
-
const bc = resolveColor(style.border_color_token, style.border_color);
|
|
458
|
-
if (bc) css.borderColor = bc;
|
|
459
|
-
if (style.border_width !== undefined) { css.borderWidth = style.border_width; css.borderStyle = 'solid'; }
|
|
460
|
-
if (style.border_radius !== undefined) {
|
|
461
|
-
css.borderRadius = Array.isArray(style.border_radius) ? style.border_radius.map((r:number)=>r+'px').join(' ') : style.border_radius;
|
|
462
|
-
}
|
|
463
|
-
if (!layout && !opts?.isText) { if (style.width !== undefined) css.width = style.width; if (style.height !== undefined) css.height = style.height; }
|
|
464
|
-
if (style.opacity !== undefined) css.opacity = style.opacity;
|
|
465
|
-
if (style.font_size) css.fontSize = style.font_size;
|
|
466
|
-
if (style.font_weight) css.fontWeight = style.font_weight;
|
|
467
|
-
if (style.font_family) css.fontFamily = style.font_family;
|
|
468
|
-
if (style.letter_spacing) css.letterSpacing = style.letter_spacing;
|
|
469
|
-
if (style.line_height) css.lineHeight = style.line_height + 'px';
|
|
470
|
-
if (style.text_align) css.textAlign = style.text_align;
|
|
471
|
-
if (style.text_decoration) css.textDecoration = style.text_decoration;
|
|
472
|
-
if (style.text_transform) css.textTransform = style.text_transform;
|
|
473
|
-
}
|
|
474
|
-
return css;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
427
|
const DynamicFontLoader = ({ fonts }: { fonts?: string[] }) => {
|
|
478
428
|
if (!fonts || fonts.length === 0) return null;
|
|
479
429
|
|
|
@@ -497,31 +447,28 @@ const DynamicFontLoader = ({ fonts }: { fonts?: string[] }) => {
|
|
|
497
447
|
};
|
|
498
448
|
|
|
499
449
|
const SurfaceComponent = (props: any) => (
|
|
500
|
-
<div style={
|
|
450
|
+
<div style={props.parsedStyle}>
|
|
501
451
|
<DynamicFontLoader fonts={props.metadata?.fonts} />
|
|
502
452
|
{props.children}
|
|
503
453
|
</div>
|
|
504
454
|
);
|
|
505
455
|
|
|
506
456
|
const GenericContainer = (props: any) => (
|
|
507
|
-
<div style={
|
|
457
|
+
<div style={props.parsedStyle}>{props.children}</div>
|
|
508
458
|
);
|
|
509
459
|
|
|
510
460
|
const TextComponent = (props: any) => (
|
|
511
|
-
<span style={
|
|
461
|
+
<span style={props.parsedStyle}>{props.content || props.text || props.name}</span>
|
|
512
462
|
);
|
|
513
463
|
|
|
514
464
|
const ButtonComponent = (props: any) => {
|
|
515
|
-
const
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
if (props.
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
if (props.text_style.font_weight) css.fontWeight = props.text_style.font_weight;
|
|
523
|
-
if (props.text_style.font_family) css.fontFamily = props.text_style.font_family;
|
|
524
|
-
if (props.text_style.text_align) css.textAlign = props.text_style.text_align;
|
|
465
|
+
const css: any = { ...props.parsedStyle, cursor: 'pointer', border: 'none' };
|
|
466
|
+
|
|
467
|
+
// If no layout, center text by default (most buttons center their text)
|
|
468
|
+
if (!props.layout) {
|
|
469
|
+
css.display = 'flex';
|
|
470
|
+
css.alignItems = 'center';
|
|
471
|
+
css.justifyContent = 'center';
|
|
525
472
|
}
|
|
526
473
|
return <button style={css}>{props.children || props.content || props.text || props.name}</button>;
|
|
527
474
|
};
|
|
@@ -533,11 +480,18 @@ export const registry: Record<string, React.FC<any>> = {
|
|
|
533
480
|
element: GenericContainer,
|
|
534
481
|
group: GenericContainer,
|
|
535
482
|
stack: GenericContainer,
|
|
483
|
+
Stack: GenericContainer,
|
|
484
|
+
Card: GenericContainer,
|
|
485
|
+
Grid: GenericContainer,
|
|
486
|
+
Header: GenericContainer,
|
|
487
|
+
Footer: GenericContainer,
|
|
536
488
|
text: TextComponent,
|
|
537
489
|
Text: TextComponent,
|
|
538
490
|
button: ButtonComponent,
|
|
539
|
-
|
|
540
|
-
|
|
491
|
+
Button: ButtonComponent,
|
|
492
|
+
input: (props: any) => <input style={props.parsedStyle} placeholder={props.content || props.name} />,
|
|
493
|
+
icon: (props: any) => <div style={{ ...props.parsedStyle, display:'inline-flex', alignItems:'center', justifyContent:'center' }}>⚙️</div>,
|
|
494
|
+
Icon: (props: any) => <div style={{ ...props.parsedStyle, display:'inline-flex', alignItems:'center', justifyContent:'center' }}>⚙️</div>,
|
|
541
495
|
};
|
|
542
496
|
`.trim());
|
|
543
497
|
console.log(chalk_1.default.green(`✅ Done! Standalone App Scaffolded.`));
|
package/package.json
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
2
|
+
"name": "desen-cli",
|
|
3
|
+
"version": "1.0.0-draft.8",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"bin": {
|
|
6
|
+
"desen": "dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"dev": "tsc -w",
|
|
11
|
+
"clean": "rm -rf dist"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"desen-core": "1.0.0-draft.8",
|
|
15
|
+
"chalk": "^5.6.2",
|
|
16
|
+
"commander": "^14.0.3",
|
|
17
|
+
"express": "^4.19.2",
|
|
18
|
+
"cors": "^2.8.5"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/cors": "^2.8.19",
|
|
22
|
+
"@types/express": "^5.0.6",
|
|
23
|
+
"@types/node": "^20.19.33",
|
|
24
|
+
"typescript": "^5.0.0"
|
|
25
|
+
}
|
|
23
26
|
}
|
package/src/index.ts
CHANGED
|
@@ -209,31 +209,41 @@ program
|
|
|
209
209
|
return res.status(400).json({ error: "Missing payloads or path in request body" });
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
-
//
|
|
212
|
+
// ─────────────────────────────────────────────────────────
|
|
213
|
+
// VALIDATION (Warn-and-Proceed for Development)
|
|
214
|
+
// Daemon is a dev tool — strict fail-closed enforcement
|
|
215
|
+
// belongs in `desen validate` (CI/CD pipeline).
|
|
216
|
+
// Here we log warnings but NEVER block the sync.
|
|
217
|
+
// ─────────────────────────────────────────────────────────
|
|
218
|
+
let validationWarnings = 0;
|
|
213
219
|
for (const item of payloads) {
|
|
214
220
|
if (!item.path || !item.ast) continue;
|
|
215
221
|
|
|
216
222
|
let result: any;
|
|
217
|
-
if (item.path.
|
|
223
|
+
if (item.path.includes('surfaces/')) {
|
|
218
224
|
result = surfaceSpec.safeParse(item.ast);
|
|
219
|
-
} else if (item.path.
|
|
225
|
+
} else if (item.path.includes('elements/') || item.path.includes('compositions/')) {
|
|
220
226
|
result = nodeSpec.safeParse(item.ast);
|
|
221
|
-
} else if (item.path.
|
|
222
|
-
result = { success: true };
|
|
227
|
+
} else if (item.path.includes('themes/')) {
|
|
228
|
+
result = { success: true };
|
|
223
229
|
} else {
|
|
224
230
|
result = nodeSpec.safeParse(item.ast);
|
|
225
231
|
}
|
|
226
232
|
|
|
227
233
|
if (!result.success) {
|
|
228
|
-
|
|
229
|
-
console.
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
234
|
+
validationWarnings++;
|
|
235
|
+
console.warn(chalk.yellow(`⚠️ [Validation Warning] ${item.path}`));
|
|
236
|
+
const formatted = result.error.format();
|
|
237
|
+
// Log a concise summary instead of the full error tree
|
|
238
|
+
const issues = result.error.errors.map((e: any) => ` → [${e.path.join('.')}] ${e.message}`).join('\n');
|
|
239
|
+
console.warn(chalk.yellow(issues));
|
|
240
|
+
} else {
|
|
241
|
+
console.log(chalk.green(` ✓ ${item.path}`));
|
|
235
242
|
}
|
|
236
243
|
}
|
|
244
|
+
if (validationWarnings > 0) {
|
|
245
|
+
console.warn(chalk.yellow(`\n⚠️ ${validationWarnings} file(s) have validation warnings. Run 'desen validate' for strict checks.`));
|
|
246
|
+
}
|
|
237
247
|
|
|
238
248
|
const projectRoot = process.cwd();
|
|
239
249
|
const workspaceDir = path.join(projectRoot, "desen-workspace");
|
|
@@ -275,8 +285,8 @@ program
|
|
|
275
285
|
"start": "next start"
|
|
276
286
|
},
|
|
277
287
|
dependencies: {
|
|
278
|
-
"desen-core": "1.0.0-draft.
|
|
279
|
-
"desen": "1.0.0-draft.
|
|
288
|
+
"desen-core": "1.0.0-draft.7",
|
|
289
|
+
"desen": "1.0.0-draft.7",
|
|
280
290
|
"next": "14.2.3",
|
|
281
291
|
"react": "18.3.1",
|
|
282
292
|
"react-dom": "18.3.1"
|
|
@@ -317,7 +327,7 @@ program
|
|
|
317
327
|
fs.mkdirSync(appDir, { recursive: true });
|
|
318
328
|
|
|
319
329
|
// Find first surface directly
|
|
320
|
-
const firstSurface = payloads.find((p: any) => p.path.
|
|
330
|
+
const firstSurface = payloads.find((p: any) => p.path.includes('surfaces/'))?.path || 'desen/surfaces/frame-1.desen.json';
|
|
321
331
|
|
|
322
332
|
// API Route to load local .desen.json dynamically
|
|
323
333
|
const apiDir = path.join(appDir, "api", "surface", "route");
|
|
@@ -448,67 +458,6 @@ export default function Page() {
|
|
|
448
458
|
fs.writeFileSync(path.join(libDir, "desenRegistry.tsx"), `
|
|
449
459
|
import React from 'react';
|
|
450
460
|
|
|
451
|
-
function resolveToken(tokenStr: string): string | undefined {
|
|
452
|
-
if (!tokenStr) return undefined;
|
|
453
|
-
const match = tokenStr.match(/t_([a-fA-F0-9]{3,8})/);
|
|
454
|
-
return match ? \`#\${match[1]}\` : undefined;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
function resolveColor(tokenStr?: string, hexStr?: string): string | undefined {
|
|
458
|
-
if (tokenStr) return resolveToken(tokenStr);
|
|
459
|
-
if (hexStr) return hexStr;
|
|
460
|
-
return undefined;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
function buildCssFromNode(layout: any, style: any, opts?: { isText?: boolean; isSurfaceRoot?: boolean }): React.CSSProperties {
|
|
464
|
-
const css: any = { boxSizing: 'border-box' };
|
|
465
|
-
|
|
466
|
-
if (layout) {
|
|
467
|
-
css.display = 'flex';
|
|
468
|
-
css.flexDirection = layout.direction === 'row' ? 'row' : 'column';
|
|
469
|
-
if (layout.gap !== undefined && layout.gap !== 0) css.gap = layout.gap;
|
|
470
|
-
|
|
471
|
-
const am: Record<string, string> = { start:'flex-start', end:'flex-end', center:'center', 'space-between':'space-between', 'space-around':'space-around', 'space-evenly':'space-evenly' };
|
|
472
|
-
css.alignItems = am[layout.align_items] || 'stretch';
|
|
473
|
-
css.justifyContent = am[layout.align_content] || 'flex-start';
|
|
474
|
-
|
|
475
|
-
if (layout.padding !== undefined) {
|
|
476
|
-
css.padding = Array.isArray(layout.padding) ? layout.padding.map((p:number)=>p+'px').join(' ') : layout.padding !== 0 ? layout.padding+'px' : undefined;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
if (opts?.isSurfaceRoot) {
|
|
480
|
-
css.width = '100%'; css.minHeight = '100vh';
|
|
481
|
-
} else {
|
|
482
|
-
if (layout.sizing_h === 'FILL') css.width = '100%';
|
|
483
|
-
else if (layout.sizing_h === 'FIXED' && style?.width !== undefined) css.width = style.width;
|
|
484
|
-
if (layout.sizing_v === 'FILL') css.height = '100%';
|
|
485
|
-
else if (layout.sizing_v === 'FIXED' && style?.height !== undefined) css.height = style.height;
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
if (style) {
|
|
490
|
-
const bgColor = resolveColor(style.bg_color_token, style.bg_color);
|
|
491
|
-
if (bgColor) { if (opts?.isText) css.color = bgColor; else css.backgroundColor = bgColor; }
|
|
492
|
-
const bc = resolveColor(style.border_color_token, style.border_color);
|
|
493
|
-
if (bc) css.borderColor = bc;
|
|
494
|
-
if (style.border_width !== undefined) { css.borderWidth = style.border_width; css.borderStyle = 'solid'; }
|
|
495
|
-
if (style.border_radius !== undefined) {
|
|
496
|
-
css.borderRadius = Array.isArray(style.border_radius) ? style.border_radius.map((r:number)=>r+'px').join(' ') : style.border_radius;
|
|
497
|
-
}
|
|
498
|
-
if (!layout && !opts?.isText) { if (style.width !== undefined) css.width = style.width; if (style.height !== undefined) css.height = style.height; }
|
|
499
|
-
if (style.opacity !== undefined) css.opacity = style.opacity;
|
|
500
|
-
if (style.font_size) css.fontSize = style.font_size;
|
|
501
|
-
if (style.font_weight) css.fontWeight = style.font_weight;
|
|
502
|
-
if (style.font_family) css.fontFamily = style.font_family;
|
|
503
|
-
if (style.letter_spacing) css.letterSpacing = style.letter_spacing;
|
|
504
|
-
if (style.line_height) css.lineHeight = style.line_height + 'px';
|
|
505
|
-
if (style.text_align) css.textAlign = style.text_align;
|
|
506
|
-
if (style.text_decoration) css.textDecoration = style.text_decoration;
|
|
507
|
-
if (style.text_transform) css.textTransform = style.text_transform;
|
|
508
|
-
}
|
|
509
|
-
return css;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
461
|
const DynamicFontLoader = ({ fonts }: { fonts?: string[] }) => {
|
|
513
462
|
if (!fonts || fonts.length === 0) return null;
|
|
514
463
|
|
|
@@ -532,31 +481,28 @@ const DynamicFontLoader = ({ fonts }: { fonts?: string[] }) => {
|
|
|
532
481
|
};
|
|
533
482
|
|
|
534
483
|
const SurfaceComponent = (props: any) => (
|
|
535
|
-
<div style={
|
|
484
|
+
<div style={props.parsedStyle}>
|
|
536
485
|
<DynamicFontLoader fonts={props.metadata?.fonts} />
|
|
537
486
|
{props.children}
|
|
538
487
|
</div>
|
|
539
488
|
);
|
|
540
489
|
|
|
541
490
|
const GenericContainer = (props: any) => (
|
|
542
|
-
<div style={
|
|
491
|
+
<div style={props.parsedStyle}>{props.children}</div>
|
|
543
492
|
);
|
|
544
493
|
|
|
545
494
|
const TextComponent = (props: any) => (
|
|
546
|
-
<span style={
|
|
495
|
+
<span style={props.parsedStyle}>{props.content || props.text || props.name}</span>
|
|
547
496
|
);
|
|
548
497
|
|
|
549
498
|
const ButtonComponent = (props: any) => {
|
|
550
|
-
const
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
if (props.
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
if (props.text_style.font_weight) css.fontWeight = props.text_style.font_weight;
|
|
558
|
-
if (props.text_style.font_family) css.fontFamily = props.text_style.font_family;
|
|
559
|
-
if (props.text_style.text_align) css.textAlign = props.text_style.text_align;
|
|
499
|
+
const css: any = { ...props.parsedStyle, cursor: 'pointer', border: 'none' };
|
|
500
|
+
|
|
501
|
+
// If no layout, center text by default (most buttons center their text)
|
|
502
|
+
if (!props.layout) {
|
|
503
|
+
css.display = 'flex';
|
|
504
|
+
css.alignItems = 'center';
|
|
505
|
+
css.justifyContent = 'center';
|
|
560
506
|
}
|
|
561
507
|
return <button style={css}>{props.children || props.content || props.text || props.name}</button>;
|
|
562
508
|
};
|
|
@@ -568,11 +514,18 @@ export const registry: Record<string, React.FC<any>> = {
|
|
|
568
514
|
element: GenericContainer,
|
|
569
515
|
group: GenericContainer,
|
|
570
516
|
stack: GenericContainer,
|
|
517
|
+
Stack: GenericContainer,
|
|
518
|
+
Card: GenericContainer,
|
|
519
|
+
Grid: GenericContainer,
|
|
520
|
+
Header: GenericContainer,
|
|
521
|
+
Footer: GenericContainer,
|
|
571
522
|
text: TextComponent,
|
|
572
523
|
Text: TextComponent,
|
|
573
524
|
button: ButtonComponent,
|
|
574
|
-
|
|
575
|
-
|
|
525
|
+
Button: ButtonComponent,
|
|
526
|
+
input: (props: any) => <input style={props.parsedStyle} placeholder={props.content || props.name} />,
|
|
527
|
+
icon: (props: any) => <div style={{ ...props.parsedStyle, display:'inline-flex', alignItems:'center', justifyContent:'center' }}>⚙️</div>,
|
|
528
|
+
Icon: (props: any) => <div style={{ ...props.parsedStyle, display:'inline-flex', alignItems:'center', justifyContent:'center' }}>⚙️</div>,
|
|
576
529
|
};
|
|
577
530
|
`.trim());
|
|
578
531
|
|