@wireweave/core 1.1.0 → 1.2.0-beta.0
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/dist/index.cjs +5151 -2219
- package/dist/index.d.cts +783 -4
- package/dist/index.d.ts +783 -4
- package/dist/index.js +5120 -2216
- package/dist/parser.cjs +1017 -474
- package/dist/parser.d.cts +1 -1
- package/dist/parser.d.ts +1 -1
- package/dist/parser.js +1017 -474
- package/dist/renderer.cjs +1244 -1673
- package/dist/renderer.d.cts +42 -133
- package/dist/renderer.d.ts +42 -133
- package/dist/renderer.js +1244 -1670
- package/dist/{types-DtovIYS6.d.cts → types-lcJzPcR0.d.cts} +40 -2
- package/dist/{types-DtovIYS6.d.ts → types-lcJzPcR0.d.ts} +40 -2
- package/package.json +1 -1
package/dist/renderer.js
CHANGED
|
@@ -51,23 +51,7 @@ function getTheme(name) {
|
|
|
51
51
|
return name === "dark" ? darkTheme : defaultTheme;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
// src/renderer/styles
|
|
55
|
-
function generateComponentStyles(_theme, prefix = "wf") {
|
|
56
|
-
const parts = [
|
|
57
|
-
generateContainerStyles(prefix),
|
|
58
|
-
generateTextStyles(prefix),
|
|
59
|
-
generateInputStyles(_theme, prefix),
|
|
60
|
-
generateButtonStyles(_theme, prefix),
|
|
61
|
-
generateDisplayStyles(_theme, prefix),
|
|
62
|
-
generateDataStyles(_theme, prefix),
|
|
63
|
-
generateFeedbackStyles(_theme, prefix),
|
|
64
|
-
generateOverlayStyles(_theme, prefix),
|
|
65
|
-
generateNavigationStyles(_theme, prefix),
|
|
66
|
-
generateSemanticMarkerStyles(_theme, prefix),
|
|
67
|
-
generateAccessibilityStyles(prefix)
|
|
68
|
-
];
|
|
69
|
-
return parts.join("\n\n");
|
|
70
|
-
}
|
|
54
|
+
// src/renderer/styles/container.ts
|
|
71
55
|
function generateContainerStyles(prefix) {
|
|
72
56
|
return `/* Container Components */
|
|
73
57
|
.${prefix}-card {
|
|
@@ -77,12 +61,17 @@ function generateContainerStyles(prefix) {
|
|
|
77
61
|
padding: 16px;
|
|
78
62
|
}
|
|
79
63
|
|
|
80
|
-
/* Cards in flex rows
|
|
64
|
+
/* Cards in flex rows: respect explicit width, shrink if needed */
|
|
81
65
|
.${prefix}-row > .${prefix}-card {
|
|
82
|
-
flex:
|
|
66
|
+
flex: 0 1 auto;
|
|
83
67
|
min-width: 0;
|
|
84
68
|
}
|
|
85
69
|
|
|
70
|
+
/* Cards without explicit width should expand to fill space */
|
|
71
|
+
.${prefix}-row > .${prefix}-card-flex {
|
|
72
|
+
flex: 1 1 0%;
|
|
73
|
+
}
|
|
74
|
+
|
|
86
75
|
.${prefix}-card-title {
|
|
87
76
|
margin: 0 0 12px 0;
|
|
88
77
|
font-size: 18px;
|
|
@@ -202,6 +191,8 @@ function generateContainerStyles(prefix) {
|
|
|
202
191
|
padding: 16px;
|
|
203
192
|
}`;
|
|
204
193
|
}
|
|
194
|
+
|
|
195
|
+
// src/renderer/styles/text.ts
|
|
205
196
|
function generateTextStyles(prefix) {
|
|
206
197
|
return `/* Text Components */
|
|
207
198
|
.${prefix}-text {
|
|
@@ -236,6 +227,11 @@ function generateTextStyles(prefix) {
|
|
|
236
227
|
line-height: 1.25;
|
|
237
228
|
}
|
|
238
229
|
|
|
230
|
+
/* Remove bottom margin when title is in a row (inline with other elements) */
|
|
231
|
+
.${prefix}-row .${prefix}-title {
|
|
232
|
+
margin-bottom: 0;
|
|
233
|
+
}
|
|
234
|
+
|
|
239
235
|
h1.${prefix}-title { font-size: 36px; }
|
|
240
236
|
h2.${prefix}-title { font-size: 30px; }
|
|
241
237
|
h3.${prefix}-title { font-size: 24px; }
|
|
@@ -253,6 +249,8 @@ h6.${prefix}-title { font-size: 16px; }
|
|
|
253
249
|
opacity: 0.7;
|
|
254
250
|
}`;
|
|
255
251
|
}
|
|
252
|
+
|
|
253
|
+
// src/renderer/styles/input.ts
|
|
256
254
|
function generateInputStyles(_theme, prefix) {
|
|
257
255
|
return `/* Input Components */
|
|
258
256
|
.${prefix}-form-field {
|
|
@@ -452,6 +450,8 @@ function generateInputStyles(_theme, prefix) {
|
|
|
452
450
|
cursor: pointer;
|
|
453
451
|
}`;
|
|
454
452
|
}
|
|
453
|
+
|
|
454
|
+
// src/renderer/styles/button.ts
|
|
455
455
|
function generateButtonStyles(_theme, prefix) {
|
|
456
456
|
return `/* Button Components */
|
|
457
457
|
.${prefix}-button {
|
|
@@ -579,6 +579,8 @@ function generateButtonStyles(_theme, prefix) {
|
|
|
579
579
|
.${prefix}-button.${prefix}-justify-end { justify-content: flex-end; }
|
|
580
580
|
.${prefix}-button.${prefix}-justify-between { justify-content: space-between; }`;
|
|
581
581
|
}
|
|
582
|
+
|
|
583
|
+
// src/renderer/styles/display.ts
|
|
582
584
|
function generateDisplayStyles(_theme, prefix) {
|
|
583
585
|
return `/* Display Components */
|
|
584
586
|
.${prefix}-image {
|
|
@@ -630,6 +632,30 @@ img.${prefix}-image {
|
|
|
630
632
|
font-size: 14px;
|
|
631
633
|
}
|
|
632
634
|
|
|
635
|
+
.${prefix}-placeholder-with-children {
|
|
636
|
+
position: relative;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
.${prefix}-placeholder-label {
|
|
640
|
+
position: absolute;
|
|
641
|
+
top: 50%;
|
|
642
|
+
left: 50%;
|
|
643
|
+
transform: translate(-50%, -50%);
|
|
644
|
+
z-index: 0;
|
|
645
|
+
pointer-events: none;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
.${prefix}-placeholder-overlay {
|
|
649
|
+
position: absolute;
|
|
650
|
+
top: 0;
|
|
651
|
+
left: 0;
|
|
652
|
+
right: 0;
|
|
653
|
+
bottom: 0;
|
|
654
|
+
z-index: 1;
|
|
655
|
+
display: flex;
|
|
656
|
+
flex-direction: column;
|
|
657
|
+
}
|
|
658
|
+
|
|
633
659
|
.${prefix}-avatar {
|
|
634
660
|
display: inline-flex;
|
|
635
661
|
align-items: center;
|
|
@@ -745,12 +771,12 @@ svg.${prefix}-icon {
|
|
|
745
771
|
display: block;
|
|
746
772
|
}
|
|
747
773
|
|
|
748
|
-
/* Icon size tokens */
|
|
774
|
+
/* Icon size tokens - matches SVG renderer */
|
|
749
775
|
svg.${prefix}-icon-xs { width: 12px; height: 12px; }
|
|
750
|
-
svg.${prefix}-icon-sm { width:
|
|
751
|
-
svg.${prefix}-icon-md { width:
|
|
752
|
-
svg.${prefix}-icon-lg { width:
|
|
753
|
-
svg.${prefix}-icon-xl { width:
|
|
776
|
+
svg.${prefix}-icon-sm { width: 16px; height: 16px; }
|
|
777
|
+
svg.${prefix}-icon-md { width: 20px; height: 20px; }
|
|
778
|
+
svg.${prefix}-icon-lg { width: 24px; height: 24px; }
|
|
779
|
+
svg.${prefix}-icon-xl { width: 32px; height: 32px; }
|
|
754
780
|
|
|
755
781
|
.${prefix}-icon svg {
|
|
756
782
|
display: block;
|
|
@@ -762,6 +788,8 @@ svg.${prefix}-icon-xl { width: 24px; height: 24px; }
|
|
|
762
788
|
justify-content: center;
|
|
763
789
|
}`;
|
|
764
790
|
}
|
|
791
|
+
|
|
792
|
+
// src/renderer/styles/data.ts
|
|
765
793
|
function generateDataStyles(_theme, prefix) {
|
|
766
794
|
return `/* Data Components */
|
|
767
795
|
.${prefix}-table {
|
|
@@ -820,6 +848,8 @@ function generateDataStyles(_theme, prefix) {
|
|
|
820
848
|
border-bottom: none;
|
|
821
849
|
}`;
|
|
822
850
|
}
|
|
851
|
+
|
|
852
|
+
// src/renderer/styles/feedback.ts
|
|
823
853
|
function generateFeedbackStyles(_theme, prefix) {
|
|
824
854
|
return `/* Feedback Components */
|
|
825
855
|
.${prefix}-alert {
|
|
@@ -911,6 +941,8 @@ function generateFeedbackStyles(_theme, prefix) {
|
|
|
911
941
|
to { transform: rotate(360deg); }
|
|
912
942
|
}`;
|
|
913
943
|
}
|
|
944
|
+
|
|
945
|
+
// src/renderer/styles/overlay.ts
|
|
914
946
|
function generateOverlayStyles(_theme, prefix) {
|
|
915
947
|
return `/* Overlay Components */
|
|
916
948
|
.${prefix}-tooltip-wrapper {
|
|
@@ -1009,6 +1041,8 @@ function generateOverlayStyles(_theme, prefix) {
|
|
|
1009
1041
|
cursor: not-allowed;
|
|
1010
1042
|
}`;
|
|
1011
1043
|
}
|
|
1044
|
+
|
|
1045
|
+
// src/renderer/styles/navigation.ts
|
|
1012
1046
|
function generateNavigationStyles(_theme, prefix) {
|
|
1013
1047
|
return `/* Navigation Components */
|
|
1014
1048
|
.${prefix}-nav {
|
|
@@ -1046,6 +1080,27 @@ function generateNavigationStyles(_theme, prefix) {
|
|
|
1046
1080
|
cursor: not-allowed;
|
|
1047
1081
|
}
|
|
1048
1082
|
|
|
1083
|
+
.${prefix}-nav-group {
|
|
1084
|
+
display: flex;
|
|
1085
|
+
flex-direction: column;
|
|
1086
|
+
gap: 4px;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
.${prefix}-nav-group-label {
|
|
1090
|
+
font-size: 11px;
|
|
1091
|
+
font-weight: 500;
|
|
1092
|
+
color: var(--${prefix}-muted);
|
|
1093
|
+
text-transform: uppercase;
|
|
1094
|
+
letter-spacing: 0.05em;
|
|
1095
|
+
padding: 8px 16px 4px;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
.${prefix}-nav-divider {
|
|
1099
|
+
margin: 8px 0;
|
|
1100
|
+
border: none;
|
|
1101
|
+
border-top: 1px solid var(--${prefix}-border);
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1049
1104
|
.${prefix}-tabs {
|
|
1050
1105
|
border-bottom: 1px solid var(--${prefix}-border);
|
|
1051
1106
|
}
|
|
@@ -1100,6 +1155,8 @@ function generateNavigationStyles(_theme, prefix) {
|
|
|
1100
1155
|
color: var(--${prefix}-muted);
|
|
1101
1156
|
}`;
|
|
1102
1157
|
}
|
|
1158
|
+
|
|
1159
|
+
// src/renderer/styles/semantic.ts
|
|
1103
1160
|
function generateSemanticMarkerStyles(_theme, prefix) {
|
|
1104
1161
|
return `/* Semantic Markers */
|
|
1105
1162
|
|
|
@@ -1186,6 +1243,8 @@ function generateSemanticMarkerStyles(_theme, prefix) {
|
|
|
1186
1243
|
color: var(--${prefix}-muted);
|
|
1187
1244
|
}`;
|
|
1188
1245
|
}
|
|
1246
|
+
|
|
1247
|
+
// src/renderer/styles/accessibility.ts
|
|
1189
1248
|
function generateAccessibilityStyles(prefix) {
|
|
1190
1249
|
return `/* Accessibility Utilities */
|
|
1191
1250
|
.sr-only {
|
|
@@ -1223,6 +1282,24 @@ function generateAccessibilityStyles(prefix) {
|
|
|
1223
1282
|
}`;
|
|
1224
1283
|
}
|
|
1225
1284
|
|
|
1285
|
+
// src/renderer/styles-components.ts
|
|
1286
|
+
function generateComponentStyles(_theme, prefix = "wf") {
|
|
1287
|
+
const parts = [
|
|
1288
|
+
generateContainerStyles(prefix),
|
|
1289
|
+
generateTextStyles(prefix),
|
|
1290
|
+
generateInputStyles(_theme, prefix),
|
|
1291
|
+
generateButtonStyles(_theme, prefix),
|
|
1292
|
+
generateDisplayStyles(_theme, prefix),
|
|
1293
|
+
generateDataStyles(_theme, prefix),
|
|
1294
|
+
generateFeedbackStyles(_theme, prefix),
|
|
1295
|
+
generateOverlayStyles(_theme, prefix),
|
|
1296
|
+
generateNavigationStyles(_theme, prefix),
|
|
1297
|
+
generateSemanticMarkerStyles(_theme, prefix),
|
|
1298
|
+
generateAccessibilityStyles(prefix)
|
|
1299
|
+
];
|
|
1300
|
+
return parts.join("\n\n");
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1226
1303
|
// src/renderer/styles.ts
|
|
1227
1304
|
function generateStyles(theme, prefix = "wf") {
|
|
1228
1305
|
const parts = [
|
|
@@ -1263,7 +1340,6 @@ function generateBaseStyles(prefix) {
|
|
|
1263
1340
|
font-family: var(--${prefix}-font);
|
|
1264
1341
|
color: var(--${prefix}-fg);
|
|
1265
1342
|
background: var(--${prefix}-bg);
|
|
1266
|
-
min-height: 100vh;
|
|
1267
1343
|
box-sizing: border-box;
|
|
1268
1344
|
position: relative;
|
|
1269
1345
|
display: flex;
|
|
@@ -1274,10 +1350,19 @@ function generateBaseStyles(prefix) {
|
|
|
1274
1350
|
overflow: hidden;
|
|
1275
1351
|
}
|
|
1276
1352
|
|
|
1353
|
+
/* Col direct child of page should fill page height */
|
|
1354
|
+
.${prefix}-page > .${prefix}-col {
|
|
1355
|
+
flex: 1;
|
|
1356
|
+
min-height: 0;
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1277
1359
|
/* Row containing sidebar should fill remaining space */
|
|
1278
1360
|
.${prefix}-page > .${prefix}-row:has(.${prefix}-sidebar),
|
|
1279
|
-
.${prefix}-page > .${prefix}-row:has(.${prefix}-main)
|
|
1361
|
+
.${prefix}-page > .${prefix}-row:has(.${prefix}-main),
|
|
1362
|
+
.${prefix}-page > .${prefix}-col > .${prefix}-row:has(.${prefix}-sidebar),
|
|
1363
|
+
.${prefix}-page > .${prefix}-col > .${prefix}-row:has(.${prefix}-main) {
|
|
1280
1364
|
flex: 1;
|
|
1365
|
+
min-height: 0;
|
|
1281
1366
|
align-items: stretch;
|
|
1282
1367
|
}
|
|
1283
1368
|
|
|
@@ -1320,10 +1405,15 @@ function generateGridClasses(_theme, prefix) {
|
|
|
1320
1405
|
box-sizing: border-box;
|
|
1321
1406
|
}
|
|
1322
1407
|
|
|
1408
|
+
/* When explicit width is set, don't flex-grow */
|
|
1409
|
+
.${prefix}-row[style*="width:"],
|
|
1410
|
+
.${prefix}-col[style*="width:"] {
|
|
1411
|
+
flex: 0 0 auto;
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1323
1414
|
`;
|
|
1324
1415
|
for (let i = 1; i <= 12; i++) {
|
|
1325
|
-
|
|
1326
|
-
css += `.${prefix}-col-${i} { flex: 0 0 auto; width: ${width}%; }
|
|
1416
|
+
css += `.${prefix}-col-${i} { flex: ${i} 0 0%; min-width: 0; }
|
|
1327
1417
|
`;
|
|
1328
1418
|
}
|
|
1329
1419
|
return css;
|
|
@@ -1491,6 +1581,26 @@ function generateLayoutClasses(prefix) {
|
|
|
1491
1581
|
.${prefix}-main {
|
|
1492
1582
|
flex: 1;
|
|
1493
1583
|
padding: 16px;
|
|
1584
|
+
display: flex;
|
|
1585
|
+
flex-direction: column;
|
|
1586
|
+
min-height: 0;
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
/* Scrollable main content */
|
|
1590
|
+
.${prefix}-main.${prefix}-scroll {
|
|
1591
|
+
overflow-y: auto;
|
|
1592
|
+
overflow-x: hidden;
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
/* Col containing scrollable main needs min-height: 0 for scroll to work */
|
|
1596
|
+
.${prefix}-col:has(> .${prefix}-main.${prefix}-scroll) {
|
|
1597
|
+
min-height: 0;
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
/* Main content should align to top, not stretch to fill */
|
|
1601
|
+
/* But allow explicit flex=1 to override */
|
|
1602
|
+
.${prefix}-main > .${prefix}-col:not(.${prefix}-flex-1) {
|
|
1603
|
+
flex: 0 0 auto;
|
|
1494
1604
|
}
|
|
1495
1605
|
|
|
1496
1606
|
.${prefix}-footer {
|
|
@@ -1507,6 +1617,7 @@ function generateLayoutClasses(prefix) {
|
|
|
1507
1617
|
border-right: 1px solid var(--${prefix}-border);
|
|
1508
1618
|
padding: 16px 16px 16px 20px;
|
|
1509
1619
|
flex-shrink: 0;
|
|
1620
|
+
align-self: stretch;
|
|
1510
1621
|
}
|
|
1511
1622
|
|
|
1512
1623
|
.${prefix}-sidebar-right {
|
|
@@ -1720,6 +1831,248 @@ function resolveViewport(viewport, device) {
|
|
|
1720
1831
|
return DEFAULT_VIEWPORT;
|
|
1721
1832
|
}
|
|
1722
1833
|
|
|
1834
|
+
// src/renderer/html/components.ts
|
|
1835
|
+
function buildClassString(classes) {
|
|
1836
|
+
return classes.filter(Boolean).join(" ");
|
|
1837
|
+
}
|
|
1838
|
+
var SIZE_TOKENS = {
|
|
1839
|
+
icon: { xs: 12, sm: 14, md: 16, lg: 20, xl: 24 },
|
|
1840
|
+
avatar: { xs: 24, sm: 32, md: 40, lg: 48, xl: 64 },
|
|
1841
|
+
spinner: { xs: 12, sm: 16, md: 24, lg: 32, xl: 48 }
|
|
1842
|
+
};
|
|
1843
|
+
function resolveSizeValue(size, componentType, prefix) {
|
|
1844
|
+
if (size === void 0) {
|
|
1845
|
+
return {};
|
|
1846
|
+
}
|
|
1847
|
+
if (typeof size === "string") {
|
|
1848
|
+
const tokens = SIZE_TOKENS[componentType];
|
|
1849
|
+
if (size in tokens) {
|
|
1850
|
+
return { className: `${prefix}-${componentType}-${size}` };
|
|
1851
|
+
}
|
|
1852
|
+
const parsed = parseInt(size, 10);
|
|
1853
|
+
if (!isNaN(parsed)) {
|
|
1854
|
+
return { style: `width: ${parsed}px; height: ${parsed}px;` };
|
|
1855
|
+
}
|
|
1856
|
+
return {};
|
|
1857
|
+
}
|
|
1858
|
+
if (typeof size === "number") {
|
|
1859
|
+
return { style: `width: ${size}px; height: ${size}px;` };
|
|
1860
|
+
}
|
|
1861
|
+
return {};
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
// src/renderer/html/renderers/layout.ts
|
|
1865
|
+
function renderHeader(node, ctx) {
|
|
1866
|
+
const classes = ctx.buildClassString([
|
|
1867
|
+
`${ctx.prefix}-header`,
|
|
1868
|
+
node.border === false ? `${ctx.prefix}-no-border` : void 0,
|
|
1869
|
+
...ctx.getCommonClasses(node)
|
|
1870
|
+
]);
|
|
1871
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1872
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1873
|
+
const children = ctx.renderChildren(node.children);
|
|
1874
|
+
return `<header class="${classes}"${styleAttr}>
|
|
1875
|
+
${children}
|
|
1876
|
+
</header>`;
|
|
1877
|
+
}
|
|
1878
|
+
function renderMain(node, ctx) {
|
|
1879
|
+
const classes = ctx.buildClassString([
|
|
1880
|
+
`${ctx.prefix}-main`,
|
|
1881
|
+
node.scroll ? `${ctx.prefix}-scroll` : void 0,
|
|
1882
|
+
...ctx.getCommonClasses(node)
|
|
1883
|
+
]);
|
|
1884
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1885
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1886
|
+
const children = ctx.renderChildren(node.children);
|
|
1887
|
+
return `<main class="${classes}"${styleAttr}>
|
|
1888
|
+
${children}
|
|
1889
|
+
</main>`;
|
|
1890
|
+
}
|
|
1891
|
+
function renderFooter(node, ctx) {
|
|
1892
|
+
const classes = ctx.buildClassString([
|
|
1893
|
+
`${ctx.prefix}-footer`,
|
|
1894
|
+
node.border === false ? `${ctx.prefix}-no-border` : void 0,
|
|
1895
|
+
...ctx.getCommonClasses(node)
|
|
1896
|
+
]);
|
|
1897
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1898
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1899
|
+
const children = ctx.renderChildren(node.children);
|
|
1900
|
+
return `<footer class="${classes}"${styleAttr}>
|
|
1901
|
+
${children}
|
|
1902
|
+
</footer>`;
|
|
1903
|
+
}
|
|
1904
|
+
function renderSidebar(node, ctx) {
|
|
1905
|
+
const classes = ctx.buildClassString([
|
|
1906
|
+
`${ctx.prefix}-sidebar`,
|
|
1907
|
+
node.position === "right" ? `${ctx.prefix}-sidebar-right` : void 0,
|
|
1908
|
+
...ctx.getCommonClasses(node)
|
|
1909
|
+
]);
|
|
1910
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1911
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1912
|
+
const children = ctx.renderChildren(node.children);
|
|
1913
|
+
return `<aside class="${classes}"${styleAttr}>
|
|
1914
|
+
${children}
|
|
1915
|
+
</aside>`;
|
|
1916
|
+
}
|
|
1917
|
+
function renderSection(node, ctx) {
|
|
1918
|
+
const classes = ctx.buildClassString([
|
|
1919
|
+
`${ctx.prefix}-section`,
|
|
1920
|
+
...ctx.getCommonClasses(node)
|
|
1921
|
+
]);
|
|
1922
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1923
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1924
|
+
const title = node.title ? `<h2 class="${ctx.prefix}-title">${ctx.escapeHtml(node.title)}</h2>
|
|
1925
|
+
` : "";
|
|
1926
|
+
const children = ctx.renderChildren(node.children);
|
|
1927
|
+
return `<section class="${classes}"${styleAttr}>
|
|
1928
|
+
${title}${children}
|
|
1929
|
+
</section>`;
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
// src/renderer/html/renderers/grid.ts
|
|
1933
|
+
function renderRow(node, ctx) {
|
|
1934
|
+
const classes = ctx.buildClassString([
|
|
1935
|
+
`${ctx.prefix}-row`,
|
|
1936
|
+
...ctx.getCommonClasses(node)
|
|
1937
|
+
]);
|
|
1938
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1939
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1940
|
+
const children = ctx.renderChildren(node.children);
|
|
1941
|
+
return `<div class="${classes}"${styleAttr}>
|
|
1942
|
+
${children}
|
|
1943
|
+
</div>`;
|
|
1944
|
+
}
|
|
1945
|
+
function renderCol(node, ctx) {
|
|
1946
|
+
const classes = ctx.buildClassString([
|
|
1947
|
+
`${ctx.prefix}-col`,
|
|
1948
|
+
node.span ? `${ctx.prefix}-col-${node.span}` : void 0,
|
|
1949
|
+
// Responsive breakpoint classes
|
|
1950
|
+
node.sm ? `${ctx.prefix}-col-sm-${node.sm}` : void 0,
|
|
1951
|
+
node.md ? `${ctx.prefix}-col-md-${node.md}` : void 0,
|
|
1952
|
+
node.lg ? `${ctx.prefix}-col-lg-${node.lg}` : void 0,
|
|
1953
|
+
node.xl ? `${ctx.prefix}-col-xl-${node.xl}` : void 0,
|
|
1954
|
+
...ctx.getCommonClasses(node)
|
|
1955
|
+
]);
|
|
1956
|
+
const styles = ctx.buildColStyles(node);
|
|
1957
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1958
|
+
const children = ctx.renderChildren(node.children);
|
|
1959
|
+
return `<div class="${classes}"${styleAttr}>
|
|
1960
|
+
${children}
|
|
1961
|
+
</div>`;
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
// src/renderer/html/renderers/container.ts
|
|
1965
|
+
function renderCard(node, ctx) {
|
|
1966
|
+
const hasExplicitWidth = node.w !== void 0;
|
|
1967
|
+
const classes = ctx.buildClassString([
|
|
1968
|
+
`${ctx.prefix}-card`,
|
|
1969
|
+
!hasExplicitWidth ? `${ctx.prefix}-card-flex` : void 0,
|
|
1970
|
+
node.shadow ? `${ctx.prefix}-card-shadow-${node.shadow}` : void 0,
|
|
1971
|
+
...ctx.getCommonClasses(node)
|
|
1972
|
+
]);
|
|
1973
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1974
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1975
|
+
const title = node.title ? `<h3 class="${ctx.prefix}-title">${ctx.escapeHtml(node.title)}</h3>
|
|
1976
|
+
` : "";
|
|
1977
|
+
const children = ctx.renderChildren(node.children);
|
|
1978
|
+
return `<div class="${classes}"${styleAttr}>
|
|
1979
|
+
${title}${children}
|
|
1980
|
+
</div>`;
|
|
1981
|
+
}
|
|
1982
|
+
function renderModal(node, ctx) {
|
|
1983
|
+
const classes = ctx.buildClassString([
|
|
1984
|
+
`${ctx.prefix}-modal`,
|
|
1985
|
+
...ctx.getCommonClasses(node)
|
|
1986
|
+
]);
|
|
1987
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1988
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1989
|
+
const title = node.title ? `<h2 class="${ctx.prefix}-title">${ctx.escapeHtml(node.title)}</h2>
|
|
1990
|
+
` : "";
|
|
1991
|
+
const children = ctx.renderChildren(node.children);
|
|
1992
|
+
return `<div class="${ctx.prefix}-modal-backdrop">
|
|
1993
|
+
<div class="${classes}"${styleAttr} role="dialog" aria-modal="true">
|
|
1994
|
+
${title}${children}
|
|
1995
|
+
</div>
|
|
1996
|
+
</div>`;
|
|
1997
|
+
}
|
|
1998
|
+
function renderDrawer(node, ctx) {
|
|
1999
|
+
const position = node.position || "left";
|
|
2000
|
+
const classes = ctx.buildClassString([
|
|
2001
|
+
`${ctx.prefix}-drawer`,
|
|
2002
|
+
`${ctx.prefix}-drawer-${position}`,
|
|
2003
|
+
...ctx.getCommonClasses(node)
|
|
2004
|
+
]);
|
|
2005
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2006
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2007
|
+
const title = node.title ? `<h2 class="${ctx.prefix}-title">${ctx.escapeHtml(node.title)}</h2>
|
|
2008
|
+
` : "";
|
|
2009
|
+
const children = ctx.renderChildren(node.children);
|
|
2010
|
+
return `<aside class="${classes}"${styleAttr}>
|
|
2011
|
+
${title}${children}
|
|
2012
|
+
</aside>`;
|
|
2013
|
+
}
|
|
2014
|
+
function renderAccordion(node, ctx) {
|
|
2015
|
+
const classes = ctx.buildClassString([
|
|
2016
|
+
`${ctx.prefix}-accordion`,
|
|
2017
|
+
...ctx.getCommonClasses(node)
|
|
2018
|
+
]);
|
|
2019
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2020
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2021
|
+
const title = node.title ? `<button class="${ctx.prefix}-accordion-header">${ctx.escapeHtml(node.title)}</button>
|
|
2022
|
+
` : "";
|
|
2023
|
+
const children = ctx.renderChildren(node.children);
|
|
2024
|
+
return `<div class="${classes}"${styleAttr}>
|
|
2025
|
+
${title}<div class="${ctx.prefix}-accordion-content">
|
|
2026
|
+
${children}
|
|
2027
|
+
</div>
|
|
2028
|
+
</div>`;
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
// src/renderer/html/renderers/text.ts
|
|
2032
|
+
function renderText(node, ctx) {
|
|
2033
|
+
const classes = ctx.buildClassString([
|
|
2034
|
+
`${ctx.prefix}-text`,
|
|
2035
|
+
node.size ? `${ctx.prefix}-text-${node.size}` : void 0,
|
|
2036
|
+
node.weight ? `${ctx.prefix}-text-${node.weight}` : void 0,
|
|
2037
|
+
node.align ? `${ctx.prefix}-text-${node.align}` : void 0,
|
|
2038
|
+
node.muted ? `${ctx.prefix}-text-muted` : void 0,
|
|
2039
|
+
...ctx.getCommonClasses(node)
|
|
2040
|
+
]);
|
|
2041
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2042
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2043
|
+
return `<p class="${classes}"${styleAttr}>${ctx.escapeHtml(node.content)}</p>`;
|
|
2044
|
+
}
|
|
2045
|
+
function renderTitle(node, ctx) {
|
|
2046
|
+
const level = node.level || 1;
|
|
2047
|
+
const tag = `h${level}`;
|
|
2048
|
+
const classes = ctx.buildClassString([
|
|
2049
|
+
`${ctx.prefix}-title`,
|
|
2050
|
+
node.size ? `${ctx.prefix}-text-${node.size}` : void 0,
|
|
2051
|
+
node.align ? `${ctx.prefix}-text-${node.align}` : void 0,
|
|
2052
|
+
...ctx.getCommonClasses(node)
|
|
2053
|
+
]);
|
|
2054
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2055
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2056
|
+
return `<${tag} class="${classes}"${styleAttr}>${ctx.escapeHtml(node.content)}</${tag}>`;
|
|
2057
|
+
}
|
|
2058
|
+
function renderLink(node, ctx) {
|
|
2059
|
+
const classes = ctx.buildClassString([
|
|
2060
|
+
`${ctx.prefix}-link`,
|
|
2061
|
+
...ctx.getCommonClasses(node)
|
|
2062
|
+
]);
|
|
2063
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2064
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2065
|
+
const attrs = {
|
|
2066
|
+
class: classes,
|
|
2067
|
+
href: node.href || "#"
|
|
2068
|
+
};
|
|
2069
|
+
if (node.external) {
|
|
2070
|
+
attrs.target = "_blank";
|
|
2071
|
+
attrs.rel = "noopener noreferrer";
|
|
2072
|
+
}
|
|
2073
|
+
return `<a${ctx.buildAttrsString(attrs)}${styleAttr}>${ctx.escapeHtml(node.content)}</a>`;
|
|
2074
|
+
}
|
|
2075
|
+
|
|
1723
2076
|
// src/icons/lucide-icons.ts
|
|
1724
2077
|
var lucideIcons = {
|
|
1725
2078
|
"a-arrow-down": [
|
|
@@ -48076,14 +48429,39 @@ var lucideIcons = {
|
|
|
48076
48429
|
]
|
|
48077
48430
|
]
|
|
48078
48431
|
};
|
|
48432
|
+
var iconAliases = {
|
|
48433
|
+
"home": "house",
|
|
48434
|
+
"plus-square": "square-plus",
|
|
48435
|
+
"minus-square": "square-minus",
|
|
48436
|
+
"x-square": "square-x",
|
|
48437
|
+
"check-square": "square-check",
|
|
48438
|
+
"edit": "pencil",
|
|
48439
|
+
"edit-2": "pencil",
|
|
48440
|
+
"edit-3": "pencil-line",
|
|
48441
|
+
"trash": "trash-2",
|
|
48442
|
+
"delete": "trash-2",
|
|
48443
|
+
"close": "x",
|
|
48444
|
+
"menu": "menu",
|
|
48445
|
+
"hamburger": "menu",
|
|
48446
|
+
"dots": "more-horizontal",
|
|
48447
|
+
"dots-vertical": "more-vertical",
|
|
48448
|
+
"cog": "settings",
|
|
48449
|
+
"gear": "settings"
|
|
48450
|
+
};
|
|
48079
48451
|
function getIconData(name) {
|
|
48080
48452
|
if (lucideIcons[name]) {
|
|
48081
48453
|
return lucideIcons[name];
|
|
48082
48454
|
}
|
|
48455
|
+
if (iconAliases[name] && lucideIcons[iconAliases[name]]) {
|
|
48456
|
+
return lucideIcons[iconAliases[name]];
|
|
48457
|
+
}
|
|
48083
48458
|
const kebabName = name.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
48084
48459
|
if (lucideIcons[kebabName]) {
|
|
48085
48460
|
return lucideIcons[kebabName];
|
|
48086
48461
|
}
|
|
48462
|
+
if (iconAliases[kebabName] && lucideIcons[iconAliases[kebabName]]) {
|
|
48463
|
+
return lucideIcons[iconAliases[kebabName]];
|
|
48464
|
+
}
|
|
48087
48465
|
return void 0;
|
|
48088
48466
|
}
|
|
48089
48467
|
function renderIconSvg(data, _size = 24, strokeWidth = 2, className = "", styleAttr = "") {
|
|
@@ -48094,34 +48472,658 @@ function renderIconSvg(data, _size = 24, strokeWidth = 2, className = "", styleA
|
|
|
48094
48472
|
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="${strokeWidth}" stroke-linecap="round" stroke-linejoin="round" class="${className}"${styleAttr}>${elements}</svg>`;
|
|
48095
48473
|
}
|
|
48096
48474
|
|
|
48097
|
-
// src/renderer/html/
|
|
48098
|
-
function
|
|
48099
|
-
|
|
48475
|
+
// src/renderer/html/renderers/button.ts
|
|
48476
|
+
function renderButton(node, ctx) {
|
|
48477
|
+
const isIconOnly = node.icon && (!node.content.trim() || node.content === "Button");
|
|
48478
|
+
const classes = ctx.buildClassString([
|
|
48479
|
+
`${ctx.prefix}-button`,
|
|
48480
|
+
node.primary ? `${ctx.prefix}-button-primary` : void 0,
|
|
48481
|
+
node.secondary ? `${ctx.prefix}-button-secondary` : void 0,
|
|
48482
|
+
node.outline ? `${ctx.prefix}-button-outline` : void 0,
|
|
48483
|
+
node.ghost ? `${ctx.prefix}-button-ghost` : void 0,
|
|
48484
|
+
node.danger ? `${ctx.prefix}-button-danger` : void 0,
|
|
48485
|
+
node.size ? `${ctx.prefix}-button-${node.size}` : void 0,
|
|
48486
|
+
node.disabled ? `${ctx.prefix}-button-disabled` : void 0,
|
|
48487
|
+
node.loading ? `${ctx.prefix}-button-loading` : void 0,
|
|
48488
|
+
isIconOnly ? `${ctx.prefix}-button-icon-only` : void 0,
|
|
48489
|
+
...ctx.getCommonClasses(node)
|
|
48490
|
+
]);
|
|
48491
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48492
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48493
|
+
const attrs = {
|
|
48494
|
+
class: classes,
|
|
48495
|
+
disabled: node.disabled
|
|
48496
|
+
};
|
|
48497
|
+
let icon = "";
|
|
48498
|
+
if (node.icon) {
|
|
48499
|
+
const iconData = getIconData(node.icon);
|
|
48500
|
+
if (iconData) {
|
|
48501
|
+
icon = renderIconSvg(iconData, 16, 2, `${ctx.prefix}-icon`);
|
|
48502
|
+
} else {
|
|
48503
|
+
icon = `<span class="${ctx.prefix}-icon">[${ctx.escapeHtml(node.icon)}]</span>`;
|
|
48504
|
+
}
|
|
48505
|
+
}
|
|
48506
|
+
const loading = node.loading ? `<span class="${ctx.prefix}-spinner ${ctx.prefix}-spinner-sm"></span>` : "";
|
|
48507
|
+
const content = isIconOnly ? "" : ctx.escapeHtml(node.content);
|
|
48508
|
+
return `<button${ctx.buildAttrsString(attrs)}${styleAttr}>${loading}${icon}${content}</button>`;
|
|
48100
48509
|
}
|
|
48101
|
-
|
|
48102
|
-
|
|
48103
|
-
|
|
48104
|
-
|
|
48105
|
-
}
|
|
48106
|
-
|
|
48107
|
-
|
|
48108
|
-
|
|
48510
|
+
|
|
48511
|
+
// src/renderer/html/renderers/feedback.ts
|
|
48512
|
+
function renderAlert(node, ctx) {
|
|
48513
|
+
const classes = ctx.buildClassString([
|
|
48514
|
+
`${ctx.prefix}-alert`,
|
|
48515
|
+
node.variant ? `${ctx.prefix}-alert-${node.variant}` : void 0,
|
|
48516
|
+
...ctx.getCommonClasses(node)
|
|
48517
|
+
]);
|
|
48518
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48519
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48520
|
+
const dismissBtn = node.dismissible ? ` <button class="${ctx.prefix}-alert-close" aria-label="Close">×</button>` : "";
|
|
48521
|
+
return `<div class="${classes}"${styleAttr} role="alert">${ctx.escapeHtml(node.content)}${dismissBtn}</div>`;
|
|
48522
|
+
}
|
|
48523
|
+
function renderToast(node, ctx) {
|
|
48524
|
+
const classes = ctx.buildClassString([
|
|
48525
|
+
`${ctx.prefix}-toast`,
|
|
48526
|
+
node.position ? `${ctx.prefix}-toast-${node.position}` : void 0,
|
|
48527
|
+
node.variant ? `${ctx.prefix}-toast-${node.variant}` : void 0,
|
|
48528
|
+
...ctx.getCommonClasses(node)
|
|
48529
|
+
]);
|
|
48530
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48531
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48532
|
+
return `<div class="${classes}"${styleAttr} role="status">${ctx.escapeHtml(node.content)}</div>`;
|
|
48533
|
+
}
|
|
48534
|
+
function renderProgress(node, ctx) {
|
|
48535
|
+
const classes = ctx.buildClassString([
|
|
48536
|
+
`${ctx.prefix}-progress`,
|
|
48537
|
+
...ctx.getCommonClasses(node)
|
|
48538
|
+
]);
|
|
48539
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48540
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48541
|
+
const value = node.value || 0;
|
|
48542
|
+
const max = node.max || 100;
|
|
48543
|
+
const percentage = Math.round(value / max * 100);
|
|
48544
|
+
const label = node.label ? `<span class="${ctx.prefix}-progress-label">${ctx.escapeHtml(node.label)}</span>` : "";
|
|
48545
|
+
if (node.indeterminate) {
|
|
48546
|
+
return `<div class="${classes} ${ctx.prefix}-progress-indeterminate"${styleAttr} role="progressbar">${label}</div>`;
|
|
48109
48547
|
}
|
|
48110
|
-
|
|
48111
|
-
|
|
48112
|
-
|
|
48113
|
-
|
|
48548
|
+
return `<div class="${classes}"${styleAttr} role="progressbar" aria-valuenow="${value}" aria-valuemin="0" aria-valuemax="${max}">
|
|
48549
|
+
${label}
|
|
48550
|
+
<div class="${ctx.prefix}-progress-bar" style="width: ${percentage}%"></div>
|
|
48551
|
+
</div>`;
|
|
48552
|
+
}
|
|
48553
|
+
function renderSpinner(node, ctx) {
|
|
48554
|
+
const sizeResolved = resolveSizeValue(node.size, "spinner", ctx.prefix);
|
|
48555
|
+
const classes = ctx.buildClassString([
|
|
48556
|
+
`${ctx.prefix}-spinner`,
|
|
48557
|
+
sizeResolved.className,
|
|
48558
|
+
...ctx.getCommonClasses(node)
|
|
48559
|
+
]);
|
|
48560
|
+
const baseStyles = ctx.buildCommonStyles(node);
|
|
48561
|
+
const sizeStyle = sizeResolved.style || "";
|
|
48562
|
+
const combinedStyles = baseStyles && sizeStyle ? `${baseStyles}; ${sizeStyle}` : baseStyles || sizeStyle;
|
|
48563
|
+
const styleAttr = combinedStyles ? ` style="${combinedStyles}"` : "";
|
|
48564
|
+
const label = node.label || "Loading...";
|
|
48565
|
+
return `<span class="${classes}"${styleAttr} role="status" aria-label="${ctx.escapeHtml(label)}"></span>`;
|
|
48566
|
+
}
|
|
48567
|
+
|
|
48568
|
+
// src/renderer/html/renderers/input.ts
|
|
48569
|
+
function renderInput(node, ctx) {
|
|
48570
|
+
const inputClasses = ctx.buildClassString([
|
|
48571
|
+
`${ctx.prefix}-input`,
|
|
48572
|
+
node.icon ? `${ctx.prefix}-input-with-icon` : void 0,
|
|
48573
|
+
...ctx.getCommonClasses(node)
|
|
48574
|
+
]);
|
|
48575
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48576
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48577
|
+
const attrs = {
|
|
48578
|
+
class: inputClasses,
|
|
48579
|
+
type: node.inputType || "text",
|
|
48580
|
+
placeholder: node.placeholder,
|
|
48581
|
+
value: node.value,
|
|
48582
|
+
disabled: node.disabled,
|
|
48583
|
+
required: node.required,
|
|
48584
|
+
readonly: node.readonly
|
|
48585
|
+
};
|
|
48586
|
+
const inputElement = `<input${ctx.buildAttrsString(attrs)} />`;
|
|
48587
|
+
if (node.icon) {
|
|
48588
|
+
const iconData = getIconData(node.icon);
|
|
48589
|
+
let iconHtml;
|
|
48590
|
+
if (iconData) {
|
|
48591
|
+
iconHtml = renderIconSvg(iconData, 16, 2, `${ctx.prefix}-input-icon`);
|
|
48592
|
+
} else {
|
|
48593
|
+
iconHtml = `<span class="${ctx.prefix}-input-icon">[${ctx.escapeHtml(node.icon)}]</span>`;
|
|
48114
48594
|
}
|
|
48115
|
-
const
|
|
48116
|
-
|
|
48117
|
-
|
|
48595
|
+
const wrapperClasses = ctx.buildClassString([`${ctx.prefix}-input-wrapper`]);
|
|
48596
|
+
const wrapper = `<div class="${wrapperClasses}"${styleAttr}>${iconHtml}${inputElement}</div>`;
|
|
48597
|
+
const shouldShowLabel = node.label && !(node.label === "Label" && node.placeholder);
|
|
48598
|
+
if (shouldShowLabel) {
|
|
48599
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48600
|
+
${wrapper}`;
|
|
48118
48601
|
}
|
|
48119
|
-
return
|
|
48602
|
+
return wrapper;
|
|
48120
48603
|
}
|
|
48121
|
-
|
|
48122
|
-
|
|
48604
|
+
const input = `<input${ctx.buildAttrsString(attrs)}${styleAttr} />`;
|
|
48605
|
+
const shouldShowLabel2 = node.label && !(node.label === "Label" && node.placeholder);
|
|
48606
|
+
if (shouldShowLabel2) {
|
|
48607
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48608
|
+
${input}`;
|
|
48123
48609
|
}
|
|
48124
|
-
return
|
|
48610
|
+
return input;
|
|
48611
|
+
}
|
|
48612
|
+
function renderTextarea(node, ctx) {
|
|
48613
|
+
const classes = ctx.buildClassString([
|
|
48614
|
+
`${ctx.prefix}-input`,
|
|
48615
|
+
...ctx.getCommonClasses(node)
|
|
48616
|
+
]);
|
|
48617
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48618
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48619
|
+
const attrs = {
|
|
48620
|
+
class: classes,
|
|
48621
|
+
placeholder: node.placeholder,
|
|
48622
|
+
disabled: node.disabled,
|
|
48623
|
+
required: node.required,
|
|
48624
|
+
rows: node.rows?.toString()
|
|
48625
|
+
};
|
|
48626
|
+
const textarea = `<textarea${ctx.buildAttrsString(attrs)}${styleAttr}>${ctx.escapeHtml(node.value || "")}</textarea>`;
|
|
48627
|
+
if (node.label) {
|
|
48628
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48629
|
+
${textarea}`;
|
|
48630
|
+
}
|
|
48631
|
+
return textarea;
|
|
48632
|
+
}
|
|
48633
|
+
function renderSelect(node, ctx) {
|
|
48634
|
+
const classes = ctx.buildClassString([
|
|
48635
|
+
`${ctx.prefix}-input`,
|
|
48636
|
+
...ctx.getCommonClasses(node)
|
|
48637
|
+
]);
|
|
48638
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48639
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48640
|
+
const attrs = {
|
|
48641
|
+
class: classes,
|
|
48642
|
+
disabled: node.disabled,
|
|
48643
|
+
required: node.required
|
|
48644
|
+
};
|
|
48645
|
+
const options = node.options.map((opt) => {
|
|
48646
|
+
if (typeof opt === "string") {
|
|
48647
|
+
const selected2 = opt === node.value ? " selected" : "";
|
|
48648
|
+
return `<option value="${ctx.escapeHtml(opt)}"${selected2}>${ctx.escapeHtml(opt)}</option>`;
|
|
48649
|
+
}
|
|
48650
|
+
const selected = opt.value === node.value ? " selected" : "";
|
|
48651
|
+
return `<option value="${ctx.escapeHtml(opt.value)}"${selected}>${ctx.escapeHtml(opt.label)}</option>`;
|
|
48652
|
+
}).join("\n");
|
|
48653
|
+
const placeholder = node.placeholder ? `<option value="" disabled selected>${ctx.escapeHtml(node.placeholder)}</option>
|
|
48654
|
+
` : "";
|
|
48655
|
+
const select = `<select${ctx.buildAttrsString(attrs)}${styleAttr}>
|
|
48656
|
+
${placeholder}${options}
|
|
48657
|
+
</select>`;
|
|
48658
|
+
if (node.label) {
|
|
48659
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48660
|
+
${select}`;
|
|
48661
|
+
}
|
|
48662
|
+
return select;
|
|
48663
|
+
}
|
|
48664
|
+
function renderCheckbox(node, ctx) {
|
|
48665
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48666
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48667
|
+
const attrs = {
|
|
48668
|
+
type: "checkbox",
|
|
48669
|
+
checked: node.checked,
|
|
48670
|
+
disabled: node.disabled
|
|
48671
|
+
};
|
|
48672
|
+
const checkbox = `<input${ctx.buildAttrsString(attrs)} />`;
|
|
48673
|
+
if (node.label) {
|
|
48674
|
+
return `<label class="${ctx.prefix}-checkbox"${styleAttr}>${checkbox}<span>${ctx.escapeHtml(node.label)}</span></label>`;
|
|
48675
|
+
}
|
|
48676
|
+
return checkbox;
|
|
48677
|
+
}
|
|
48678
|
+
function renderRadio(node, ctx) {
|
|
48679
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48680
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48681
|
+
const attrs = {
|
|
48682
|
+
type: "radio",
|
|
48683
|
+
name: node.name,
|
|
48684
|
+
checked: node.checked,
|
|
48685
|
+
disabled: node.disabled
|
|
48686
|
+
};
|
|
48687
|
+
const radio = `<input${ctx.buildAttrsString(attrs)} />`;
|
|
48688
|
+
if (node.label) {
|
|
48689
|
+
return `<label class="${ctx.prefix}-radio"${styleAttr}>${radio}<span>${ctx.escapeHtml(node.label)}</span></label>`;
|
|
48690
|
+
}
|
|
48691
|
+
return radio;
|
|
48692
|
+
}
|
|
48693
|
+
function renderSwitch(node, ctx) {
|
|
48694
|
+
const classes = ctx.buildClassString([
|
|
48695
|
+
`${ctx.prefix}-switch`,
|
|
48696
|
+
...ctx.getCommonClasses(node)
|
|
48697
|
+
]);
|
|
48698
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48699
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48700
|
+
const attrs = {
|
|
48701
|
+
type: "checkbox",
|
|
48702
|
+
role: "switch",
|
|
48703
|
+
checked: node.checked,
|
|
48704
|
+
disabled: node.disabled
|
|
48705
|
+
};
|
|
48706
|
+
const switchEl = `<input${ctx.buildAttrsString(attrs)} />`;
|
|
48707
|
+
if (node.label) {
|
|
48708
|
+
return `<label class="${classes}"${styleAttr}>${switchEl} ${ctx.escapeHtml(node.label)}</label>`;
|
|
48709
|
+
}
|
|
48710
|
+
return `<label class="${classes}"${styleAttr}>${switchEl}</label>`;
|
|
48711
|
+
}
|
|
48712
|
+
function renderSlider(node, ctx) {
|
|
48713
|
+
const classes = ctx.buildClassString([
|
|
48714
|
+
`${ctx.prefix}-slider`,
|
|
48715
|
+
...ctx.getCommonClasses(node)
|
|
48716
|
+
]);
|
|
48717
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48718
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48719
|
+
const attrs = {
|
|
48720
|
+
class: classes,
|
|
48721
|
+
type: "range",
|
|
48722
|
+
min: node.min?.toString(),
|
|
48723
|
+
max: node.max?.toString(),
|
|
48724
|
+
step: node.step?.toString(),
|
|
48725
|
+
value: node.value?.toString(),
|
|
48726
|
+
disabled: node.disabled
|
|
48727
|
+
};
|
|
48728
|
+
const slider = `<input${ctx.buildAttrsString(attrs)}${styleAttr} />`;
|
|
48729
|
+
if (node.label) {
|
|
48730
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48731
|
+
${slider}`;
|
|
48732
|
+
}
|
|
48733
|
+
return slider;
|
|
48734
|
+
}
|
|
48735
|
+
|
|
48736
|
+
// src/renderer/html/renderers/display.ts
|
|
48737
|
+
function renderImage(node, ctx) {
|
|
48738
|
+
const classes = ctx.buildClassString([
|
|
48739
|
+
`${ctx.prefix}-image`,
|
|
48740
|
+
...ctx.getCommonClasses(node)
|
|
48741
|
+
]);
|
|
48742
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48743
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48744
|
+
if (node.src) {
|
|
48745
|
+
const attrs = {
|
|
48746
|
+
class: classes,
|
|
48747
|
+
src: node.src,
|
|
48748
|
+
alt: node.alt || "Image"
|
|
48749
|
+
};
|
|
48750
|
+
const imgStyleAttr = styles ? `; ${styles}` : "";
|
|
48751
|
+
return `<img${ctx.buildAttrsString(attrs)}${imgStyleAttr ? ` style="${imgStyleAttr.slice(2)}"` : ""} />`;
|
|
48752
|
+
}
|
|
48753
|
+
const label = node.alt || "Image";
|
|
48754
|
+
const icon = `<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>`;
|
|
48755
|
+
return `<div class="${classes}"${styleAttr} role="img" aria-label="${ctx.escapeHtml(label)}">${icon}<span>${ctx.escapeHtml(label)}</span></div>`;
|
|
48756
|
+
}
|
|
48757
|
+
function renderPlaceholder(node, ctx) {
|
|
48758
|
+
const classes = ctx.buildClassString([
|
|
48759
|
+
`${ctx.prefix}-placeholder`,
|
|
48760
|
+
node.children && node.children.length > 0 ? `${ctx.prefix}-placeholder-with-children` : void 0,
|
|
48761
|
+
...ctx.getCommonClasses(node)
|
|
48762
|
+
]);
|
|
48763
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48764
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48765
|
+
const label = node.label ? ctx.escapeHtml(node.label) : "Placeholder";
|
|
48766
|
+
if (node.children && node.children.length > 0) {
|
|
48767
|
+
const childrenHtml = ctx.renderChildren(node.children);
|
|
48768
|
+
return `<div class="${classes}"${styleAttr}>
|
|
48769
|
+
<span class="${ctx.prefix}-placeholder-label">${label}</span>
|
|
48770
|
+
<div class="${ctx.prefix}-placeholder-overlay">${childrenHtml}</div>
|
|
48771
|
+
</div>`;
|
|
48772
|
+
}
|
|
48773
|
+
return `<div class="${classes}"${styleAttr}>${label}</div>`;
|
|
48774
|
+
}
|
|
48775
|
+
function renderAvatar(node, ctx) {
|
|
48776
|
+
const sizeResolved = resolveSizeValue(node.size, "avatar", ctx.prefix);
|
|
48777
|
+
const classes = ctx.buildClassString([
|
|
48778
|
+
`${ctx.prefix}-avatar`,
|
|
48779
|
+
sizeResolved.className,
|
|
48780
|
+
...ctx.getCommonClasses(node)
|
|
48781
|
+
]);
|
|
48782
|
+
const baseStyles = ctx.buildCommonStyles(node);
|
|
48783
|
+
const sizeStyle = sizeResolved.style || "";
|
|
48784
|
+
const combinedStyles = baseStyles && sizeStyle ? `${baseStyles}; ${sizeStyle}` : baseStyles || sizeStyle;
|
|
48785
|
+
const styleAttr = combinedStyles ? ` style="${combinedStyles}"` : "";
|
|
48786
|
+
const initials = node.name ? node.name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) : "?";
|
|
48787
|
+
return `<div class="${classes}"${styleAttr} role="img" aria-label="${ctx.escapeHtml(node.name || "Avatar")}">${initials}</div>`;
|
|
48788
|
+
}
|
|
48789
|
+
function renderBadge(node, ctx) {
|
|
48790
|
+
if (node.icon) {
|
|
48791
|
+
const iconData = getIconData(node.icon);
|
|
48792
|
+
const classes2 = ctx.buildClassString([
|
|
48793
|
+
`${ctx.prefix}-badge-icon`,
|
|
48794
|
+
node.size ? `${ctx.prefix}-badge-icon-${node.size}` : void 0,
|
|
48795
|
+
node.variant ? `${ctx.prefix}-badge-icon-${node.variant}` : void 0,
|
|
48796
|
+
...ctx.getCommonClasses(node)
|
|
48797
|
+
]);
|
|
48798
|
+
const styles2 = ctx.buildCommonStyles(node);
|
|
48799
|
+
const styleAttr2 = styles2 ? ` style="${styles2}"` : "";
|
|
48800
|
+
if (iconData) {
|
|
48801
|
+
const svg = renderIconSvg(iconData, 24, 2, `${ctx.prefix}-icon`);
|
|
48802
|
+
return `<span class="${classes2}"${styleAttr2} aria-label="${ctx.escapeHtml(node.icon)}">${svg}</span>`;
|
|
48803
|
+
}
|
|
48804
|
+
return `<span class="${classes2}"${styleAttr2} aria-label="unknown icon">?</span>`;
|
|
48805
|
+
}
|
|
48806
|
+
const isDot = !node.content || node.content.trim() === "";
|
|
48807
|
+
const classes = ctx.buildClassString([
|
|
48808
|
+
`${ctx.prefix}-badge`,
|
|
48809
|
+
isDot ? `${ctx.prefix}-badge-dot` : void 0,
|
|
48810
|
+
node.variant ? `${ctx.prefix}-badge-${node.variant}` : void 0,
|
|
48811
|
+
node.pill ? `${ctx.prefix}-badge-pill` : void 0,
|
|
48812
|
+
...ctx.getCommonClasses(node)
|
|
48813
|
+
]);
|
|
48814
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48815
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48816
|
+
return `<span class="${classes}"${styleAttr}>${ctx.escapeHtml(node.content)}</span>`;
|
|
48817
|
+
}
|
|
48818
|
+
function renderIcon(node, ctx) {
|
|
48819
|
+
const iconData = getIconData(node.name);
|
|
48820
|
+
const sizeResolved = resolveSizeValue(node.size, "icon", ctx.prefix);
|
|
48821
|
+
const wrapperClasses = ctx.buildClassString([
|
|
48822
|
+
`${ctx.prefix}-icon-wrapper`,
|
|
48823
|
+
node.muted ? `${ctx.prefix}-text-muted` : void 0,
|
|
48824
|
+
...ctx.getCommonClasses(node)
|
|
48825
|
+
]);
|
|
48826
|
+
const baseStyles = ctx.buildCommonStyles(node);
|
|
48827
|
+
if (iconData) {
|
|
48828
|
+
const iconClasses = buildClassString([
|
|
48829
|
+
`${ctx.prefix}-icon`,
|
|
48830
|
+
sizeResolved.className
|
|
48831
|
+
]);
|
|
48832
|
+
const svgStyleAttr = sizeResolved.style ? ` style="${sizeResolved.style}"` : "";
|
|
48833
|
+
const svg = renderIconSvg(iconData, 24, 2, iconClasses, svgStyleAttr);
|
|
48834
|
+
const wrapperStyleAttr2 = baseStyles ? ` style="${baseStyles}"` : "";
|
|
48835
|
+
return `<span class="${wrapperClasses}"${wrapperStyleAttr2} aria-hidden="true">${svg}</span>`;
|
|
48836
|
+
}
|
|
48837
|
+
const size = sizeResolved.style?.match(/(\d+)px/)?.[1] || "24";
|
|
48838
|
+
const sizeNum = parseInt(size, 10);
|
|
48839
|
+
const placeholderSvg = `<svg class="${ctx.prefix}-icon ${sizeResolved.className || ""}" width="${sizeNum}" height="${sizeNum}" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
48840
|
+
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" stroke-dasharray="4 2" fill="none" opacity="0.5"/>
|
|
48841
|
+
<text x="12" y="16" text-anchor="middle" font-size="10" fill="currentColor" opacity="0.7">?</text>
|
|
48842
|
+
</svg>`;
|
|
48843
|
+
const wrapperStyleAttr = baseStyles ? ` style="${baseStyles}"` : "";
|
|
48844
|
+
return `<span class="${wrapperClasses}"${wrapperStyleAttr} aria-hidden="true" title="Unknown icon: ${ctx.escapeHtml(node.name)}">${placeholderSvg}</span>`;
|
|
48845
|
+
}
|
|
48846
|
+
|
|
48847
|
+
// src/renderer/html/renderers/overlay.ts
|
|
48848
|
+
function renderTooltip(node, ctx) {
|
|
48849
|
+
const classes = ctx.buildClassString([
|
|
48850
|
+
`${ctx.prefix}-tooltip-wrapper`,
|
|
48851
|
+
...ctx.getCommonClasses(node)
|
|
48852
|
+
]);
|
|
48853
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48854
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48855
|
+
const position = node.position || "top";
|
|
48856
|
+
const children = ctx.renderChildren(node.children);
|
|
48857
|
+
return `<div class="${classes}"${styleAttr}>
|
|
48858
|
+
${children}
|
|
48859
|
+
<div class="${ctx.prefix}-tooltip ${ctx.prefix}-tooltip-${position}" role="tooltip">${ctx.escapeHtml(node.content)}</div>
|
|
48860
|
+
</div>`;
|
|
48861
|
+
}
|
|
48862
|
+
function renderPopover(node, ctx) {
|
|
48863
|
+
const classes = ctx.buildClassString([
|
|
48864
|
+
`${ctx.prefix}-popover`,
|
|
48865
|
+
...ctx.getCommonClasses(node)
|
|
48866
|
+
]);
|
|
48867
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48868
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48869
|
+
const title = node.title ? `<div class="${ctx.prefix}-popover-header">${ctx.escapeHtml(node.title)}</div>
|
|
48870
|
+
` : "";
|
|
48871
|
+
const children = ctx.renderChildren(node.children);
|
|
48872
|
+
return `<div class="${classes}"${styleAttr}>
|
|
48873
|
+
${title}<div class="${ctx.prefix}-popover-body">
|
|
48874
|
+
${children}
|
|
48875
|
+
</div>
|
|
48876
|
+
</div>`;
|
|
48877
|
+
}
|
|
48878
|
+
function renderDropdown(node, ctx) {
|
|
48879
|
+
const classes = ctx.buildClassString([
|
|
48880
|
+
`${ctx.prefix}-dropdown`,
|
|
48881
|
+
...ctx.getCommonClasses(node)
|
|
48882
|
+
]);
|
|
48883
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48884
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48885
|
+
const items = node.items.map((item) => {
|
|
48886
|
+
if ("type" in item && item.type === "divider") {
|
|
48887
|
+
return `<hr class="${ctx.prefix}-divider" />`;
|
|
48888
|
+
}
|
|
48889
|
+
const dropdownItem = item;
|
|
48890
|
+
const itemClasses = ctx.buildClassString([
|
|
48891
|
+
`${ctx.prefix}-dropdown-item`,
|
|
48892
|
+
dropdownItem.danger ? `${ctx.prefix}-dropdown-item-danger` : void 0,
|
|
48893
|
+
dropdownItem.disabled ? `${ctx.prefix}-dropdown-item-disabled` : void 0
|
|
48894
|
+
]);
|
|
48895
|
+
return `<button class="${itemClasses}"${dropdownItem.disabled ? " disabled" : ""}>${ctx.escapeHtml(dropdownItem.label)}</button>`;
|
|
48896
|
+
}).join("\n");
|
|
48897
|
+
return `<div class="${classes}"${styleAttr}>
|
|
48898
|
+
${items}
|
|
48899
|
+
</div>`;
|
|
48900
|
+
}
|
|
48901
|
+
|
|
48902
|
+
// src/renderer/html/renderers/navigation.ts
|
|
48903
|
+
function renderIconHtml(iconName, prefix) {
|
|
48904
|
+
return `<span class="${prefix}-icon" data-icon="${iconName}"></span>`;
|
|
48905
|
+
}
|
|
48906
|
+
function renderNavItem(item, ctx) {
|
|
48907
|
+
const linkClasses = ctx.buildClassString([
|
|
48908
|
+
`${ctx.prefix}-nav-link`,
|
|
48909
|
+
item.active ? `${ctx.prefix}-nav-link-active` : void 0,
|
|
48910
|
+
item.disabled ? `${ctx.prefix}-nav-link-disabled` : void 0
|
|
48911
|
+
]);
|
|
48912
|
+
const iconHtml = item.icon ? renderIconHtml(item.icon, ctx.prefix) + " " : "";
|
|
48913
|
+
return `<a class="${linkClasses}" href="${item.href || "#"}">${iconHtml}${ctx.escapeHtml(item.label)}</a>`;
|
|
48914
|
+
}
|
|
48915
|
+
function renderNavChildren(children, ctx) {
|
|
48916
|
+
return children.map((child) => {
|
|
48917
|
+
if (child.type === "divider") {
|
|
48918
|
+
return `<hr class="${ctx.prefix}-nav-divider" />`;
|
|
48919
|
+
}
|
|
48920
|
+
if (child.type === "group") {
|
|
48921
|
+
const groupItems = child.items.map((item) => {
|
|
48922
|
+
if (item.type === "divider") {
|
|
48923
|
+
return `<hr class="${ctx.prefix}-nav-divider" />`;
|
|
48924
|
+
}
|
|
48925
|
+
return renderNavItem(item, ctx);
|
|
48926
|
+
}).join("\n");
|
|
48927
|
+
return `<div class="${ctx.prefix}-nav-group">
|
|
48928
|
+
<div class="${ctx.prefix}-nav-group-label">${ctx.escapeHtml(child.label)}</div>
|
|
48929
|
+
${groupItems}
|
|
48930
|
+
</div>`;
|
|
48931
|
+
}
|
|
48932
|
+
if (child.type === "item") {
|
|
48933
|
+
return renderNavItem(child, ctx);
|
|
48934
|
+
}
|
|
48935
|
+
return "";
|
|
48936
|
+
}).join("\n");
|
|
48937
|
+
}
|
|
48938
|
+
function renderNav(node, ctx) {
|
|
48939
|
+
const classes = ctx.buildClassString([
|
|
48940
|
+
`${ctx.prefix}-nav`,
|
|
48941
|
+
node.vertical ? `${ctx.prefix}-nav-vertical` : void 0,
|
|
48942
|
+
...ctx.getCommonClasses(node)
|
|
48943
|
+
]);
|
|
48944
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48945
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48946
|
+
if (node.children && node.children.length > 0) {
|
|
48947
|
+
const content = renderNavChildren(node.children, ctx);
|
|
48948
|
+
return `<nav class="${classes}"${styleAttr}>
|
|
48949
|
+
${content}
|
|
48950
|
+
</nav>`;
|
|
48951
|
+
}
|
|
48952
|
+
const items = node.items.map((item) => {
|
|
48953
|
+
if (typeof item === "string") {
|
|
48954
|
+
return `<a class="${ctx.prefix}-nav-link" href="#">${ctx.escapeHtml(item)}</a>`;
|
|
48955
|
+
}
|
|
48956
|
+
const linkClasses = ctx.buildClassString([
|
|
48957
|
+
`${ctx.prefix}-nav-link`,
|
|
48958
|
+
item.active ? `${ctx.prefix}-nav-link-active` : void 0,
|
|
48959
|
+
item.disabled ? `${ctx.prefix}-nav-link-disabled` : void 0
|
|
48960
|
+
]);
|
|
48961
|
+
const iconHtml = item.icon ? renderIconHtml(item.icon, ctx.prefix) + " " : "";
|
|
48962
|
+
return `<a class="${linkClasses}" href="${item.href || "#"}">${iconHtml}${ctx.escapeHtml(item.label)}</a>`;
|
|
48963
|
+
}).join("\n");
|
|
48964
|
+
return `<nav class="${classes}"${styleAttr}>
|
|
48965
|
+
${items}
|
|
48966
|
+
</nav>`;
|
|
48967
|
+
}
|
|
48968
|
+
function renderTabs(node, ctx) {
|
|
48969
|
+
const classes = ctx.buildClassString([
|
|
48970
|
+
`${ctx.prefix}-tabs`,
|
|
48971
|
+
...ctx.getCommonClasses(node)
|
|
48972
|
+
]);
|
|
48973
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48974
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48975
|
+
const tabList = node.items.map((label, idx) => {
|
|
48976
|
+
const isActive = idx === (node.active || 0);
|
|
48977
|
+
const tabClasses = `${ctx.prefix}-tab${isActive ? ` ${ctx.prefix}-tab-active` : ""}`;
|
|
48978
|
+
return `<button class="${tabClasses}" role="tab" aria-selected="${isActive}">${ctx.escapeHtml(label)}</button>`;
|
|
48979
|
+
}).join("\n");
|
|
48980
|
+
return `<div class="${classes}"${styleAttr}>
|
|
48981
|
+
<div class="${ctx.prefix}-tab-list" role="tablist">
|
|
48982
|
+
${tabList}
|
|
48983
|
+
</div>
|
|
48984
|
+
</div>`;
|
|
48985
|
+
}
|
|
48986
|
+
function renderBreadcrumb(node, ctx) {
|
|
48987
|
+
const classes = ctx.buildClassString([
|
|
48988
|
+
`${ctx.prefix}-breadcrumb`,
|
|
48989
|
+
...ctx.getCommonClasses(node)
|
|
48990
|
+
]);
|
|
48991
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48992
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48993
|
+
const items = node.items.map((item, idx) => {
|
|
48994
|
+
const isLast = idx === node.items.length - 1;
|
|
48995
|
+
if (typeof item === "string") {
|
|
48996
|
+
return isLast ? `<span class="${ctx.prefix}-breadcrumb-item" aria-current="page">${ctx.escapeHtml(item)}</span>` : `<a class="${ctx.prefix}-breadcrumb-item" href="#">${ctx.escapeHtml(item)}</a>`;
|
|
48997
|
+
}
|
|
48998
|
+
return isLast ? `<span class="${ctx.prefix}-breadcrumb-item" aria-current="page">${ctx.escapeHtml(item.label)}</span>` : `<a class="${ctx.prefix}-breadcrumb-item" href="${item.href || "#"}">${ctx.escapeHtml(item.label)}</a>`;
|
|
48999
|
+
}).join(" / ");
|
|
49000
|
+
return `<nav class="${classes}"${styleAttr} aria-label="Breadcrumb">${items}</nav>`;
|
|
49001
|
+
}
|
|
49002
|
+
|
|
49003
|
+
// src/renderer/html/semantic.ts
|
|
49004
|
+
function renderSemanticMarker(component, variant, prefix) {
|
|
49005
|
+
switch (component) {
|
|
49006
|
+
case "avatar":
|
|
49007
|
+
const avatarSize = variant || "sm";
|
|
49008
|
+
return `<span class="${prefix}-semantic-avatar ${prefix}-semantic-avatar-${avatarSize}" data-semantic="avatar" data-variant="${avatarSize}" aria-hidden="true"></span>`;
|
|
49009
|
+
case "dot":
|
|
49010
|
+
const dotVariant = variant || "default";
|
|
49011
|
+
return `<span class="${prefix}-semantic-dot ${prefix}-semantic-dot-${dotVariant}" data-semantic="dot" data-variant="${dotVariant}" aria-hidden="true"></span>`;
|
|
49012
|
+
case "icon":
|
|
49013
|
+
const iconName = variant || "default";
|
|
49014
|
+
return `<span class="${prefix}-semantic-icon" data-semantic="icon" data-variant="${iconName}" aria-hidden="true">[${iconName}]</span>`;
|
|
49015
|
+
default:
|
|
49016
|
+
return `<span class="${prefix}-semantic-unknown" data-semantic="${component}" data-variant="${variant || ""}">[${component}${variant ? ":" + variant : ""}]</span>`;
|
|
49017
|
+
}
|
|
49018
|
+
}
|
|
49019
|
+
function renderSemanticMarkerWithContent(component, variant, content, prefix, escapeHtml) {
|
|
49020
|
+
switch (component) {
|
|
49021
|
+
case "badge":
|
|
49022
|
+
const badgeVariant = variant || "default";
|
|
49023
|
+
const escapedContent = escapeHtml(content);
|
|
49024
|
+
return `<span class="${prefix}-semantic-badge ${prefix}-semantic-badge-${badgeVariant}" data-semantic="badge" data-variant="${badgeVariant}">${escapedContent}</span>`;
|
|
49025
|
+
default:
|
|
49026
|
+
return renderSemanticMarker(component, variant, prefix) + escapeHtml(content);
|
|
49027
|
+
}
|
|
49028
|
+
}
|
|
49029
|
+
function renderSemanticMarkers(text, prefix, escapeHtml) {
|
|
49030
|
+
const markerPattern = /\[([a-z]+)(?::([a-z0-9-]+))?\](\s*)/gi;
|
|
49031
|
+
let result = "";
|
|
49032
|
+
let lastIndex = 0;
|
|
49033
|
+
let match;
|
|
49034
|
+
while ((match = markerPattern.exec(text)) !== null) {
|
|
49035
|
+
if (match.index > lastIndex) {
|
|
49036
|
+
result += escapeHtml(text.substring(lastIndex, match.index));
|
|
49037
|
+
}
|
|
49038
|
+
const [fullMatch, component, variant] = match;
|
|
49039
|
+
const comp = component.toLowerCase();
|
|
49040
|
+
const varnt = variant?.toLowerCase();
|
|
49041
|
+
if (comp === "badge") {
|
|
49042
|
+
const afterMarker = text.substring(match.index + fullMatch.length);
|
|
49043
|
+
const contentMatch = afterMarker.match(/^([^\n\[]+?)(?=\n|\[|$)/);
|
|
49044
|
+
const badgeContent = contentMatch ? contentMatch[1].trim() : "";
|
|
49045
|
+
result += renderSemanticMarkerWithContent(comp, varnt, badgeContent, prefix, escapeHtml);
|
|
49046
|
+
lastIndex = match.index + fullMatch.length + (contentMatch ? contentMatch[0].length : 0);
|
|
49047
|
+
markerPattern.lastIndex = lastIndex;
|
|
49048
|
+
} else {
|
|
49049
|
+
result += renderSemanticMarker(comp, varnt, prefix);
|
|
49050
|
+
lastIndex = match.index + fullMatch.length;
|
|
49051
|
+
}
|
|
49052
|
+
}
|
|
49053
|
+
if (lastIndex < text.length) {
|
|
49054
|
+
result += escapeHtml(text.substring(lastIndex));
|
|
49055
|
+
}
|
|
49056
|
+
if (lastIndex === 0) {
|
|
49057
|
+
return escapeHtml(text);
|
|
49058
|
+
}
|
|
49059
|
+
return result;
|
|
49060
|
+
}
|
|
49061
|
+
function renderTableCellContent(content, prefix, escapeHtml) {
|
|
49062
|
+
const avatarMatch = content.match(/^\[avatar(?::([a-z0-9-]+))?\]\s*/i);
|
|
49063
|
+
if (avatarMatch) {
|
|
49064
|
+
const avatarVariant = avatarMatch[1]?.toLowerCase();
|
|
49065
|
+
const avatarHtml = renderSemanticMarker("avatar", avatarVariant, prefix);
|
|
49066
|
+
const restContent = content.slice(avatarMatch[0].length);
|
|
49067
|
+
const restHtml = renderSemanticMarkers(restContent, prefix, escapeHtml);
|
|
49068
|
+
const lines = restHtml.split("\n");
|
|
49069
|
+
const textHtml = lines.length > 1 ? lines.map((line) => `<span>${line}</span>`).join("") : restHtml;
|
|
49070
|
+
return `<div class="${prefix}-cell-avatar-layout">${avatarHtml}<div class="${prefix}-cell-avatar-text">${textHtml}</div></div>`;
|
|
49071
|
+
}
|
|
49072
|
+
const withMarkers = renderSemanticMarkers(content, prefix, escapeHtml);
|
|
49073
|
+
return withMarkers.replace(/\n/g, "<br>");
|
|
49074
|
+
}
|
|
49075
|
+
|
|
49076
|
+
// src/renderer/html/renderers/data.ts
|
|
49077
|
+
function renderTable(node, ctx) {
|
|
49078
|
+
const classes = ctx.buildClassString([
|
|
49079
|
+
`${ctx.prefix}-table`,
|
|
49080
|
+
node.striped ? `${ctx.prefix}-table-striped` : void 0,
|
|
49081
|
+
node.bordered ? `${ctx.prefix}-table-bordered` : void 0,
|
|
49082
|
+
node.hover ? `${ctx.prefix}-table-hover` : void 0,
|
|
49083
|
+
...ctx.getCommonClasses(node)
|
|
49084
|
+
]);
|
|
49085
|
+
const styles = ctx.buildCommonStyles(node);
|
|
49086
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49087
|
+
const thead = `<thead><tr>${node.columns.map((col) => `<th>${ctx.escapeHtml(col)}</th>`).join("")}</tr></thead>`;
|
|
49088
|
+
const tbody = `<tbody>${node.rows.map(
|
|
49089
|
+
(row) => `<tr>${row.map((cell) => {
|
|
49090
|
+
if (typeof cell === "string") {
|
|
49091
|
+
return `<td>${renderTableCellContent(cell, ctx.prefix, ctx.escapeHtml)}</td>`;
|
|
49092
|
+
}
|
|
49093
|
+
return `<td>${ctx.renderNode(cell)}</td>`;
|
|
49094
|
+
}).join("")}</tr>`
|
|
49095
|
+
).join("")}</tbody>`;
|
|
49096
|
+
return `<table class="${classes}"${styleAttr}>
|
|
49097
|
+
${thead}
|
|
49098
|
+
${tbody}
|
|
49099
|
+
</table>`;
|
|
49100
|
+
}
|
|
49101
|
+
function renderList(node, ctx) {
|
|
49102
|
+
const tag = node.ordered ? "ol" : "ul";
|
|
49103
|
+
const classes = ctx.buildClassString([
|
|
49104
|
+
`${ctx.prefix}-list`,
|
|
49105
|
+
node.ordered ? `${ctx.prefix}-list-ordered` : void 0,
|
|
49106
|
+
node.none ? `${ctx.prefix}-list-none` : void 0,
|
|
49107
|
+
...ctx.getCommonClasses(node)
|
|
49108
|
+
]);
|
|
49109
|
+
const styles = ctx.buildCommonStyles(node);
|
|
49110
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49111
|
+
const items = node.items.map((item) => {
|
|
49112
|
+
if (typeof item === "string") {
|
|
49113
|
+
return `<li class="${ctx.prefix}-list-item">${ctx.escapeHtml(item)}</li>`;
|
|
49114
|
+
}
|
|
49115
|
+
return `<li class="${ctx.prefix}-list-item">${ctx.escapeHtml(item.content)}</li>`;
|
|
49116
|
+
}).join("\n");
|
|
49117
|
+
return `<${tag} class="${classes}"${styleAttr}>
|
|
49118
|
+
${items}
|
|
49119
|
+
</${tag}>`;
|
|
49120
|
+
}
|
|
49121
|
+
|
|
49122
|
+
// src/renderer/html/renderers/divider.ts
|
|
49123
|
+
function renderDivider(node, ctx) {
|
|
49124
|
+
const styles = ctx.buildCommonStyles(node);
|
|
49125
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49126
|
+
return `<hr class="${ctx.prefix}-divider"${styleAttr} />`;
|
|
48125
49127
|
}
|
|
48126
49128
|
|
|
48127
49129
|
// src/renderer/html/index.ts
|
|
@@ -48163,8 +49165,97 @@ function resolveSizeValueToCss(value) {
|
|
|
48163
49165
|
return void 0;
|
|
48164
49166
|
}
|
|
48165
49167
|
var HtmlRenderer = class extends BaseRenderer {
|
|
49168
|
+
/**
|
|
49169
|
+
* Node type to renderer method mapping
|
|
49170
|
+
*/
|
|
49171
|
+
nodeRenderers;
|
|
48166
49172
|
constructor(options = {}) {
|
|
48167
49173
|
super(options);
|
|
49174
|
+
this.nodeRenderers = this.createNodeRenderers();
|
|
49175
|
+
}
|
|
49176
|
+
/**
|
|
49177
|
+
* Get render context for external renderer functions
|
|
49178
|
+
*/
|
|
49179
|
+
getRenderContext() {
|
|
49180
|
+
return {
|
|
49181
|
+
prefix: this.prefix,
|
|
49182
|
+
escapeHtml: this.escapeHtml.bind(this),
|
|
49183
|
+
buildClassString: this.buildClassString.bind(this),
|
|
49184
|
+
buildAttrsString: this.buildAttrsString.bind(this),
|
|
49185
|
+
buildCommonStyles: this.buildCommonStyles.bind(this),
|
|
49186
|
+
getCommonClasses: this.getCommonClasses.bind(this),
|
|
49187
|
+
renderChildren: this.renderChildren.bind(this),
|
|
49188
|
+
renderNode: this.renderNode.bind(this)
|
|
49189
|
+
};
|
|
49190
|
+
}
|
|
49191
|
+
/**
|
|
49192
|
+
* Get grid render context (extends RenderContext with buildColStyles)
|
|
49193
|
+
*/
|
|
49194
|
+
getGridRenderContext() {
|
|
49195
|
+
return {
|
|
49196
|
+
...this.getRenderContext(),
|
|
49197
|
+
buildColStyles: this.buildColStyles.bind(this)
|
|
49198
|
+
};
|
|
49199
|
+
}
|
|
49200
|
+
/**
|
|
49201
|
+
* Create the node renderer mapping
|
|
49202
|
+
*/
|
|
49203
|
+
createNodeRenderers() {
|
|
49204
|
+
return {
|
|
49205
|
+
// Layout nodes
|
|
49206
|
+
Page: (node) => this.renderPage(node),
|
|
49207
|
+
Header: (node) => this.renderHeader(node),
|
|
49208
|
+
Main: (node) => this.renderMain(node),
|
|
49209
|
+
Footer: (node) => this.renderFooter(node),
|
|
49210
|
+
Sidebar: (node) => this.renderSidebar(node),
|
|
49211
|
+
Section: (node) => this.renderSection(node),
|
|
49212
|
+
// Grid nodes
|
|
49213
|
+
Row: (node) => this.renderRow(node),
|
|
49214
|
+
Col: (node) => this.renderCol(node),
|
|
49215
|
+
// Container nodes
|
|
49216
|
+
Card: (node) => this.renderCard(node),
|
|
49217
|
+
Modal: (node) => this.renderModal(node),
|
|
49218
|
+
Drawer: (node) => this.renderDrawer(node),
|
|
49219
|
+
Accordion: (node) => this.renderAccordion(node),
|
|
49220
|
+
// Text nodes
|
|
49221
|
+
Text: (node) => this.renderText(node),
|
|
49222
|
+
Title: (node) => this.renderTitle(node),
|
|
49223
|
+
Link: (node) => this.renderLink(node),
|
|
49224
|
+
// Input nodes
|
|
49225
|
+
Input: (node) => this.renderInput(node),
|
|
49226
|
+
Textarea: (node) => this.renderTextarea(node),
|
|
49227
|
+
Select: (node) => this.renderSelect(node),
|
|
49228
|
+
Checkbox: (node) => this.renderCheckbox(node),
|
|
49229
|
+
Radio: (node) => this.renderRadio(node),
|
|
49230
|
+
Switch: (node) => this.renderSwitch(node),
|
|
49231
|
+
Slider: (node) => this.renderSlider(node),
|
|
49232
|
+
// Button
|
|
49233
|
+
Button: (node) => this.renderButton(node),
|
|
49234
|
+
// Display nodes
|
|
49235
|
+
Image: (node) => this.renderImage(node),
|
|
49236
|
+
Placeholder: (node) => this.renderPlaceholder(node),
|
|
49237
|
+
Avatar: (node) => this.renderAvatar(node),
|
|
49238
|
+
Badge: (node) => this.renderBadge(node),
|
|
49239
|
+
Icon: (node) => this.renderIcon(node),
|
|
49240
|
+
// Data nodes
|
|
49241
|
+
Table: (node) => this.renderTable(node),
|
|
49242
|
+
List: (node) => this.renderList(node),
|
|
49243
|
+
// Feedback nodes
|
|
49244
|
+
Alert: (node) => this.renderAlert(node),
|
|
49245
|
+
Toast: (node) => this.renderToast(node),
|
|
49246
|
+
Progress: (node) => this.renderProgress(node),
|
|
49247
|
+
Spinner: (node) => this.renderSpinner(node),
|
|
49248
|
+
// Overlay nodes
|
|
49249
|
+
Tooltip: (node) => this.renderTooltip(node),
|
|
49250
|
+
Popover: (node) => this.renderPopover(node),
|
|
49251
|
+
Dropdown: (node) => this.renderDropdown(node),
|
|
49252
|
+
// Navigation nodes
|
|
49253
|
+
Nav: (node) => this.renderNav(node),
|
|
49254
|
+
Tabs: (node) => this.renderTabs(node),
|
|
49255
|
+
Breadcrumb: (node) => this.renderBreadcrumb(node),
|
|
49256
|
+
// Other
|
|
49257
|
+
Divider: (node) => this.renderDivider(node)
|
|
49258
|
+
};
|
|
48168
49259
|
}
|
|
48169
49260
|
/**
|
|
48170
49261
|
* Render a page node
|
|
@@ -48193,7 +49284,7 @@ var HtmlRenderer = class extends BaseRenderer {
|
|
|
48193
49284
|
const title = node.title ? `<title>${this.escapeHtml(node.title)}</title>
|
|
48194
49285
|
` : "";
|
|
48195
49286
|
const commonStyles = this.buildCommonStyles(node);
|
|
48196
|
-
const viewportStyle = `width: ${viewport.width}px; height: ${viewport.height}px`;
|
|
49287
|
+
const viewportStyle = `position: relative; width: ${viewport.width}px; height: ${viewport.height}px; overflow: hidden`;
|
|
48197
49288
|
const combinedStyle = commonStyles ? `${viewportStyle}; ${commonStyles}` : viewportStyle;
|
|
48198
49289
|
const dataAttrs = `data-viewport-width="${viewport.width}" data-viewport-height="${viewport.height}" data-viewport-label="${viewport.label}"`;
|
|
48199
49290
|
return `<div class="${classes}" style="${combinedStyle}" ${dataAttrs}>
|
|
@@ -48204,104 +49295,11 @@ ${title}${children}
|
|
|
48204
49295
|
* Render any AST node
|
|
48205
49296
|
*/
|
|
48206
49297
|
renderNode(node) {
|
|
48207
|
-
|
|
48208
|
-
|
|
48209
|
-
|
|
48210
|
-
return this.renderPage(node);
|
|
48211
|
-
case "Header":
|
|
48212
|
-
return this.renderHeader(node);
|
|
48213
|
-
case "Main":
|
|
48214
|
-
return this.renderMain(node);
|
|
48215
|
-
case "Footer":
|
|
48216
|
-
return this.renderFooter(node);
|
|
48217
|
-
case "Sidebar":
|
|
48218
|
-
return this.renderSidebar(node);
|
|
48219
|
-
case "Section":
|
|
48220
|
-
return this.renderSection(node);
|
|
48221
|
-
// Grid nodes
|
|
48222
|
-
case "Row":
|
|
48223
|
-
return this.renderRow(node);
|
|
48224
|
-
case "Col":
|
|
48225
|
-
return this.renderCol(node);
|
|
48226
|
-
// Container nodes
|
|
48227
|
-
case "Card":
|
|
48228
|
-
return this.renderCard(node);
|
|
48229
|
-
case "Modal":
|
|
48230
|
-
return this.renderModal(node);
|
|
48231
|
-
case "Drawer":
|
|
48232
|
-
return this.renderDrawer(node);
|
|
48233
|
-
case "Accordion":
|
|
48234
|
-
return this.renderAccordion(node);
|
|
48235
|
-
// Text nodes
|
|
48236
|
-
case "Text":
|
|
48237
|
-
return this.renderText(node);
|
|
48238
|
-
case "Title":
|
|
48239
|
-
return this.renderTitle(node);
|
|
48240
|
-
case "Link":
|
|
48241
|
-
return this.renderLink(node);
|
|
48242
|
-
// Input nodes
|
|
48243
|
-
case "Input":
|
|
48244
|
-
return this.renderInput(node);
|
|
48245
|
-
case "Textarea":
|
|
48246
|
-
return this.renderTextarea(node);
|
|
48247
|
-
case "Select":
|
|
48248
|
-
return this.renderSelect(node);
|
|
48249
|
-
case "Checkbox":
|
|
48250
|
-
return this.renderCheckbox(node);
|
|
48251
|
-
case "Radio":
|
|
48252
|
-
return this.renderRadio(node);
|
|
48253
|
-
case "Switch":
|
|
48254
|
-
return this.renderSwitch(node);
|
|
48255
|
-
case "Slider":
|
|
48256
|
-
return this.renderSlider(node);
|
|
48257
|
-
// Button
|
|
48258
|
-
case "Button":
|
|
48259
|
-
return this.renderButton(node);
|
|
48260
|
-
// Display nodes
|
|
48261
|
-
case "Image":
|
|
48262
|
-
return this.renderImage(node);
|
|
48263
|
-
case "Placeholder":
|
|
48264
|
-
return this.renderPlaceholder(node);
|
|
48265
|
-
case "Avatar":
|
|
48266
|
-
return this.renderAvatar(node);
|
|
48267
|
-
case "Badge":
|
|
48268
|
-
return this.renderBadge(node);
|
|
48269
|
-
case "Icon":
|
|
48270
|
-
return this.renderIcon(node);
|
|
48271
|
-
// Data nodes
|
|
48272
|
-
case "Table":
|
|
48273
|
-
return this.renderTable(node);
|
|
48274
|
-
case "List":
|
|
48275
|
-
return this.renderList(node);
|
|
48276
|
-
// Feedback nodes
|
|
48277
|
-
case "Alert":
|
|
48278
|
-
return this.renderAlert(node);
|
|
48279
|
-
case "Toast":
|
|
48280
|
-
return this.renderToast(node);
|
|
48281
|
-
case "Progress":
|
|
48282
|
-
return this.renderProgress(node);
|
|
48283
|
-
case "Spinner":
|
|
48284
|
-
return this.renderSpinner(node);
|
|
48285
|
-
// Overlay nodes
|
|
48286
|
-
case "Tooltip":
|
|
48287
|
-
return this.renderTooltip(node);
|
|
48288
|
-
case "Popover":
|
|
48289
|
-
return this.renderPopover(node);
|
|
48290
|
-
case "Dropdown":
|
|
48291
|
-
return this.renderDropdown(node);
|
|
48292
|
-
// Navigation nodes
|
|
48293
|
-
case "Nav":
|
|
48294
|
-
return this.renderNav(node);
|
|
48295
|
-
case "Tabs":
|
|
48296
|
-
return this.renderTabs(node);
|
|
48297
|
-
case "Breadcrumb":
|
|
48298
|
-
return this.renderBreadcrumb(node);
|
|
48299
|
-
// Other
|
|
48300
|
-
case "Divider":
|
|
48301
|
-
return this.renderDivider(node);
|
|
48302
|
-
default:
|
|
48303
|
-
return `<!-- Unknown node type: ${node.type} -->`;
|
|
49298
|
+
const renderer = this.nodeRenderers[node.type];
|
|
49299
|
+
if (renderer) {
|
|
49300
|
+
return renderer(node);
|
|
48304
49301
|
}
|
|
49302
|
+
return `<!-- Unknown node type: ${node.type} -->`;
|
|
48305
49303
|
}
|
|
48306
49304
|
/**
|
|
48307
49305
|
* Render children nodes
|
|
@@ -48344,106 +49342,36 @@ ${title}${children}
|
|
|
48344
49342
|
// Layout Node Renderers
|
|
48345
49343
|
// ===========================================
|
|
48346
49344
|
renderHeader(node) {
|
|
48347
|
-
|
|
48348
|
-
`${this.prefix}-header`,
|
|
48349
|
-
node.border === false ? `${this.prefix}-no-border` : void 0,
|
|
48350
|
-
...this.getCommonClasses(node)
|
|
48351
|
-
]);
|
|
48352
|
-
const styles = this.buildCommonStyles(node);
|
|
48353
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48354
|
-
const children = this.renderChildren(node.children);
|
|
48355
|
-
return `<header class="${classes}"${styleAttr}>
|
|
48356
|
-
${children}
|
|
48357
|
-
</header>`;
|
|
49345
|
+
return renderHeader(node, this.getRenderContext());
|
|
48358
49346
|
}
|
|
48359
49347
|
renderMain(node) {
|
|
48360
|
-
|
|
48361
|
-
`${this.prefix}-main`,
|
|
48362
|
-
...this.getCommonClasses(node)
|
|
48363
|
-
]);
|
|
48364
|
-
const styles = this.buildCommonStyles(node);
|
|
48365
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48366
|
-
const children = this.renderChildren(node.children);
|
|
48367
|
-
return `<main class="${classes}"${styleAttr}>
|
|
48368
|
-
${children}
|
|
48369
|
-
</main>`;
|
|
49348
|
+
return renderMain(node, this.getRenderContext());
|
|
48370
49349
|
}
|
|
48371
49350
|
renderFooter(node) {
|
|
48372
|
-
|
|
48373
|
-
`${this.prefix}-footer`,
|
|
48374
|
-
node.border === false ? `${this.prefix}-no-border` : void 0,
|
|
48375
|
-
...this.getCommonClasses(node)
|
|
48376
|
-
]);
|
|
48377
|
-
const styles = this.buildCommonStyles(node);
|
|
48378
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48379
|
-
const children = this.renderChildren(node.children);
|
|
48380
|
-
return `<footer class="${classes}"${styleAttr}>
|
|
48381
|
-
${children}
|
|
48382
|
-
</footer>`;
|
|
49351
|
+
return renderFooter(node, this.getRenderContext());
|
|
48383
49352
|
}
|
|
48384
49353
|
renderSidebar(node) {
|
|
48385
|
-
|
|
48386
|
-
`${this.prefix}-sidebar`,
|
|
48387
|
-
node.position === "right" ? `${this.prefix}-sidebar-right` : void 0,
|
|
48388
|
-
...this.getCommonClasses(node)
|
|
48389
|
-
]);
|
|
48390
|
-
const styles = this.buildCommonStyles(node);
|
|
48391
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48392
|
-
const children = this.renderChildren(node.children);
|
|
48393
|
-
return `<aside class="${classes}"${styleAttr}>
|
|
48394
|
-
${children}
|
|
48395
|
-
</aside>`;
|
|
49354
|
+
return renderSidebar(node, this.getRenderContext());
|
|
48396
49355
|
}
|
|
48397
49356
|
renderSection(node) {
|
|
48398
|
-
|
|
48399
|
-
`${this.prefix}-section`,
|
|
48400
|
-
...this.getCommonClasses(node)
|
|
48401
|
-
]);
|
|
48402
|
-
const styles = this.buildCommonStyles(node);
|
|
48403
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48404
|
-
const title = node.title ? `<h2 class="${this.prefix}-title">${this.escapeHtml(node.title)}</h2>
|
|
48405
|
-
` : "";
|
|
48406
|
-
const children = this.renderChildren(node.children);
|
|
48407
|
-
return `<section class="${classes}"${styleAttr}>
|
|
48408
|
-
${title}${children}
|
|
48409
|
-
</section>`;
|
|
49357
|
+
return renderSection(node, this.getRenderContext());
|
|
48410
49358
|
}
|
|
48411
49359
|
// ===========================================
|
|
48412
49360
|
// Grid Node Renderers
|
|
48413
49361
|
// ===========================================
|
|
48414
49362
|
renderRow(node) {
|
|
48415
|
-
|
|
48416
|
-
`${this.prefix}-row`,
|
|
48417
|
-
...this.getCommonClasses(node)
|
|
48418
|
-
]);
|
|
48419
|
-
const styles = this.buildCommonStyles(node);
|
|
48420
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48421
|
-
const children = this.renderChildren(node.children);
|
|
48422
|
-
return `<div class="${classes}"${styleAttr}>
|
|
48423
|
-
${children}
|
|
48424
|
-
</div>`;
|
|
49363
|
+
return renderRow(node, this.getRenderContext());
|
|
48425
49364
|
}
|
|
48426
49365
|
renderCol(node) {
|
|
48427
|
-
|
|
48428
|
-
`${this.prefix}-col`,
|
|
48429
|
-
node.span ? `${this.prefix}-col-${node.span}` : void 0,
|
|
48430
|
-
// Responsive breakpoint classes
|
|
48431
|
-
node.sm ? `${this.prefix}-col-sm-${node.sm}` : void 0,
|
|
48432
|
-
node.md ? `${this.prefix}-col-md-${node.md}` : void 0,
|
|
48433
|
-
node.lg ? `${this.prefix}-col-lg-${node.lg}` : void 0,
|
|
48434
|
-
node.xl ? `${this.prefix}-col-xl-${node.xl}` : void 0,
|
|
48435
|
-
...this.getCommonClasses(node)
|
|
48436
|
-
]);
|
|
48437
|
-
const styles = this.buildColStyles(node);
|
|
48438
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48439
|
-
const children = this.renderChildren(node.children);
|
|
48440
|
-
return `<div class="${classes}"${styleAttr}>
|
|
48441
|
-
${children}
|
|
48442
|
-
</div>`;
|
|
49366
|
+
return renderCol(node, this.getGridRenderContext());
|
|
48443
49367
|
}
|
|
48444
49368
|
/**
|
|
48445
49369
|
* Build common inline styles for all values
|
|
48446
49370
|
*
|
|
49371
|
+
* Position values (x, y) for absolute positioning:
|
|
49372
|
+
* - When x or y is specified, element gets position: absolute
|
|
49373
|
+
* - x → left, y → top
|
|
49374
|
+
*
|
|
48447
49375
|
* Spacing values (p, m, gap) use token system:
|
|
48448
49376
|
* - number: spacing token (e.g., p=4 → padding: 16px from token table)
|
|
48449
49377
|
* - ValueWithUnit: direct CSS value (e.g., p=16px → padding: 16px)
|
|
@@ -48458,6 +49386,33 @@ ${children}
|
|
|
48458
49386
|
*/
|
|
48459
49387
|
buildCommonStyles(props) {
|
|
48460
49388
|
const styles = [];
|
|
49389
|
+
this.buildPositionStyles(props, styles);
|
|
49390
|
+
this.buildSizeStyles(props, styles);
|
|
49391
|
+
this.buildPaddingStyles(props, styles);
|
|
49392
|
+
this.buildMarginStyles(props, styles);
|
|
49393
|
+
this.buildGapStyles(props, styles);
|
|
49394
|
+
return styles.join("; ");
|
|
49395
|
+
}
|
|
49396
|
+
/**
|
|
49397
|
+
* Build position styles (absolute positioning)
|
|
49398
|
+
*/
|
|
49399
|
+
buildPositionStyles(props, styles) {
|
|
49400
|
+
if (props.x !== void 0 || props.y !== void 0) {
|
|
49401
|
+
styles.push("position: absolute");
|
|
49402
|
+
if (props.x !== void 0) {
|
|
49403
|
+
const xValue = resolveSizeValueToCss(props.x);
|
|
49404
|
+
if (xValue) styles.push(`left: ${xValue}`);
|
|
49405
|
+
}
|
|
49406
|
+
if (props.y !== void 0) {
|
|
49407
|
+
const yValue = resolveSizeValueToCss(props.y);
|
|
49408
|
+
if (yValue) styles.push(`top: ${yValue}`);
|
|
49409
|
+
}
|
|
49410
|
+
}
|
|
49411
|
+
}
|
|
49412
|
+
/**
|
|
49413
|
+
* Build size styles (width, height, min/max)
|
|
49414
|
+
*/
|
|
49415
|
+
buildSizeStyles(props, styles) {
|
|
48461
49416
|
const wValue = resolveSizeValueToCss(props.w);
|
|
48462
49417
|
if (wValue) {
|
|
48463
49418
|
styles.push(`width: ${wValue}`);
|
|
@@ -48483,6 +49438,11 @@ ${children}
|
|
|
48483
49438
|
if (maxHValue) {
|
|
48484
49439
|
styles.push(`max-height: ${maxHValue}`);
|
|
48485
49440
|
}
|
|
49441
|
+
}
|
|
49442
|
+
/**
|
|
49443
|
+
* Build padding styles (p, px, py, pt, pr, pb, pl)
|
|
49444
|
+
*/
|
|
49445
|
+
buildPaddingStyles(props, styles) {
|
|
48486
49446
|
const pValue = resolveSpacingValue(props.p);
|
|
48487
49447
|
if (pValue) {
|
|
48488
49448
|
styles.push(`padding: ${pValue}`);
|
|
@@ -48513,6 +49473,11 @@ ${children}
|
|
|
48513
49473
|
if (plValue) {
|
|
48514
49474
|
styles.push(`padding-left: ${plValue}`);
|
|
48515
49475
|
}
|
|
49476
|
+
}
|
|
49477
|
+
/**
|
|
49478
|
+
* Build margin styles (m, mx, my, mt, mr, mb, ml)
|
|
49479
|
+
*/
|
|
49480
|
+
buildMarginStyles(props, styles) {
|
|
48516
49481
|
const mValue = resolveSpacingValue(props.m);
|
|
48517
49482
|
if (mValue) {
|
|
48518
49483
|
styles.push(`margin: ${mValue}`);
|
|
@@ -48543,11 +49508,15 @@ ${children}
|
|
|
48543
49508
|
if (mlValue) {
|
|
48544
49509
|
styles.push(`margin-left: ${mlValue}`);
|
|
48545
49510
|
}
|
|
49511
|
+
}
|
|
49512
|
+
/**
|
|
49513
|
+
* Build gap styles
|
|
49514
|
+
*/
|
|
49515
|
+
buildGapStyles(props, styles) {
|
|
48546
49516
|
const gapValue = resolveSpacingValue(props.gap);
|
|
48547
49517
|
if (gapValue) {
|
|
48548
49518
|
styles.push(`gap: ${gapValue}`);
|
|
48549
49519
|
}
|
|
48550
|
-
return styles.join("; ");
|
|
48551
49520
|
}
|
|
48552
49521
|
/**
|
|
48553
49522
|
* Build inline styles for Col node (extends common styles with order)
|
|
@@ -48567,1532 +49536,136 @@ ${children}
|
|
|
48567
49536
|
// Container Node Renderers
|
|
48568
49537
|
// ===========================================
|
|
48569
49538
|
renderCard(node) {
|
|
48570
|
-
|
|
48571
|
-
`${this.prefix}-card`,
|
|
48572
|
-
node.shadow ? `${this.prefix}-card-shadow-${node.shadow}` : void 0,
|
|
48573
|
-
...this.getCommonClasses(node)
|
|
48574
|
-
]);
|
|
48575
|
-
const styles = this.buildCommonStyles(node);
|
|
48576
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48577
|
-
const title = node.title ? `<h3 class="${this.prefix}-title">${this.escapeHtml(node.title)}</h3>
|
|
48578
|
-
` : "";
|
|
48579
|
-
const children = this.renderChildren(node.children);
|
|
48580
|
-
return `<div class="${classes}"${styleAttr}>
|
|
48581
|
-
${title}${children}
|
|
48582
|
-
</div>`;
|
|
49539
|
+
return renderCard(node, this.getRenderContext());
|
|
48583
49540
|
}
|
|
48584
49541
|
renderModal(node) {
|
|
48585
|
-
|
|
48586
|
-
`${this.prefix}-modal`,
|
|
48587
|
-
...this.getCommonClasses(node)
|
|
48588
|
-
]);
|
|
48589
|
-
const styles = this.buildCommonStyles(node);
|
|
48590
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48591
|
-
const title = node.title ? `<h2 class="${this.prefix}-title">${this.escapeHtml(node.title)}</h2>
|
|
48592
|
-
` : "";
|
|
48593
|
-
const children = this.renderChildren(node.children);
|
|
48594
|
-
return `<div class="${this.prefix}-modal-backdrop">
|
|
48595
|
-
<div class="${classes}"${styleAttr} role="dialog" aria-modal="true">
|
|
48596
|
-
${title}${children}
|
|
48597
|
-
</div>
|
|
48598
|
-
</div>`;
|
|
49542
|
+
return renderModal(node, this.getRenderContext());
|
|
48599
49543
|
}
|
|
48600
49544
|
renderDrawer(node) {
|
|
48601
|
-
|
|
48602
|
-
const classes = this.buildClassString([
|
|
48603
|
-
`${this.prefix}-drawer`,
|
|
48604
|
-
`${this.prefix}-drawer-${position}`,
|
|
48605
|
-
...this.getCommonClasses(node)
|
|
48606
|
-
]);
|
|
48607
|
-
const styles = this.buildCommonStyles(node);
|
|
48608
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48609
|
-
const title = node.title ? `<h2 class="${this.prefix}-title">${this.escapeHtml(node.title)}</h2>
|
|
48610
|
-
` : "";
|
|
48611
|
-
const children = this.renderChildren(node.children);
|
|
48612
|
-
return `<aside class="${classes}"${styleAttr}>
|
|
48613
|
-
${title}${children}
|
|
48614
|
-
</aside>`;
|
|
49545
|
+
return renderDrawer(node, this.getRenderContext());
|
|
48615
49546
|
}
|
|
48616
49547
|
renderAccordion(node) {
|
|
48617
|
-
|
|
48618
|
-
`${this.prefix}-accordion`,
|
|
48619
|
-
...this.getCommonClasses(node)
|
|
48620
|
-
]);
|
|
48621
|
-
const styles = this.buildCommonStyles(node);
|
|
48622
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48623
|
-
const title = node.title ? `<button class="${this.prefix}-accordion-header">${this.escapeHtml(node.title)}</button>
|
|
48624
|
-
` : "";
|
|
48625
|
-
const children = this.renderChildren(node.children);
|
|
48626
|
-
return `<div class="${classes}"${styleAttr}>
|
|
48627
|
-
${title}<div class="${this.prefix}-accordion-content">
|
|
48628
|
-
${children}
|
|
48629
|
-
</div>
|
|
48630
|
-
</div>`;
|
|
49548
|
+
return renderAccordion(node, this.getRenderContext());
|
|
48631
49549
|
}
|
|
48632
49550
|
// ===========================================
|
|
48633
49551
|
// Text Node Renderers
|
|
48634
49552
|
// ===========================================
|
|
48635
49553
|
renderText(node) {
|
|
48636
|
-
|
|
48637
|
-
`${this.prefix}-text`,
|
|
48638
|
-
node.size ? `${this.prefix}-text-${node.size}` : void 0,
|
|
48639
|
-
node.weight ? `${this.prefix}-text-${node.weight}` : void 0,
|
|
48640
|
-
node.align ? `${this.prefix}-text-${node.align}` : void 0,
|
|
48641
|
-
node.muted ? `${this.prefix}-text-muted` : void 0,
|
|
48642
|
-
...this.getCommonClasses(node)
|
|
48643
|
-
]);
|
|
48644
|
-
const styles = this.buildCommonStyles(node);
|
|
48645
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48646
|
-
return `<p class="${classes}"${styleAttr}>${this.escapeHtml(node.content)}</p>`;
|
|
49554
|
+
return renderText(node, this.getRenderContext());
|
|
48647
49555
|
}
|
|
48648
49556
|
renderTitle(node) {
|
|
48649
|
-
|
|
48650
|
-
const tag = `h${level}`;
|
|
48651
|
-
const classes = this.buildClassString([
|
|
48652
|
-
`${this.prefix}-title`,
|
|
48653
|
-
node.size ? `${this.prefix}-text-${node.size}` : void 0,
|
|
48654
|
-
node.align ? `${this.prefix}-text-${node.align}` : void 0,
|
|
48655
|
-
...this.getCommonClasses(node)
|
|
48656
|
-
]);
|
|
48657
|
-
const styles = this.buildCommonStyles(node);
|
|
48658
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48659
|
-
return `<${tag} class="${classes}"${styleAttr}>${this.escapeHtml(node.content)}</${tag}>`;
|
|
49557
|
+
return renderTitle(node, this.getRenderContext());
|
|
48660
49558
|
}
|
|
48661
49559
|
renderLink(node) {
|
|
48662
|
-
|
|
48663
|
-
`${this.prefix}-link`,
|
|
48664
|
-
...this.getCommonClasses(node)
|
|
48665
|
-
]);
|
|
48666
|
-
const styles = this.buildCommonStyles(node);
|
|
48667
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48668
|
-
const attrs = {
|
|
48669
|
-
class: classes,
|
|
48670
|
-
href: node.href || "#"
|
|
48671
|
-
};
|
|
48672
|
-
if (node.external) {
|
|
48673
|
-
attrs.target = "_blank";
|
|
48674
|
-
attrs.rel = "noopener noreferrer";
|
|
48675
|
-
}
|
|
48676
|
-
return `<a${this.buildAttrsString(attrs)}${styleAttr}>${this.escapeHtml(node.content)}</a>`;
|
|
49560
|
+
return renderLink(node, this.getRenderContext());
|
|
48677
49561
|
}
|
|
48678
49562
|
// ===========================================
|
|
48679
49563
|
// Input Node Renderers
|
|
48680
49564
|
// ===========================================
|
|
48681
49565
|
renderInput(node) {
|
|
48682
|
-
|
|
48683
|
-
`${this.prefix}-input`,
|
|
48684
|
-
node.icon ? `${this.prefix}-input-with-icon` : void 0,
|
|
48685
|
-
...this.getCommonClasses(node)
|
|
48686
|
-
]);
|
|
48687
|
-
const styles = this.buildCommonStyles(node);
|
|
48688
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48689
|
-
const attrs = {
|
|
48690
|
-
class: inputClasses,
|
|
48691
|
-
type: node.inputType || "text",
|
|
48692
|
-
placeholder: node.placeholder,
|
|
48693
|
-
value: node.value,
|
|
48694
|
-
disabled: node.disabled,
|
|
48695
|
-
required: node.required,
|
|
48696
|
-
readonly: node.readonly
|
|
48697
|
-
};
|
|
48698
|
-
const inputElement = `<input${this.buildAttrsString(attrs)} />`;
|
|
48699
|
-
if (node.icon) {
|
|
48700
|
-
const iconData = getIconData(node.icon);
|
|
48701
|
-
let iconHtml;
|
|
48702
|
-
if (iconData) {
|
|
48703
|
-
iconHtml = renderIconSvg(iconData, 16, 2, `${this.prefix}-input-icon`);
|
|
48704
|
-
} else {
|
|
48705
|
-
iconHtml = `<span class="${this.prefix}-input-icon">[${this.escapeHtml(node.icon)}]</span>`;
|
|
48706
|
-
}
|
|
48707
|
-
const wrapperClasses = this.buildClassString([`${this.prefix}-input-wrapper`]);
|
|
48708
|
-
const wrapper = `<div class="${wrapperClasses}"${styleAttr}>${iconHtml}${inputElement}</div>`;
|
|
48709
|
-
if (node.label) {
|
|
48710
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48711
|
-
${wrapper}`;
|
|
48712
|
-
}
|
|
48713
|
-
return wrapper;
|
|
48714
|
-
}
|
|
48715
|
-
const input = `<input${this.buildAttrsString(attrs)}${styleAttr} />`;
|
|
48716
|
-
if (node.label) {
|
|
48717
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48718
|
-
${input}`;
|
|
48719
|
-
}
|
|
48720
|
-
return input;
|
|
49566
|
+
return renderInput(node, this.getRenderContext());
|
|
48721
49567
|
}
|
|
48722
49568
|
renderTextarea(node) {
|
|
48723
|
-
|
|
48724
|
-
`${this.prefix}-input`,
|
|
48725
|
-
...this.getCommonClasses(node)
|
|
48726
|
-
]);
|
|
48727
|
-
const styles = this.buildCommonStyles(node);
|
|
48728
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48729
|
-
const attrs = {
|
|
48730
|
-
class: classes,
|
|
48731
|
-
placeholder: node.placeholder,
|
|
48732
|
-
disabled: node.disabled,
|
|
48733
|
-
required: node.required,
|
|
48734
|
-
rows: node.rows?.toString()
|
|
48735
|
-
};
|
|
48736
|
-
const textarea = `<textarea${this.buildAttrsString(attrs)}${styleAttr}>${this.escapeHtml(node.value || "")}</textarea>`;
|
|
48737
|
-
if (node.label) {
|
|
48738
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48739
|
-
${textarea}`;
|
|
48740
|
-
}
|
|
48741
|
-
return textarea;
|
|
49569
|
+
return renderTextarea(node, this.getRenderContext());
|
|
48742
49570
|
}
|
|
48743
49571
|
renderSelect(node) {
|
|
48744
|
-
|
|
48745
|
-
`${this.prefix}-input`,
|
|
48746
|
-
...this.getCommonClasses(node)
|
|
48747
|
-
]);
|
|
48748
|
-
const styles = this.buildCommonStyles(node);
|
|
48749
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48750
|
-
const attrs = {
|
|
48751
|
-
class: classes,
|
|
48752
|
-
disabled: node.disabled,
|
|
48753
|
-
required: node.required
|
|
48754
|
-
};
|
|
48755
|
-
const options = node.options.map((opt) => {
|
|
48756
|
-
if (typeof opt === "string") {
|
|
48757
|
-
const selected2 = opt === node.value ? " selected" : "";
|
|
48758
|
-
return `<option value="${this.escapeHtml(opt)}"${selected2}>${this.escapeHtml(opt)}</option>`;
|
|
48759
|
-
}
|
|
48760
|
-
const selected = opt.value === node.value ? " selected" : "";
|
|
48761
|
-
return `<option value="${this.escapeHtml(opt.value)}"${selected}>${this.escapeHtml(opt.label)}</option>`;
|
|
48762
|
-
}).join("\n");
|
|
48763
|
-
const placeholder = node.placeholder ? `<option value="" disabled selected>${this.escapeHtml(node.placeholder)}</option>
|
|
48764
|
-
` : "";
|
|
48765
|
-
const select = `<select${this.buildAttrsString(attrs)}${styleAttr}>
|
|
48766
|
-
${placeholder}${options}
|
|
48767
|
-
</select>`;
|
|
48768
|
-
if (node.label) {
|
|
48769
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48770
|
-
${select}`;
|
|
48771
|
-
}
|
|
48772
|
-
return select;
|
|
49572
|
+
return renderSelect(node, this.getRenderContext());
|
|
48773
49573
|
}
|
|
48774
49574
|
renderCheckbox(node) {
|
|
48775
|
-
|
|
48776
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48777
|
-
const attrs = {
|
|
48778
|
-
type: "checkbox",
|
|
48779
|
-
checked: node.checked,
|
|
48780
|
-
disabled: node.disabled
|
|
48781
|
-
};
|
|
48782
|
-
const checkbox = `<input${this.buildAttrsString(attrs)} />`;
|
|
48783
|
-
if (node.label) {
|
|
48784
|
-
return `<label class="${this.prefix}-checkbox"${styleAttr}>${checkbox}<span>${this.escapeHtml(node.label)}</span></label>`;
|
|
48785
|
-
}
|
|
48786
|
-
return checkbox;
|
|
49575
|
+
return renderCheckbox(node, this.getRenderContext());
|
|
48787
49576
|
}
|
|
48788
49577
|
renderRadio(node) {
|
|
48789
|
-
|
|
48790
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48791
|
-
const attrs = {
|
|
48792
|
-
type: "radio",
|
|
48793
|
-
name: node.name,
|
|
48794
|
-
checked: node.checked,
|
|
48795
|
-
disabled: node.disabled
|
|
48796
|
-
};
|
|
48797
|
-
const radio = `<input${this.buildAttrsString(attrs)} />`;
|
|
48798
|
-
if (node.label) {
|
|
48799
|
-
return `<label class="${this.prefix}-radio"${styleAttr}>${radio}<span>${this.escapeHtml(node.label)}</span></label>`;
|
|
48800
|
-
}
|
|
48801
|
-
return radio;
|
|
49578
|
+
return renderRadio(node, this.getRenderContext());
|
|
48802
49579
|
}
|
|
48803
49580
|
renderSwitch(node) {
|
|
48804
|
-
|
|
48805
|
-
`${this.prefix}-switch`,
|
|
48806
|
-
...this.getCommonClasses(node)
|
|
48807
|
-
]);
|
|
48808
|
-
const styles = this.buildCommonStyles(node);
|
|
48809
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48810
|
-
const attrs = {
|
|
48811
|
-
type: "checkbox",
|
|
48812
|
-
role: "switch",
|
|
48813
|
-
checked: node.checked,
|
|
48814
|
-
disabled: node.disabled
|
|
48815
|
-
};
|
|
48816
|
-
const switchEl = `<input${this.buildAttrsString(attrs)} />`;
|
|
48817
|
-
if (node.label) {
|
|
48818
|
-
return `<label class="${classes}"${styleAttr}>${switchEl} ${this.escapeHtml(node.label)}</label>`;
|
|
48819
|
-
}
|
|
48820
|
-
return `<label class="${classes}"${styleAttr}>${switchEl}</label>`;
|
|
49581
|
+
return renderSwitch(node, this.getRenderContext());
|
|
48821
49582
|
}
|
|
48822
49583
|
renderSlider(node) {
|
|
48823
|
-
|
|
48824
|
-
`${this.prefix}-slider`,
|
|
48825
|
-
...this.getCommonClasses(node)
|
|
48826
|
-
]);
|
|
48827
|
-
const styles = this.buildCommonStyles(node);
|
|
48828
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48829
|
-
const attrs = {
|
|
48830
|
-
class: classes,
|
|
48831
|
-
type: "range",
|
|
48832
|
-
min: node.min?.toString(),
|
|
48833
|
-
max: node.max?.toString(),
|
|
48834
|
-
step: node.step?.toString(),
|
|
48835
|
-
value: node.value?.toString(),
|
|
48836
|
-
disabled: node.disabled
|
|
48837
|
-
};
|
|
48838
|
-
const slider = `<input${this.buildAttrsString(attrs)}${styleAttr} />`;
|
|
48839
|
-
if (node.label) {
|
|
48840
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48841
|
-
${slider}`;
|
|
48842
|
-
}
|
|
48843
|
-
return slider;
|
|
49584
|
+
return renderSlider(node, this.getRenderContext());
|
|
48844
49585
|
}
|
|
48845
49586
|
// ===========================================
|
|
48846
49587
|
// Button Renderer
|
|
48847
49588
|
// ===========================================
|
|
48848
49589
|
renderButton(node) {
|
|
48849
|
-
|
|
48850
|
-
const classes = this.buildClassString([
|
|
48851
|
-
`${this.prefix}-button`,
|
|
48852
|
-
node.primary ? `${this.prefix}-button-primary` : void 0,
|
|
48853
|
-
node.secondary ? `${this.prefix}-button-secondary` : void 0,
|
|
48854
|
-
node.outline ? `${this.prefix}-button-outline` : void 0,
|
|
48855
|
-
node.ghost ? `${this.prefix}-button-ghost` : void 0,
|
|
48856
|
-
node.danger ? `${this.prefix}-button-danger` : void 0,
|
|
48857
|
-
node.size ? `${this.prefix}-button-${node.size}` : void 0,
|
|
48858
|
-
node.disabled ? `${this.prefix}-button-disabled` : void 0,
|
|
48859
|
-
node.loading ? `${this.prefix}-button-loading` : void 0,
|
|
48860
|
-
isIconOnly ? `${this.prefix}-button-icon-only` : void 0,
|
|
48861
|
-
...this.getCommonClasses(node)
|
|
48862
|
-
]);
|
|
48863
|
-
const styles = this.buildCommonStyles(node);
|
|
48864
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48865
|
-
const attrs = {
|
|
48866
|
-
class: classes,
|
|
48867
|
-
disabled: node.disabled
|
|
48868
|
-
};
|
|
48869
|
-
let icon = "";
|
|
48870
|
-
if (node.icon) {
|
|
48871
|
-
const iconData = getIconData(node.icon);
|
|
48872
|
-
if (iconData) {
|
|
48873
|
-
icon = renderIconSvg(iconData, 16, 2, `${this.prefix}-icon`);
|
|
48874
|
-
} else {
|
|
48875
|
-
icon = `<span class="${this.prefix}-icon">[${this.escapeHtml(node.icon)}]</span>`;
|
|
48876
|
-
}
|
|
48877
|
-
}
|
|
48878
|
-
const loading = node.loading ? `<span class="${this.prefix}-spinner ${this.prefix}-spinner-sm"></span>` : "";
|
|
48879
|
-
const content = this.escapeHtml(node.content);
|
|
48880
|
-
return `<button${this.buildAttrsString(attrs)}${styleAttr}>${loading}${icon}${content}</button>`;
|
|
49590
|
+
return renderButton(node, this.getRenderContext());
|
|
48881
49591
|
}
|
|
48882
49592
|
// ===========================================
|
|
48883
49593
|
// Display Node Renderers
|
|
48884
49594
|
// ===========================================
|
|
48885
49595
|
renderImage(node) {
|
|
48886
|
-
|
|
48887
|
-
`${this.prefix}-image`,
|
|
48888
|
-
...this.getCommonClasses(node)
|
|
48889
|
-
]);
|
|
48890
|
-
const styles = this.buildCommonStyles(node);
|
|
48891
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48892
|
-
if (node.src) {
|
|
48893
|
-
const attrs = {
|
|
48894
|
-
class: classes,
|
|
48895
|
-
src: node.src,
|
|
48896
|
-
alt: node.alt || "Image"
|
|
48897
|
-
};
|
|
48898
|
-
const imgStyleAttr = styles ? `; ${styles}` : "";
|
|
48899
|
-
return `<img${this.buildAttrsString(attrs)}${imgStyleAttr ? ` style="${imgStyleAttr.slice(2)}"` : ""} />`;
|
|
48900
|
-
}
|
|
48901
|
-
const label = node.alt || "Image";
|
|
48902
|
-
const icon = `<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>`;
|
|
48903
|
-
return `<div class="${classes}"${styleAttr} role="img" aria-label="${this.escapeHtml(label)}">${icon}<span>${this.escapeHtml(label)}</span></div>`;
|
|
49596
|
+
return renderImage(node, this.getRenderContext());
|
|
48904
49597
|
}
|
|
48905
49598
|
renderPlaceholder(node) {
|
|
48906
|
-
|
|
48907
|
-
`${this.prefix}-placeholder`,
|
|
48908
|
-
...this.getCommonClasses(node)
|
|
48909
|
-
]);
|
|
48910
|
-
const styles = this.buildCommonStyles(node);
|
|
48911
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48912
|
-
const label = node.label ? this.escapeHtml(node.label) : "Placeholder";
|
|
48913
|
-
return `<div class="${classes}"${styleAttr}>${label}</div>`;
|
|
49599
|
+
return renderPlaceholder(node, this.getRenderContext());
|
|
48914
49600
|
}
|
|
48915
49601
|
renderAvatar(node) {
|
|
48916
|
-
|
|
48917
|
-
const classes = this.buildClassString([
|
|
48918
|
-
`${this.prefix}-avatar`,
|
|
48919
|
-
sizeResolved.className,
|
|
48920
|
-
...this.getCommonClasses(node)
|
|
48921
|
-
]);
|
|
48922
|
-
const baseStyles = this.buildCommonStyles(node);
|
|
48923
|
-
const sizeStyle = sizeResolved.style || "";
|
|
48924
|
-
const combinedStyles = baseStyles && sizeStyle ? `${baseStyles}; ${sizeStyle}` : baseStyles || sizeStyle;
|
|
48925
|
-
const styleAttr = combinedStyles ? ` style="${combinedStyles}"` : "";
|
|
48926
|
-
const initials = node.name ? node.name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) : "?";
|
|
48927
|
-
return `<div class="${classes}"${styleAttr} role="img" aria-label="${this.escapeHtml(node.name || "Avatar")}">${initials}</div>`;
|
|
49602
|
+
return renderAvatar(node, this.getRenderContext());
|
|
48928
49603
|
}
|
|
48929
49604
|
renderBadge(node) {
|
|
48930
|
-
|
|
48931
|
-
const iconData = getIconData(node.icon);
|
|
48932
|
-
const classes2 = this.buildClassString([
|
|
48933
|
-
`${this.prefix}-badge-icon`,
|
|
48934
|
-
node.size ? `${this.prefix}-badge-icon-${node.size}` : void 0,
|
|
48935
|
-
node.variant ? `${this.prefix}-badge-icon-${node.variant}` : void 0,
|
|
48936
|
-
...this.getCommonClasses(node)
|
|
48937
|
-
]);
|
|
48938
|
-
const styles2 = this.buildCommonStyles(node);
|
|
48939
|
-
const styleAttr2 = styles2 ? ` style="${styles2}"` : "";
|
|
48940
|
-
if (iconData) {
|
|
48941
|
-
const svg = renderIconSvg(iconData, 24, 2, `${this.prefix}-icon`);
|
|
48942
|
-
return `<span class="${classes2}"${styleAttr2} aria-label="${this.escapeHtml(node.icon)}">${svg}</span>`;
|
|
48943
|
-
}
|
|
48944
|
-
return `<span class="${classes2}"${styleAttr2} aria-label="unknown icon">?</span>`;
|
|
48945
|
-
}
|
|
48946
|
-
const isDot = !node.content || node.content.trim() === "";
|
|
48947
|
-
const classes = this.buildClassString([
|
|
48948
|
-
`${this.prefix}-badge`,
|
|
48949
|
-
isDot ? `${this.prefix}-badge-dot` : void 0,
|
|
48950
|
-
node.variant ? `${this.prefix}-badge-${node.variant}` : void 0,
|
|
48951
|
-
node.pill ? `${this.prefix}-badge-pill` : void 0,
|
|
48952
|
-
...this.getCommonClasses(node)
|
|
48953
|
-
]);
|
|
48954
|
-
const styles = this.buildCommonStyles(node);
|
|
48955
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48956
|
-
return `<span class="${classes}"${styleAttr}>${this.escapeHtml(node.content)}</span>`;
|
|
49605
|
+
return renderBadge(node, this.getRenderContext());
|
|
48957
49606
|
}
|
|
48958
49607
|
renderIcon(node) {
|
|
48959
|
-
|
|
48960
|
-
const sizeResolved = resolveSizeValue(node.size, "icon", this.prefix);
|
|
48961
|
-
const wrapperClasses = this.buildClassString([
|
|
48962
|
-
`${this.prefix}-icon-wrapper`,
|
|
48963
|
-
node.muted ? `${this.prefix}-text-muted` : void 0,
|
|
48964
|
-
...this.getCommonClasses(node)
|
|
48965
|
-
]);
|
|
48966
|
-
const baseStyles = this.buildCommonStyles(node);
|
|
48967
|
-
if (iconData) {
|
|
48968
|
-
const iconClasses = buildClassString([
|
|
48969
|
-
`${this.prefix}-icon`,
|
|
48970
|
-
sizeResolved.className
|
|
48971
|
-
]);
|
|
48972
|
-
const svgStyleAttr = sizeResolved.style ? ` style="${sizeResolved.style}"` : "";
|
|
48973
|
-
const svg = renderIconSvg(iconData, 24, 2, iconClasses, svgStyleAttr);
|
|
48974
|
-
const wrapperStyleAttr2 = baseStyles ? ` style="${baseStyles}"` : "";
|
|
48975
|
-
return `<span class="${wrapperClasses}"${wrapperStyleAttr2} aria-hidden="true">${svg}</span>`;
|
|
48976
|
-
}
|
|
48977
|
-
const size = sizeResolved.style?.match(/(\d+)px/)?.[1] || "24";
|
|
48978
|
-
const sizeNum = parseInt(size, 10);
|
|
48979
|
-
const placeholderSvg = `<svg class="${this.prefix}-icon ${sizeResolved.className || ""}" width="${sizeNum}" height="${sizeNum}" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
48980
|
-
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" stroke-dasharray="4 2" fill="none" opacity="0.5"/>
|
|
48981
|
-
<text x="12" y="16" text-anchor="middle" font-size="10" fill="currentColor" opacity="0.7">?</text>
|
|
48982
|
-
</svg>`;
|
|
48983
|
-
const wrapperStyleAttr = baseStyles ? ` style="${baseStyles}"` : "";
|
|
48984
|
-
return `<span class="${wrapperClasses}"${wrapperStyleAttr} aria-hidden="true" title="Unknown icon: ${this.escapeHtml(node.name)}">${placeholderSvg}</span>`;
|
|
49608
|
+
return renderIcon(node, this.getRenderContext());
|
|
48985
49609
|
}
|
|
48986
49610
|
// ===========================================
|
|
48987
49611
|
// Data Node Renderers
|
|
48988
49612
|
// ===========================================
|
|
48989
49613
|
renderTable(node) {
|
|
48990
|
-
|
|
48991
|
-
`${this.prefix}-table`,
|
|
48992
|
-
node.striped ? `${this.prefix}-table-striped` : void 0,
|
|
48993
|
-
node.bordered ? `${this.prefix}-table-bordered` : void 0,
|
|
48994
|
-
node.hover ? `${this.prefix}-table-hover` : void 0,
|
|
48995
|
-
...this.getCommonClasses(node)
|
|
48996
|
-
]);
|
|
48997
|
-
const styles = this.buildCommonStyles(node);
|
|
48998
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48999
|
-
const thead = `<thead><tr>${node.columns.map((col) => `<th>${this.escapeHtml(col)}</th>`).join("")}</tr></thead>`;
|
|
49000
|
-
const tbody = `<tbody>${node.rows.map(
|
|
49001
|
-
(row) => `<tr>${row.map((cell) => {
|
|
49002
|
-
if (typeof cell === "string") {
|
|
49003
|
-
return `<td>${this.renderTableCellContent(cell)}</td>`;
|
|
49004
|
-
}
|
|
49005
|
-
return `<td>${this.renderNode(cell)}</td>`;
|
|
49006
|
-
}).join("")}</tr>`
|
|
49007
|
-
).join("")}</tbody>`;
|
|
49008
|
-
return `<table class="${classes}"${styleAttr}>
|
|
49009
|
-
${thead}
|
|
49010
|
-
${tbody}
|
|
49011
|
-
</table>`;
|
|
49614
|
+
return renderTable(node, this.getRenderContext());
|
|
49012
49615
|
}
|
|
49013
49616
|
renderList(node) {
|
|
49014
|
-
|
|
49015
|
-
const classes = this.buildClassString([
|
|
49016
|
-
`${this.prefix}-list`,
|
|
49017
|
-
node.ordered ? `${this.prefix}-list-ordered` : void 0,
|
|
49018
|
-
node.none ? `${this.prefix}-list-none` : void 0,
|
|
49019
|
-
...this.getCommonClasses(node)
|
|
49020
|
-
]);
|
|
49021
|
-
const styles = this.buildCommonStyles(node);
|
|
49022
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49023
|
-
const items = node.items.map((item) => {
|
|
49024
|
-
if (typeof item === "string") {
|
|
49025
|
-
return `<li class="${this.prefix}-list-item">${this.escapeHtml(item)}</li>`;
|
|
49026
|
-
}
|
|
49027
|
-
return `<li class="${this.prefix}-list-item">${this.escapeHtml(item.content)}</li>`;
|
|
49028
|
-
}).join("\n");
|
|
49029
|
-
return `<${tag} class="${classes}"${styleAttr}>
|
|
49030
|
-
${items}
|
|
49031
|
-
</${tag}>`;
|
|
49617
|
+
return renderList(node, this.getRenderContext());
|
|
49032
49618
|
}
|
|
49033
49619
|
// ===========================================
|
|
49034
49620
|
// Feedback Node Renderers
|
|
49035
49621
|
// ===========================================
|
|
49036
49622
|
renderAlert(node) {
|
|
49037
|
-
|
|
49038
|
-
`${this.prefix}-alert`,
|
|
49039
|
-
node.variant ? `${this.prefix}-alert-${node.variant}` : void 0,
|
|
49040
|
-
...this.getCommonClasses(node)
|
|
49041
|
-
]);
|
|
49042
|
-
const styles = this.buildCommonStyles(node);
|
|
49043
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49044
|
-
const dismissBtn = node.dismissible ? ` <button class="${this.prefix}-alert-close" aria-label="Close">×</button>` : "";
|
|
49045
|
-
return `<div class="${classes}"${styleAttr} role="alert">${this.escapeHtml(node.content)}${dismissBtn}</div>`;
|
|
49623
|
+
return renderAlert(node, this.getRenderContext());
|
|
49046
49624
|
}
|
|
49047
49625
|
renderToast(node) {
|
|
49048
|
-
|
|
49049
|
-
`${this.prefix}-toast`,
|
|
49050
|
-
node.position ? `${this.prefix}-toast-${node.position}` : void 0,
|
|
49051
|
-
node.variant ? `${this.prefix}-toast-${node.variant}` : void 0,
|
|
49052
|
-
...this.getCommonClasses(node)
|
|
49053
|
-
]);
|
|
49054
|
-
const styles = this.buildCommonStyles(node);
|
|
49055
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49056
|
-
return `<div class="${classes}"${styleAttr} role="status">${this.escapeHtml(node.content)}</div>`;
|
|
49626
|
+
return renderToast(node, this.getRenderContext());
|
|
49057
49627
|
}
|
|
49058
49628
|
renderProgress(node) {
|
|
49059
|
-
|
|
49060
|
-
`${this.prefix}-progress`,
|
|
49061
|
-
...this.getCommonClasses(node)
|
|
49062
|
-
]);
|
|
49063
|
-
const styles = this.buildCommonStyles(node);
|
|
49064
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49065
|
-
const value = node.value || 0;
|
|
49066
|
-
const max = node.max || 100;
|
|
49067
|
-
const percentage = Math.round(value / max * 100);
|
|
49068
|
-
const label = node.label ? `<span class="${this.prefix}-progress-label">${this.escapeHtml(node.label)}</span>` : "";
|
|
49069
|
-
if (node.indeterminate) {
|
|
49070
|
-
return `<div class="${classes} ${this.prefix}-progress-indeterminate"${styleAttr} role="progressbar">${label}</div>`;
|
|
49071
|
-
}
|
|
49072
|
-
return `<div class="${classes}"${styleAttr} role="progressbar" aria-valuenow="${value}" aria-valuemin="0" aria-valuemax="${max}">
|
|
49073
|
-
${label}
|
|
49074
|
-
<div class="${this.prefix}-progress-bar" style="width: ${percentage}%"></div>
|
|
49075
|
-
</div>`;
|
|
49629
|
+
return renderProgress(node, this.getRenderContext());
|
|
49076
49630
|
}
|
|
49077
49631
|
renderSpinner(node) {
|
|
49078
|
-
|
|
49079
|
-
const classes = this.buildClassString([
|
|
49080
|
-
`${this.prefix}-spinner`,
|
|
49081
|
-
sizeResolved.className,
|
|
49082
|
-
...this.getCommonClasses(node)
|
|
49083
|
-
]);
|
|
49084
|
-
const baseStyles = this.buildCommonStyles(node);
|
|
49085
|
-
const sizeStyle = sizeResolved.style || "";
|
|
49086
|
-
const combinedStyles = baseStyles && sizeStyle ? `${baseStyles}; ${sizeStyle}` : baseStyles || sizeStyle;
|
|
49087
|
-
const styleAttr = combinedStyles ? ` style="${combinedStyles}"` : "";
|
|
49088
|
-
const label = node.label || "Loading...";
|
|
49089
|
-
return `<span class="${classes}"${styleAttr} role="status" aria-label="${this.escapeHtml(label)}"></span>`;
|
|
49632
|
+
return renderSpinner(node, this.getRenderContext());
|
|
49090
49633
|
}
|
|
49091
49634
|
// ===========================================
|
|
49092
49635
|
// Overlay Node Renderers
|
|
49093
49636
|
// ===========================================
|
|
49094
49637
|
renderTooltip(node) {
|
|
49095
|
-
|
|
49096
|
-
`${this.prefix}-tooltip-wrapper`,
|
|
49097
|
-
...this.getCommonClasses(node)
|
|
49098
|
-
]);
|
|
49099
|
-
const styles = this.buildCommonStyles(node);
|
|
49100
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49101
|
-
const position = node.position || "top";
|
|
49102
|
-
const children = this.renderChildren(node.children);
|
|
49103
|
-
return `<div class="${classes}"${styleAttr}>
|
|
49104
|
-
${children}
|
|
49105
|
-
<div class="${this.prefix}-tooltip ${this.prefix}-tooltip-${position}" role="tooltip">${this.escapeHtml(node.content)}</div>
|
|
49106
|
-
</div>`;
|
|
49638
|
+
return renderTooltip(node, this.getRenderContext());
|
|
49107
49639
|
}
|
|
49108
49640
|
renderPopover(node) {
|
|
49109
|
-
|
|
49110
|
-
`${this.prefix}-popover`,
|
|
49111
|
-
...this.getCommonClasses(node)
|
|
49112
|
-
]);
|
|
49113
|
-
const styles = this.buildCommonStyles(node);
|
|
49114
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49115
|
-
const title = node.title ? `<div class="${this.prefix}-popover-header">${this.escapeHtml(node.title)}</div>
|
|
49116
|
-
` : "";
|
|
49117
|
-
const children = this.renderChildren(node.children);
|
|
49118
|
-
return `<div class="${classes}"${styleAttr}>
|
|
49119
|
-
${title}<div class="${this.prefix}-popover-body">
|
|
49120
|
-
${children}
|
|
49121
|
-
</div>
|
|
49122
|
-
</div>`;
|
|
49641
|
+
return renderPopover(node, this.getRenderContext());
|
|
49123
49642
|
}
|
|
49124
49643
|
renderDropdown(node) {
|
|
49125
|
-
|
|
49126
|
-
`${this.prefix}-dropdown`,
|
|
49127
|
-
...this.getCommonClasses(node)
|
|
49128
|
-
]);
|
|
49129
|
-
const styles = this.buildCommonStyles(node);
|
|
49130
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49131
|
-
const items = node.items.map((item) => {
|
|
49132
|
-
if ("type" in item && item.type === "divider") {
|
|
49133
|
-
return `<hr class="${this.prefix}-divider" />`;
|
|
49134
|
-
}
|
|
49135
|
-
const dropdownItem = item;
|
|
49136
|
-
const itemClasses = this.buildClassString([
|
|
49137
|
-
`${this.prefix}-dropdown-item`,
|
|
49138
|
-
dropdownItem.danger ? `${this.prefix}-dropdown-item-danger` : void 0,
|
|
49139
|
-
dropdownItem.disabled ? `${this.prefix}-dropdown-item-disabled` : void 0
|
|
49140
|
-
]);
|
|
49141
|
-
return `<button class="${itemClasses}"${dropdownItem.disabled ? " disabled" : ""}>${this.escapeHtml(dropdownItem.label)}</button>`;
|
|
49142
|
-
}).join("\n");
|
|
49143
|
-
return `<div class="${classes}"${styleAttr}>
|
|
49144
|
-
${items}
|
|
49145
|
-
</div>`;
|
|
49644
|
+
return renderDropdown(node, this.getRenderContext());
|
|
49146
49645
|
}
|
|
49147
49646
|
// ===========================================
|
|
49148
49647
|
// Navigation Node Renderers
|
|
49149
49648
|
// ===========================================
|
|
49150
49649
|
renderNav(node) {
|
|
49151
|
-
|
|
49152
|
-
`${this.prefix}-nav`,
|
|
49153
|
-
node.vertical ? `${this.prefix}-nav-vertical` : void 0,
|
|
49154
|
-
...this.getCommonClasses(node)
|
|
49155
|
-
]);
|
|
49156
|
-
const styles = this.buildCommonStyles(node);
|
|
49157
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49158
|
-
const items = node.items.map((item) => {
|
|
49159
|
-
if (typeof item === "string") {
|
|
49160
|
-
return `<a class="${this.prefix}-nav-link" href="#">${this.escapeHtml(item)}</a>`;
|
|
49161
|
-
}
|
|
49162
|
-
const linkClasses = this.buildClassString([
|
|
49163
|
-
`${this.prefix}-nav-link`,
|
|
49164
|
-
item.active ? `${this.prefix}-nav-link-active` : void 0,
|
|
49165
|
-
item.disabled ? `${this.prefix}-nav-link-disabled` : void 0
|
|
49166
|
-
]);
|
|
49167
|
-
return `<a class="${linkClasses}" href="${item.href || "#"}">${this.escapeHtml(item.label)}</a>`;
|
|
49168
|
-
}).join("\n");
|
|
49169
|
-
return `<nav class="${classes}"${styleAttr}>
|
|
49170
|
-
${items}
|
|
49171
|
-
</nav>`;
|
|
49650
|
+
return renderNav(node, this.getRenderContext());
|
|
49172
49651
|
}
|
|
49173
49652
|
renderTabs(node) {
|
|
49174
|
-
|
|
49175
|
-
`${this.prefix}-tabs`,
|
|
49176
|
-
...this.getCommonClasses(node)
|
|
49177
|
-
]);
|
|
49178
|
-
const styles = this.buildCommonStyles(node);
|
|
49179
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49180
|
-
const tabList = node.items.map((label, idx) => {
|
|
49181
|
-
const isActive = idx === (node.active || 0);
|
|
49182
|
-
const tabClasses = `${this.prefix}-tab${isActive ? ` ${this.prefix}-tab-active` : ""}`;
|
|
49183
|
-
return `<button class="${tabClasses}" role="tab" aria-selected="${isActive}">${this.escapeHtml(label)}</button>`;
|
|
49184
|
-
}).join("\n");
|
|
49185
|
-
return `<div class="${classes}"${styleAttr}>
|
|
49186
|
-
<div class="${this.prefix}-tab-list" role="tablist">
|
|
49187
|
-
${tabList}
|
|
49188
|
-
</div>
|
|
49189
|
-
</div>`;
|
|
49653
|
+
return renderTabs(node, this.getRenderContext());
|
|
49190
49654
|
}
|
|
49191
49655
|
renderBreadcrumb(node) {
|
|
49192
|
-
|
|
49193
|
-
`${this.prefix}-breadcrumb`,
|
|
49194
|
-
...this.getCommonClasses(node)
|
|
49195
|
-
]);
|
|
49196
|
-
const styles = this.buildCommonStyles(node);
|
|
49197
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49198
|
-
const items = node.items.map((item, idx) => {
|
|
49199
|
-
const isLast = idx === node.items.length - 1;
|
|
49200
|
-
if (typeof item === "string") {
|
|
49201
|
-
return isLast ? `<span class="${this.prefix}-breadcrumb-item" aria-current="page">${this.escapeHtml(item)}</span>` : `<a class="${this.prefix}-breadcrumb-item" href="#">${this.escapeHtml(item)}</a>`;
|
|
49202
|
-
}
|
|
49203
|
-
return isLast ? `<span class="${this.prefix}-breadcrumb-item" aria-current="page">${this.escapeHtml(item.label)}</span>` : `<a class="${this.prefix}-breadcrumb-item" href="${item.href || "#"}">${this.escapeHtml(item.label)}</a>`;
|
|
49204
|
-
}).join(" / ");
|
|
49205
|
-
return `<nav class="${classes}"${styleAttr} aria-label="Breadcrumb">${items}</nav>`;
|
|
49656
|
+
return renderBreadcrumb(node, this.getRenderContext());
|
|
49206
49657
|
}
|
|
49207
49658
|
// ===========================================
|
|
49208
49659
|
// Divider Renderer
|
|
49209
49660
|
// ===========================================
|
|
49210
49661
|
renderDivider(node) {
|
|
49211
|
-
|
|
49212
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49213
|
-
return `<hr class="${this.prefix}-divider"${styleAttr} />`;
|
|
49214
|
-
}
|
|
49215
|
-
// ===========================================
|
|
49216
|
-
// Semantic Marker Rendering
|
|
49217
|
-
// ===========================================
|
|
49218
|
-
/**
|
|
49219
|
-
* Parse and render semantic markers in text content
|
|
49220
|
-
*
|
|
49221
|
-
* Semantic markers use the syntax [component:variant] to indicate
|
|
49222
|
-
* what a visual element represents. This helps LLMs understand
|
|
49223
|
-
* the meaning of placeholder content.
|
|
49224
|
-
*
|
|
49225
|
-
* Supported markers:
|
|
49226
|
-
* - [avatar] or [avatar:size] - User avatar (renders as circle placeholder)
|
|
49227
|
-
* - [badge:variant] TEXT - Status badge (TEXT is displayed inside the badge)
|
|
49228
|
-
* - [dot:variant] - Status dot (renders as small circle before text)
|
|
49229
|
-
* - [icon:name] - Icon placeholder
|
|
49230
|
-
*
|
|
49231
|
-
* Examples:
|
|
49232
|
-
* - "[avatar] John Doe" → renders avatar circle + "John Doe"
|
|
49233
|
-
* - "[badge:primary] PRO" → renders badge containing "PRO"
|
|
49234
|
-
* - "[dot:success] Active" → renders green dot + "Active"
|
|
49235
|
-
*/
|
|
49236
|
-
renderSemanticMarkers(text) {
|
|
49237
|
-
const markerPattern = /\[([a-z]+)(?::([a-z0-9-]+))?\](\s*)/gi;
|
|
49238
|
-
let result = "";
|
|
49239
|
-
let lastIndex = 0;
|
|
49240
|
-
let match;
|
|
49241
|
-
while ((match = markerPattern.exec(text)) !== null) {
|
|
49242
|
-
if (match.index > lastIndex) {
|
|
49243
|
-
result += this.escapeHtml(text.substring(lastIndex, match.index));
|
|
49244
|
-
}
|
|
49245
|
-
const [fullMatch, component, variant] = match;
|
|
49246
|
-
const comp = component.toLowerCase();
|
|
49247
|
-
const varnt = variant?.toLowerCase();
|
|
49248
|
-
if (comp === "badge") {
|
|
49249
|
-
const afterMarker = text.substring(match.index + fullMatch.length);
|
|
49250
|
-
const contentMatch = afterMarker.match(/^([^\n\[]+?)(?=\n|\[|$)/);
|
|
49251
|
-
const badgeContent = contentMatch ? contentMatch[1].trim() : "";
|
|
49252
|
-
result += this.renderSemanticMarkerWithContent(comp, varnt, badgeContent);
|
|
49253
|
-
lastIndex = match.index + fullMatch.length + (contentMatch ? contentMatch[0].length : 0);
|
|
49254
|
-
markerPattern.lastIndex = lastIndex;
|
|
49255
|
-
} else {
|
|
49256
|
-
result += this.renderSemanticMarker(comp, varnt);
|
|
49257
|
-
lastIndex = match.index + fullMatch.length;
|
|
49258
|
-
}
|
|
49259
|
-
}
|
|
49260
|
-
if (lastIndex < text.length) {
|
|
49261
|
-
result += this.escapeHtml(text.substring(lastIndex));
|
|
49262
|
-
}
|
|
49263
|
-
if (lastIndex === 0) {
|
|
49264
|
-
return this.escapeHtml(text);
|
|
49265
|
-
}
|
|
49266
|
-
return result;
|
|
49267
|
-
}
|
|
49268
|
-
/**
|
|
49269
|
-
* Render a single semantic marker to HTML (without content)
|
|
49270
|
-
*/
|
|
49271
|
-
renderSemanticMarker(component, variant) {
|
|
49272
|
-
const prefix = this.prefix;
|
|
49273
|
-
switch (component) {
|
|
49274
|
-
case "avatar":
|
|
49275
|
-
const avatarSize = variant || "sm";
|
|
49276
|
-
return `<span class="${prefix}-semantic-avatar ${prefix}-semantic-avatar-${avatarSize}" data-semantic="avatar" data-variant="${avatarSize}" aria-hidden="true"></span>`;
|
|
49277
|
-
case "dot":
|
|
49278
|
-
const dotVariant = variant || "default";
|
|
49279
|
-
return `<span class="${prefix}-semantic-dot ${prefix}-semantic-dot-${dotVariant}" data-semantic="dot" data-variant="${dotVariant}" aria-hidden="true"></span>`;
|
|
49280
|
-
case "icon":
|
|
49281
|
-
const iconName = variant || "default";
|
|
49282
|
-
return `<span class="${prefix}-semantic-icon" data-semantic="icon" data-variant="${iconName}" aria-hidden="true">[${iconName}]</span>`;
|
|
49283
|
-
default:
|
|
49284
|
-
return `<span class="${prefix}-semantic-unknown" data-semantic="${component}" data-variant="${variant || ""}">[${component}${variant ? ":" + variant : ""}]</span>`;
|
|
49285
|
-
}
|
|
49286
|
-
}
|
|
49287
|
-
/**
|
|
49288
|
-
* Render a semantic marker with text content (for badge)
|
|
49289
|
-
*/
|
|
49290
|
-
renderSemanticMarkerWithContent(component, variant, content) {
|
|
49291
|
-
const prefix = this.prefix;
|
|
49292
|
-
switch (component) {
|
|
49293
|
-
case "badge":
|
|
49294
|
-
const badgeVariant = variant || "default";
|
|
49295
|
-
const escapedContent = this.escapeHtml(content);
|
|
49296
|
-
return `<span class="${prefix}-semantic-badge ${prefix}-semantic-badge-${badgeVariant}" data-semantic="badge" data-variant="${badgeVariant}">${escapedContent}</span>`;
|
|
49297
|
-
default:
|
|
49298
|
-
return this.renderSemanticMarker(component, variant) + this.escapeHtml(content);
|
|
49299
|
-
}
|
|
49300
|
-
}
|
|
49301
|
-
/**
|
|
49302
|
-
* Process table cell content with semantic markers and newlines
|
|
49303
|
-
*
|
|
49304
|
-
* Special handling for avatar + text layout:
|
|
49305
|
-
* When content starts with [avatar], wraps in flex container
|
|
49306
|
-
* so avatar and text align horizontally, with text stacking vertically
|
|
49307
|
-
*/
|
|
49308
|
-
renderTableCellContent(content) {
|
|
49309
|
-
const avatarMatch = content.match(/^\[avatar(?::([a-z0-9-]+))?\]\s*/i);
|
|
49310
|
-
if (avatarMatch) {
|
|
49311
|
-
const avatarVariant = avatarMatch[1]?.toLowerCase();
|
|
49312
|
-
const avatarHtml = this.renderSemanticMarker("avatar", avatarVariant);
|
|
49313
|
-
const restContent = content.slice(avatarMatch[0].length);
|
|
49314
|
-
const restHtml = this.renderSemanticMarkers(restContent);
|
|
49315
|
-
const lines = restHtml.split("\n");
|
|
49316
|
-
const textHtml = lines.length > 1 ? lines.map((line) => `<span>${line}</span>`).join("") : restHtml;
|
|
49317
|
-
return `<div class="${this.prefix}-cell-avatar-layout">${avatarHtml}<div class="${this.prefix}-cell-avatar-text">${textHtml}</div></div>`;
|
|
49318
|
-
}
|
|
49319
|
-
const withMarkers = this.renderSemanticMarkers(content);
|
|
49320
|
-
return withMarkers.replace(/\n/g, "<br>");
|
|
49662
|
+
return renderDivider(node, this.getRenderContext());
|
|
49321
49663
|
}
|
|
49322
49664
|
};
|
|
49323
49665
|
function createHtmlRenderer(options) {
|
|
49324
49666
|
return new HtmlRenderer(options);
|
|
49325
49667
|
}
|
|
49326
49668
|
|
|
49327
|
-
// src/renderer/svg/index.ts
|
|
49328
|
-
var SvgRenderer = class {
|
|
49329
|
-
options;
|
|
49330
|
-
theme;
|
|
49331
|
-
currentX = 0;
|
|
49332
|
-
currentY = 0;
|
|
49333
|
-
contentWidth = 0;
|
|
49334
|
-
constructor(options = {}) {
|
|
49335
|
-
this.options = {
|
|
49336
|
-
width: options.width ?? 800,
|
|
49337
|
-
height: options.height ?? 600,
|
|
49338
|
-
scale: options.scale ?? 1,
|
|
49339
|
-
background: options.background ?? "#ffffff",
|
|
49340
|
-
padding: options.padding ?? 20,
|
|
49341
|
-
fontFamily: options.fontFamily ?? "system-ui, -apple-system, sans-serif"
|
|
49342
|
-
};
|
|
49343
|
-
this.theme = defaultTheme;
|
|
49344
|
-
this.contentWidth = this.options.width - this.options.padding * 2;
|
|
49345
|
-
}
|
|
49346
|
-
/**
|
|
49347
|
-
* Render a wireframe document to SVG
|
|
49348
|
-
*/
|
|
49349
|
-
render(doc) {
|
|
49350
|
-
this.currentX = this.options.padding;
|
|
49351
|
-
this.currentY = this.options.padding;
|
|
49352
|
-
const firstPage = doc.children[0];
|
|
49353
|
-
let width = this.options.width;
|
|
49354
|
-
let height = this.options.height;
|
|
49355
|
-
if (firstPage && (firstPage.viewport !== void 0 || firstPage.device !== void 0)) {
|
|
49356
|
-
const viewport = resolveViewport(firstPage.viewport, firstPage.device);
|
|
49357
|
-
width = viewport.width;
|
|
49358
|
-
height = viewport.height;
|
|
49359
|
-
this.contentWidth = width - this.options.padding * 2;
|
|
49360
|
-
}
|
|
49361
|
-
const content = doc.children.map((page) => this.renderPage(page)).join("\n");
|
|
49362
|
-
const svg = `<?xml version="1.0" encoding="UTF-8"?>
|
|
49363
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" width="${width}" height="${height}">
|
|
49364
|
-
<defs>
|
|
49365
|
-
${this.generateDefs()}
|
|
49366
|
-
</defs>
|
|
49367
|
-
<rect width="100%" height="100%" fill="${this.options.background}"/>
|
|
49368
|
-
<g transform="scale(${this.options.scale})">
|
|
49369
|
-
${content}
|
|
49370
|
-
</g>
|
|
49371
|
-
</svg>`;
|
|
49372
|
-
return { svg, width, height };
|
|
49373
|
-
}
|
|
49374
|
-
/**
|
|
49375
|
-
* Generate SVG defs (styles, patterns, etc.)
|
|
49376
|
-
*/
|
|
49377
|
-
generateDefs() {
|
|
49378
|
-
return `
|
|
49379
|
-
<style>
|
|
49380
|
-
text { font-family: ${this.options.fontFamily}; }
|
|
49381
|
-
.wf-title { font-weight: 600; }
|
|
49382
|
-
.wf-muted { fill: ${this.theme.colors.muted}; }
|
|
49383
|
-
</style>
|
|
49384
|
-
`;
|
|
49385
|
-
}
|
|
49386
|
-
/**
|
|
49387
|
-
* Render a page node
|
|
49388
|
-
*/
|
|
49389
|
-
renderPage(node) {
|
|
49390
|
-
const elements = [];
|
|
49391
|
-
if (node.title) {
|
|
49392
|
-
elements.push(this.renderPageTitle(node.title));
|
|
49393
|
-
}
|
|
49394
|
-
for (const child of node.children) {
|
|
49395
|
-
elements.push(this.renderNode(child));
|
|
49396
|
-
}
|
|
49397
|
-
return elements.join("\n");
|
|
49398
|
-
}
|
|
49399
|
-
/**
|
|
49400
|
-
* Render page title
|
|
49401
|
-
*/
|
|
49402
|
-
renderPageTitle(title) {
|
|
49403
|
-
const fontSize = 24;
|
|
49404
|
-
const y = this.currentY + fontSize;
|
|
49405
|
-
this.currentY += fontSize + 16;
|
|
49406
|
-
return `<text x="${this.currentX}" y="${y}" font-size="${fontSize}" font-weight="600" fill="${this.theme.colors.foreground}">${this.escapeXml(title)}</text>`;
|
|
49407
|
-
}
|
|
49408
|
-
/**
|
|
49409
|
-
* Render any AST node
|
|
49410
|
-
*/
|
|
49411
|
-
renderNode(node) {
|
|
49412
|
-
switch (node.type) {
|
|
49413
|
-
// Layout nodes
|
|
49414
|
-
case "Row":
|
|
49415
|
-
return this.renderRow(node);
|
|
49416
|
-
case "Col":
|
|
49417
|
-
return this.renderCol(node);
|
|
49418
|
-
case "Header":
|
|
49419
|
-
return this.renderHeader(node);
|
|
49420
|
-
case "Main":
|
|
49421
|
-
return this.renderMain(node);
|
|
49422
|
-
case "Footer":
|
|
49423
|
-
return this.renderFooter(node);
|
|
49424
|
-
case "Sidebar":
|
|
49425
|
-
return this.renderSidebar(node);
|
|
49426
|
-
// Container nodes
|
|
49427
|
-
case "Card":
|
|
49428
|
-
return this.renderCard(node);
|
|
49429
|
-
case "Modal":
|
|
49430
|
-
return this.renderModal(node);
|
|
49431
|
-
// Text nodes
|
|
49432
|
-
case "Text":
|
|
49433
|
-
return this.renderText(node);
|
|
49434
|
-
case "Title":
|
|
49435
|
-
return this.renderTitle(node);
|
|
49436
|
-
case "Link":
|
|
49437
|
-
return this.renderLink(node);
|
|
49438
|
-
// Input nodes
|
|
49439
|
-
case "Input":
|
|
49440
|
-
return this.renderInput(node);
|
|
49441
|
-
case "Textarea":
|
|
49442
|
-
return this.renderTextarea(node);
|
|
49443
|
-
case "Select":
|
|
49444
|
-
return this.renderSelect(node);
|
|
49445
|
-
case "Checkbox":
|
|
49446
|
-
return this.renderCheckbox(node);
|
|
49447
|
-
case "Radio":
|
|
49448
|
-
return this.renderRadio(node);
|
|
49449
|
-
case "Switch":
|
|
49450
|
-
return this.renderSwitch(node);
|
|
49451
|
-
// Button
|
|
49452
|
-
case "Button":
|
|
49453
|
-
return this.renderButton(node);
|
|
49454
|
-
// Display nodes
|
|
49455
|
-
case "Image":
|
|
49456
|
-
return this.renderImage(node);
|
|
49457
|
-
case "Placeholder":
|
|
49458
|
-
return this.renderPlaceholder(node);
|
|
49459
|
-
case "Avatar":
|
|
49460
|
-
return this.renderAvatar(node);
|
|
49461
|
-
case "Badge":
|
|
49462
|
-
return this.renderBadge(node);
|
|
49463
|
-
// Data nodes
|
|
49464
|
-
case "Table":
|
|
49465
|
-
return this.renderTable(node);
|
|
49466
|
-
case "List":
|
|
49467
|
-
return this.renderList(node);
|
|
49468
|
-
// Feedback nodes
|
|
49469
|
-
case "Alert":
|
|
49470
|
-
return this.renderAlert(node);
|
|
49471
|
-
case "Progress":
|
|
49472
|
-
return this.renderProgress(node);
|
|
49473
|
-
case "Spinner":
|
|
49474
|
-
return this.renderSpinner(node);
|
|
49475
|
-
// Navigation nodes
|
|
49476
|
-
case "Nav":
|
|
49477
|
-
return this.renderNav(node);
|
|
49478
|
-
case "Tabs":
|
|
49479
|
-
return this.renderTabs(node);
|
|
49480
|
-
case "Breadcrumb":
|
|
49481
|
-
return this.renderBreadcrumb(node);
|
|
49482
|
-
default:
|
|
49483
|
-
return `<!-- Unsupported: ${node.type} -->`;
|
|
49484
|
-
}
|
|
49485
|
-
}
|
|
49486
|
-
// ===========================================
|
|
49487
|
-
// Layout Renderers
|
|
49488
|
-
// ===========================================
|
|
49489
|
-
renderRow(node) {
|
|
49490
|
-
const savedX = this.currentX;
|
|
49491
|
-
const savedY = this.currentY;
|
|
49492
|
-
const elements = [];
|
|
49493
|
-
const totalSpan = node.children.reduce((sum, child) => {
|
|
49494
|
-
if ("span" in child && typeof child.span === "number") {
|
|
49495
|
-
return sum + child.span;
|
|
49496
|
-
}
|
|
49497
|
-
return sum + 1;
|
|
49498
|
-
}, 0);
|
|
49499
|
-
const colWidth = this.contentWidth / Math.max(totalSpan, 1);
|
|
49500
|
-
let maxHeight = 0;
|
|
49501
|
-
for (const child of node.children) {
|
|
49502
|
-
const span = "span" in child && typeof child.span === "number" ? child.span : 1;
|
|
49503
|
-
const childWidth = colWidth * span;
|
|
49504
|
-
const startY = this.currentY;
|
|
49505
|
-
elements.push(this.renderNode(child));
|
|
49506
|
-
const childHeight = this.currentY - startY;
|
|
49507
|
-
maxHeight = Math.max(maxHeight, childHeight);
|
|
49508
|
-
this.currentX += childWidth;
|
|
49509
|
-
this.currentY = savedY;
|
|
49510
|
-
}
|
|
49511
|
-
this.currentX = savedX;
|
|
49512
|
-
this.currentY = savedY + maxHeight;
|
|
49513
|
-
return elements.join("\n");
|
|
49514
|
-
}
|
|
49515
|
-
renderCol(node) {
|
|
49516
|
-
return node.children.map((child) => this.renderNode(child)).join("\n");
|
|
49517
|
-
}
|
|
49518
|
-
renderHeader(node) {
|
|
49519
|
-
const height = 60;
|
|
49520
|
-
const x = this.currentX;
|
|
49521
|
-
const y = this.currentY;
|
|
49522
|
-
const savedY = this.currentY;
|
|
49523
|
-
this.currentY += 16;
|
|
49524
|
-
const children = node.children.map((c) => this.renderNode(c)).join("\n");
|
|
49525
|
-
this.currentY = savedY + height + 8;
|
|
49526
|
-
return `
|
|
49527
|
-
<g transform="translate(${x}, ${y})">
|
|
49528
|
-
<rect width="${this.contentWidth}" height="${height}" fill="${this.theme.colors.background}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49529
|
-
${children}
|
|
49530
|
-
</g>`;
|
|
49531
|
-
}
|
|
49532
|
-
renderMain(node) {
|
|
49533
|
-
return node.children.map((c) => this.renderNode(c)).join("\n");
|
|
49534
|
-
}
|
|
49535
|
-
renderFooter(node) {
|
|
49536
|
-
const height = 60;
|
|
49537
|
-
const x = this.currentX;
|
|
49538
|
-
const y = this.currentY;
|
|
49539
|
-
const savedY = this.currentY;
|
|
49540
|
-
this.currentY += 16;
|
|
49541
|
-
const children = node.children.map((c) => this.renderNode(c)).join("\n");
|
|
49542
|
-
this.currentY = savedY + height + 8;
|
|
49543
|
-
return `
|
|
49544
|
-
<g transform="translate(${x}, ${y})">
|
|
49545
|
-
<rect width="${this.contentWidth}" height="${height}" fill="${this.theme.colors.background}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49546
|
-
${children}
|
|
49547
|
-
</g>`;
|
|
49548
|
-
}
|
|
49549
|
-
renderSidebar(node) {
|
|
49550
|
-
const width = 200;
|
|
49551
|
-
const height = 300;
|
|
49552
|
-
const x = this.currentX;
|
|
49553
|
-
const y = this.currentY;
|
|
49554
|
-
const savedY = this.currentY;
|
|
49555
|
-
this.currentY += 16;
|
|
49556
|
-
const children = node.children.map((c) => this.renderNode(c)).join("\n");
|
|
49557
|
-
this.currentY = savedY + height + 8;
|
|
49558
|
-
return `
|
|
49559
|
-
<g transform="translate(${x}, ${y})">
|
|
49560
|
-
<rect width="${width}" height="${height}" fill="${this.theme.colors.background}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49561
|
-
${children}
|
|
49562
|
-
</g>`;
|
|
49563
|
-
}
|
|
49564
|
-
// ===========================================
|
|
49565
|
-
// Container Renderers
|
|
49566
|
-
// ===========================================
|
|
49567
|
-
renderCard(node) {
|
|
49568
|
-
const width = Math.min(300, this.contentWidth);
|
|
49569
|
-
const x = this.currentX;
|
|
49570
|
-
const y = this.currentY;
|
|
49571
|
-
const savedY = this.currentY;
|
|
49572
|
-
this.currentY += 16;
|
|
49573
|
-
let titleSvg = "";
|
|
49574
|
-
if (node.title) {
|
|
49575
|
-
const titleFontSize = 16;
|
|
49576
|
-
titleSvg = `<text x="16" y="${titleFontSize + 12}" font-size="${titleFontSize}" font-weight="600" fill="${this.theme.colors.foreground}">${this.escapeXml(node.title)}</text>`;
|
|
49577
|
-
this.currentY += titleFontSize + 8;
|
|
49578
|
-
}
|
|
49579
|
-
const childStartY = this.currentY - savedY;
|
|
49580
|
-
const children = node.children.map((c) => this.renderNode(c)).join("\n");
|
|
49581
|
-
const contentHeight = Math.max(this.currentY - savedY, 100);
|
|
49582
|
-
this.currentY = savedY + contentHeight + 16;
|
|
49583
|
-
return `
|
|
49584
|
-
<g transform="translate(${x}, ${y})">
|
|
49585
|
-
<rect width="${width}" height="${contentHeight}" rx="8" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49586
|
-
${titleSvg}
|
|
49587
|
-
<g transform="translate(16, ${childStartY})">
|
|
49588
|
-
${children}
|
|
49589
|
-
</g>
|
|
49590
|
-
</g>`;
|
|
49591
|
-
}
|
|
49592
|
-
renderModal(node) {
|
|
49593
|
-
const width = 400;
|
|
49594
|
-
const height = 300;
|
|
49595
|
-
const x = (this.options.width - width) / 2;
|
|
49596
|
-
const y = (this.options.height - height) / 2;
|
|
49597
|
-
let titleSvg = "";
|
|
49598
|
-
if (node.title) {
|
|
49599
|
-
titleSvg = `<text x="20" y="30" font-size="18" font-weight="600" fill="${this.theme.colors.foreground}">${this.escapeXml(node.title)}</text>`;
|
|
49600
|
-
}
|
|
49601
|
-
const savedX = this.currentX;
|
|
49602
|
-
const savedY = this.currentY;
|
|
49603
|
-
this.currentX = 20;
|
|
49604
|
-
this.currentY = 50;
|
|
49605
|
-
const children = node.children.map((c) => this.renderNode(c)).join("\n");
|
|
49606
|
-
this.currentX = savedX;
|
|
49607
|
-
this.currentY = savedY;
|
|
49608
|
-
return `
|
|
49609
|
-
<g>
|
|
49610
|
-
<rect width="100%" height="100%" fill="rgba(0,0,0,0.5)" opacity="0.5"/>
|
|
49611
|
-
<g transform="translate(${x}, ${y})">
|
|
49612
|
-
<rect width="${width}" height="${height}" rx="8" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49613
|
-
${titleSvg}
|
|
49614
|
-
${children}
|
|
49615
|
-
</g>
|
|
49616
|
-
</g>`;
|
|
49617
|
-
}
|
|
49618
|
-
// ===========================================
|
|
49619
|
-
// Text Renderers
|
|
49620
|
-
// ===========================================
|
|
49621
|
-
renderText(node) {
|
|
49622
|
-
const fontSize = this.resolveFontSize(node.size);
|
|
49623
|
-
const fill = node.muted ? this.theme.colors.muted : this.theme.colors.foreground;
|
|
49624
|
-
const fontWeight = node.weight || "normal";
|
|
49625
|
-
const y = this.currentY + fontSize;
|
|
49626
|
-
this.currentY += fontSize + 8;
|
|
49627
|
-
return `<text x="${this.currentX}" y="${y}" font-size="${fontSize}" font-weight="${fontWeight}" fill="${fill}">${this.escapeXml(node.content)}</text>`;
|
|
49628
|
-
}
|
|
49629
|
-
renderTitle(node) {
|
|
49630
|
-
const level = node.level || 1;
|
|
49631
|
-
const fontSize = this.getTitleFontSize(level);
|
|
49632
|
-
const y = this.currentY + fontSize;
|
|
49633
|
-
this.currentY += fontSize + 12;
|
|
49634
|
-
return `<text x="${this.currentX}" y="${y}" font-size="${fontSize}" font-weight="600" fill="${this.theme.colors.foreground}">${this.escapeXml(node.content)}</text>`;
|
|
49635
|
-
}
|
|
49636
|
-
renderLink(node) {
|
|
49637
|
-
const fontSize = 14;
|
|
49638
|
-
const y = this.currentY + fontSize;
|
|
49639
|
-
this.currentY += fontSize + 8;
|
|
49640
|
-
return `<text x="${this.currentX}" y="${y}" font-size="${fontSize}" fill="${this.theme.colors.primary}" text-decoration="underline">${this.escapeXml(node.content)}</text>`;
|
|
49641
|
-
}
|
|
49642
|
-
// ===========================================
|
|
49643
|
-
// Input Renderers
|
|
49644
|
-
// ===========================================
|
|
49645
|
-
renderInput(node) {
|
|
49646
|
-
const width = 280;
|
|
49647
|
-
const height = 40;
|
|
49648
|
-
const x = this.currentX;
|
|
49649
|
-
let y = this.currentY;
|
|
49650
|
-
let result = "";
|
|
49651
|
-
if (node.label) {
|
|
49652
|
-
result += `<text x="${x}" y="${y + 14}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
49653
|
-
y += 24;
|
|
49654
|
-
}
|
|
49655
|
-
const placeholder = node.placeholder || "";
|
|
49656
|
-
result += `
|
|
49657
|
-
<g transform="translate(${x}, ${y})">
|
|
49658
|
-
<rect width="${width}" height="${height}" rx="4" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49659
|
-
<text x="12" y="${height / 2 + 5}" font-size="14" fill="${this.theme.colors.muted}">${this.escapeXml(placeholder)}</text>
|
|
49660
|
-
</g>`;
|
|
49661
|
-
this.currentY = y + height + 12;
|
|
49662
|
-
return result;
|
|
49663
|
-
}
|
|
49664
|
-
renderTextarea(node) {
|
|
49665
|
-
const width = 280;
|
|
49666
|
-
const height = 100;
|
|
49667
|
-
const x = this.currentX;
|
|
49668
|
-
let y = this.currentY;
|
|
49669
|
-
let result = "";
|
|
49670
|
-
if (node.label) {
|
|
49671
|
-
result += `<text x="${x}" y="${y + 14}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
49672
|
-
y += 24;
|
|
49673
|
-
}
|
|
49674
|
-
const placeholder = node.placeholder || "";
|
|
49675
|
-
result += `
|
|
49676
|
-
<g transform="translate(${x}, ${y})">
|
|
49677
|
-
<rect width="${width}" height="${height}" rx="4" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49678
|
-
<text x="12" y="24" font-size="14" fill="${this.theme.colors.muted}">${this.escapeXml(placeholder)}</text>
|
|
49679
|
-
</g>`;
|
|
49680
|
-
this.currentY = y + height + 12;
|
|
49681
|
-
return result;
|
|
49682
|
-
}
|
|
49683
|
-
renderSelect(node) {
|
|
49684
|
-
const width = 280;
|
|
49685
|
-
const height = 40;
|
|
49686
|
-
const x = this.currentX;
|
|
49687
|
-
let y = this.currentY;
|
|
49688
|
-
let result = "";
|
|
49689
|
-
if (node.label) {
|
|
49690
|
-
result += `<text x="${x}" y="${y + 14}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
49691
|
-
y += 24;
|
|
49692
|
-
}
|
|
49693
|
-
const placeholder = node.placeholder || "Select...";
|
|
49694
|
-
result += `
|
|
49695
|
-
<g transform="translate(${x}, ${y})">
|
|
49696
|
-
<rect width="${width}" height="${height}" rx="4" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49697
|
-
<text x="12" y="${height / 2 + 5}" font-size="14" fill="${this.theme.colors.muted}">${this.escapeXml(placeholder)}</text>
|
|
49698
|
-
<path d="M${width - 24} ${height / 2 - 3} l6 6 l6 -6" fill="none" stroke="${this.theme.colors.muted}" stroke-width="1.5"/>
|
|
49699
|
-
</g>`;
|
|
49700
|
-
this.currentY = y + height + 12;
|
|
49701
|
-
return result;
|
|
49702
|
-
}
|
|
49703
|
-
renderCheckbox(node) {
|
|
49704
|
-
const x = this.currentX;
|
|
49705
|
-
const y = this.currentY;
|
|
49706
|
-
const size = 18;
|
|
49707
|
-
let result = `
|
|
49708
|
-
<g transform="translate(${x}, ${y})">
|
|
49709
|
-
<rect width="${size}" height="${size}" rx="3" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
49710
|
-
if (node.checked) {
|
|
49711
|
-
result += `<path d="M4 9 L7 12 L14 5" fill="none" stroke="${this.theme.colors.foreground}" stroke-width="2"/>`;
|
|
49712
|
-
}
|
|
49713
|
-
if (node.label) {
|
|
49714
|
-
result += `<text x="${size + 8}" y="${size - 3}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
49715
|
-
}
|
|
49716
|
-
result += "</g>";
|
|
49717
|
-
this.currentY += size + 12;
|
|
49718
|
-
return result;
|
|
49719
|
-
}
|
|
49720
|
-
renderRadio(node) {
|
|
49721
|
-
const x = this.currentX;
|
|
49722
|
-
const y = this.currentY;
|
|
49723
|
-
const size = 18;
|
|
49724
|
-
const radius = size / 2;
|
|
49725
|
-
let result = `
|
|
49726
|
-
<g transform="translate(${x}, ${y})">
|
|
49727
|
-
<circle cx="${radius}" cy="${radius}" r="${radius - 1}" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
49728
|
-
if (node.checked) {
|
|
49729
|
-
result += `<circle cx="${radius}" cy="${radius}" r="${radius - 5}" fill="${this.theme.colors.foreground}"/>`;
|
|
49730
|
-
}
|
|
49731
|
-
if (node.label) {
|
|
49732
|
-
result += `<text x="${size + 8}" y="${size - 3}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
49733
|
-
}
|
|
49734
|
-
result += "</g>";
|
|
49735
|
-
this.currentY += size + 12;
|
|
49736
|
-
return result;
|
|
49737
|
-
}
|
|
49738
|
-
renderSwitch(node) {
|
|
49739
|
-
const x = this.currentX;
|
|
49740
|
-
const y = this.currentY;
|
|
49741
|
-
const width = 44;
|
|
49742
|
-
const height = 24;
|
|
49743
|
-
const radius = height / 2;
|
|
49744
|
-
const isOn = node.checked;
|
|
49745
|
-
const bgColor = isOn ? this.theme.colors.primary : this.theme.colors.border;
|
|
49746
|
-
const knobX = isOn ? width - radius : radius;
|
|
49747
|
-
let result = `
|
|
49748
|
-
<g transform="translate(${x}, ${y})">
|
|
49749
|
-
<rect width="${width}" height="${height}" rx="${radius}" fill="${bgColor}"/>
|
|
49750
|
-
<circle cx="${knobX}" cy="${radius}" r="${radius - 3}" fill="white"/>`;
|
|
49751
|
-
if (node.label) {
|
|
49752
|
-
result += `<text x="${width + 8}" y="${height - 6}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
49753
|
-
}
|
|
49754
|
-
result += "</g>";
|
|
49755
|
-
this.currentY += height + 12;
|
|
49756
|
-
return result;
|
|
49757
|
-
}
|
|
49758
|
-
// ===========================================
|
|
49759
|
-
// Button Renderer
|
|
49760
|
-
// ===========================================
|
|
49761
|
-
renderButton(node) {
|
|
49762
|
-
const content = node.content;
|
|
49763
|
-
const hasIcon = !!node.icon;
|
|
49764
|
-
const isIconOnly = hasIcon && !content.trim();
|
|
49765
|
-
const iconSize = 16;
|
|
49766
|
-
const padding = isIconOnly ? 8 : 16;
|
|
49767
|
-
let width;
|
|
49768
|
-
if (isIconOnly) {
|
|
49769
|
-
width = iconSize + padding * 2;
|
|
49770
|
-
} else if (hasIcon) {
|
|
49771
|
-
width = Math.max(80, content.length * 10 + iconSize + 40);
|
|
49772
|
-
} else {
|
|
49773
|
-
width = Math.max(80, content.length * 10 + 32);
|
|
49774
|
-
}
|
|
49775
|
-
const height = 36;
|
|
49776
|
-
const x = this.currentX;
|
|
49777
|
-
const y = this.currentY;
|
|
49778
|
-
let fill = this.theme.colors.primary;
|
|
49779
|
-
let textFill = "#ffffff";
|
|
49780
|
-
let isOutline = false;
|
|
49781
|
-
if (node.secondary) {
|
|
49782
|
-
fill = this.theme.colors.secondary;
|
|
49783
|
-
} else if (node.outline) {
|
|
49784
|
-
fill = "white";
|
|
49785
|
-
textFill = this.theme.colors.foreground;
|
|
49786
|
-
isOutline = true;
|
|
49787
|
-
} else if (node.ghost) {
|
|
49788
|
-
fill = "transparent";
|
|
49789
|
-
textFill = this.theme.colors.foreground;
|
|
49790
|
-
}
|
|
49791
|
-
this.currentY += height + 8;
|
|
49792
|
-
const strokeAttr = isOutline ? `stroke="${this.theme.colors.border}" stroke-width="1"` : "";
|
|
49793
|
-
let iconSvg = "";
|
|
49794
|
-
if (hasIcon) {
|
|
49795
|
-
const iconData = getIconData(node.icon);
|
|
49796
|
-
if (iconData) {
|
|
49797
|
-
const iconX = isIconOnly ? (width - iconSize) / 2 : padding;
|
|
49798
|
-
const iconY = (height - iconSize) / 2;
|
|
49799
|
-
iconSvg = this.renderIconPaths(iconData, iconX, iconY, iconSize, textFill);
|
|
49800
|
-
}
|
|
49801
|
-
}
|
|
49802
|
-
const textX = hasIcon && !isIconOnly ? padding + iconSize + 8 + (width - padding - iconSize - 8 - padding) / 2 : width / 2;
|
|
49803
|
-
const textContent = isIconOnly ? "" : `<text x="${textX}" y="${height / 2 + 5}" font-size="14" fill="${textFill}" text-anchor="middle">${this.escapeXml(content)}</text>`;
|
|
49804
|
-
return `
|
|
49805
|
-
<g transform="translate(${x}, ${y})">
|
|
49806
|
-
<rect width="${width}" height="${height}" rx="4" fill="${fill}" ${strokeAttr}/>
|
|
49807
|
-
${iconSvg}
|
|
49808
|
-
${textContent}
|
|
49809
|
-
</g>`;
|
|
49810
|
-
}
|
|
49811
|
-
/**
|
|
49812
|
-
* Render icon paths for SVG
|
|
49813
|
-
*/
|
|
49814
|
-
renderIconPaths(data, x, y, size, color) {
|
|
49815
|
-
const scale = size / 24;
|
|
49816
|
-
const paths = data.map(([tag, attrs]) => {
|
|
49817
|
-
const attrStr = Object.entries(attrs).map(([key, value]) => `${key}="${value}"`).join(" ");
|
|
49818
|
-
return `<${tag} ${attrStr} />`;
|
|
49819
|
-
}).join("");
|
|
49820
|
-
return `<g transform="translate(${x}, ${y}) scale(${scale})" fill="none" stroke="${color}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${paths}</g>`;
|
|
49821
|
-
}
|
|
49822
|
-
// ===========================================
|
|
49823
|
-
// Display Renderers
|
|
49824
|
-
// ===========================================
|
|
49825
|
-
renderImage(node) {
|
|
49826
|
-
const width = node.w && typeof node.w === "number" ? node.w : 200;
|
|
49827
|
-
const height = node.h && typeof node.h === "number" ? node.h : 150;
|
|
49828
|
-
const x = this.currentX;
|
|
49829
|
-
const y = this.currentY;
|
|
49830
|
-
this.currentY += height + 12;
|
|
49831
|
-
return `
|
|
49832
|
-
<g transform="translate(${x}, ${y})">
|
|
49833
|
-
<rect width="${width}" height="${height}" fill="${this.theme.colors.muted}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49834
|
-
<line x1="0" y1="0" x2="${width}" y2="${height}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49835
|
-
<line x1="${width}" y1="0" x2="0" y2="${height}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49836
|
-
<text x="${width / 2}" y="${height / 2 + 5}" font-size="14" fill="${this.theme.colors.foreground}" text-anchor="middle">${this.escapeXml(node.alt || "Image")}</text>
|
|
49837
|
-
</g>`;
|
|
49838
|
-
}
|
|
49839
|
-
renderPlaceholder(node) {
|
|
49840
|
-
const width = node.w && typeof node.w === "number" ? node.w : 200;
|
|
49841
|
-
const height = node.h && typeof node.h === "number" ? node.h : 100;
|
|
49842
|
-
const x = this.currentX;
|
|
49843
|
-
const y = this.currentY;
|
|
49844
|
-
this.currentY += height + 12;
|
|
49845
|
-
return `
|
|
49846
|
-
<g transform="translate(${x}, ${y})">
|
|
49847
|
-
<rect width="${width}" height="${height}" fill="${this.theme.colors.muted}" stroke="${this.theme.colors.border}" stroke-width="1" stroke-dasharray="4,4"/>
|
|
49848
|
-
<text x="${width / 2}" y="${height / 2 + 5}" font-size="14" fill="${this.theme.colors.foreground}" text-anchor="middle">${this.escapeXml(node.label || "Placeholder")}</text>
|
|
49849
|
-
</g>`;
|
|
49850
|
-
}
|
|
49851
|
-
renderAvatar(node) {
|
|
49852
|
-
const sizes = { xs: 24, sm: 32, md: 40, lg: 48, xl: 64 };
|
|
49853
|
-
const size = sizes[node.size || "md"] || 40;
|
|
49854
|
-
const radius = size / 2;
|
|
49855
|
-
const x = this.currentX;
|
|
49856
|
-
const y = this.currentY;
|
|
49857
|
-
const initial = node.name ? node.name.charAt(0).toUpperCase() : "?";
|
|
49858
|
-
this.currentY += size + 12;
|
|
49859
|
-
return `
|
|
49860
|
-
<g transform="translate(${x}, ${y})">
|
|
49861
|
-
<circle cx="${radius}" cy="${radius}" r="${radius}" fill="${this.theme.colors.muted}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49862
|
-
<text x="${radius}" y="${radius + 5}" font-size="${size / 2.5}" fill="${this.theme.colors.foreground}" text-anchor="middle">${initial}</text>
|
|
49863
|
-
</g>`;
|
|
49864
|
-
}
|
|
49865
|
-
renderBadge(node) {
|
|
49866
|
-
const content = node.content;
|
|
49867
|
-
const width = Math.max(24, content.length * 8 + 16);
|
|
49868
|
-
const height = 22;
|
|
49869
|
-
const x = this.currentX;
|
|
49870
|
-
const y = this.currentY;
|
|
49871
|
-
const fill = this.theme.colors.muted;
|
|
49872
|
-
const textFill = this.theme.colors.foreground;
|
|
49873
|
-
this.currentY += height + 8;
|
|
49874
|
-
return `
|
|
49875
|
-
<g transform="translate(${x}, ${y})">
|
|
49876
|
-
<rect width="${width}" height="${height}" rx="11" fill="${fill}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49877
|
-
<text x="${width / 2}" y="${height / 2 + 4}" font-size="12" fill="${textFill}" text-anchor="middle">${this.escapeXml(content)}</text>
|
|
49878
|
-
</g>`;
|
|
49879
|
-
}
|
|
49880
|
-
// ===========================================
|
|
49881
|
-
// Data Renderers
|
|
49882
|
-
// ===========================================
|
|
49883
|
-
renderTable(node) {
|
|
49884
|
-
const columns = node.columns || [];
|
|
49885
|
-
const rows = node.rows || [];
|
|
49886
|
-
const rowCount = rows.length || 3;
|
|
49887
|
-
const colWidth = 120;
|
|
49888
|
-
const rowHeight = 40;
|
|
49889
|
-
const x = this.currentX;
|
|
49890
|
-
const y = this.currentY;
|
|
49891
|
-
let svg = `<g transform="translate(${x}, ${y})">`;
|
|
49892
|
-
svg += `<rect width="${columns.length * colWidth}" height="${rowHeight}" fill="${this.theme.colors.muted}"/>`;
|
|
49893
|
-
columns.forEach((col, i) => {
|
|
49894
|
-
svg += `<text x="${i * colWidth + 12}" y="${rowHeight / 2 + 5}" font-size="14" font-weight="600">${this.escapeXml(col)}</text>`;
|
|
49895
|
-
});
|
|
49896
|
-
const displayRowCount = rows.length > 0 ? rows.length : Math.max(rowCount, 3);
|
|
49897
|
-
for (let rowIdx = 0; rowIdx < displayRowCount; rowIdx++) {
|
|
49898
|
-
const rowY = (rowIdx + 1) * rowHeight;
|
|
49899
|
-
svg += `<rect y="${rowY}" width="${columns.length * colWidth}" height="${rowHeight}" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
49900
|
-
columns.forEach((_, colIdx) => {
|
|
49901
|
-
const cellContent = rows[rowIdx] && rows[rowIdx][colIdx] ? String(typeof rows[rowIdx][colIdx] === "object" ? "..." : rows[rowIdx][colIdx]) : "\u2014";
|
|
49902
|
-
svg += `<text x="${colIdx * colWidth + 12}" y="${rowY + rowHeight / 2 + 5}" font-size="14" fill="${this.theme.colors.muted}">${this.escapeXml(cellContent)}</text>`;
|
|
49903
|
-
});
|
|
49904
|
-
}
|
|
49905
|
-
svg += "</g>";
|
|
49906
|
-
this.currentY += (displayRowCount + 1) * rowHeight + 16;
|
|
49907
|
-
return svg;
|
|
49908
|
-
}
|
|
49909
|
-
renderList(node) {
|
|
49910
|
-
const x = this.currentX;
|
|
49911
|
-
let y = this.currentY;
|
|
49912
|
-
const items = node.items || [];
|
|
49913
|
-
const ordered = node.ordered || false;
|
|
49914
|
-
let svg = `<g transform="translate(${x}, ${y})">`;
|
|
49915
|
-
items.forEach((item, idx) => {
|
|
49916
|
-
const marker = ordered ? `${idx + 1}.` : "\u2022";
|
|
49917
|
-
const content = typeof item === "string" ? item : item.content;
|
|
49918
|
-
svg += `<text x="0" y="${idx * 24 + 16}" font-size="14" fill="${this.theme.colors.foreground}">${marker} ${this.escapeXml(content)}</text>`;
|
|
49919
|
-
});
|
|
49920
|
-
svg += "</g>";
|
|
49921
|
-
this.currentY += items.length * 24 + 12;
|
|
49922
|
-
return svg;
|
|
49923
|
-
}
|
|
49924
|
-
// ===========================================
|
|
49925
|
-
// Feedback Renderers
|
|
49926
|
-
// ===========================================
|
|
49927
|
-
renderAlert(node) {
|
|
49928
|
-
const width = Math.min(400, this.contentWidth);
|
|
49929
|
-
const height = 48;
|
|
49930
|
-
const x = this.currentX;
|
|
49931
|
-
const y = this.currentY;
|
|
49932
|
-
this.currentY += height + 12;
|
|
49933
|
-
return `
|
|
49934
|
-
<g transform="translate(${x}, ${y})">
|
|
49935
|
-
<rect width="${width}" height="${height}" rx="4" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49936
|
-
<text x="16" y="${height / 2 + 5}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.content)}</text>
|
|
49937
|
-
</g>`;
|
|
49938
|
-
}
|
|
49939
|
-
renderProgress(node) {
|
|
49940
|
-
const width = 200;
|
|
49941
|
-
const height = 8;
|
|
49942
|
-
const x = this.currentX;
|
|
49943
|
-
let y = this.currentY;
|
|
49944
|
-
let result = "";
|
|
49945
|
-
if (node.label) {
|
|
49946
|
-
result += `<text x="${x}" y="${y + 14}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
49947
|
-
y += 24;
|
|
49948
|
-
}
|
|
49949
|
-
const value = node.value || 0;
|
|
49950
|
-
const max = node.max || 100;
|
|
49951
|
-
const percent = Math.min(100, Math.max(0, value / max * 100));
|
|
49952
|
-
result += `
|
|
49953
|
-
<g transform="translate(${x}, ${y})">
|
|
49954
|
-
<rect width="${width}" height="${height}" rx="${height / 2}" fill="${this.theme.colors.muted}"/>
|
|
49955
|
-
<rect width="${width * percent / 100}" height="${height}" rx="${height / 2}" fill="${this.theme.colors.primary}"/>
|
|
49956
|
-
</g>`;
|
|
49957
|
-
this.currentY = y + height + 12;
|
|
49958
|
-
return result;
|
|
49959
|
-
}
|
|
49960
|
-
renderSpinner(node) {
|
|
49961
|
-
const sizes = { xs: 16, sm: 20, md: 24, lg: 32, xl: 40 };
|
|
49962
|
-
const size = sizes[node.size || "md"] || 24;
|
|
49963
|
-
const x = this.currentX + size / 2;
|
|
49964
|
-
const y = this.currentY + size / 2;
|
|
49965
|
-
const radius = size / 2 - 2;
|
|
49966
|
-
this.currentY += size + 12;
|
|
49967
|
-
return `
|
|
49968
|
-
<g transform="translate(${x}, ${y})">
|
|
49969
|
-
<circle r="${radius}" fill="none" stroke="${this.theme.colors.muted}" stroke-width="2"/>
|
|
49970
|
-
<path d="M0,-${radius} A${radius},${radius} 0 0,1 ${radius},0" fill="none" stroke="${this.theme.colors.primary}" stroke-width="2" stroke-linecap="round"/>
|
|
49971
|
-
</g>`;
|
|
49972
|
-
}
|
|
49973
|
-
// ===========================================
|
|
49974
|
-
// Navigation Renderers
|
|
49975
|
-
// ===========================================
|
|
49976
|
-
renderNav(node) {
|
|
49977
|
-
const items = node.items || [];
|
|
49978
|
-
const x = this.currentX;
|
|
49979
|
-
const y = this.currentY;
|
|
49980
|
-
const vertical = node.vertical || false;
|
|
49981
|
-
let svg = `<g transform="translate(${x}, ${y})">`;
|
|
49982
|
-
if (vertical) {
|
|
49983
|
-
items.forEach((item, idx) => {
|
|
49984
|
-
const label = typeof item === "string" ? item : item.label;
|
|
49985
|
-
const isActive = typeof item === "object" && item.active;
|
|
49986
|
-
const fill = isActive ? this.theme.colors.foreground : this.theme.colors.muted;
|
|
49987
|
-
svg += `<text x="0" y="${idx * 32 + 16}" font-size="14" fill="${fill}">${this.escapeXml(label)}</text>`;
|
|
49988
|
-
});
|
|
49989
|
-
this.currentY += items.length * 32 + 12;
|
|
49990
|
-
} else {
|
|
49991
|
-
let offsetX = 0;
|
|
49992
|
-
items.forEach((item) => {
|
|
49993
|
-
const label = typeof item === "string" ? item : item.label;
|
|
49994
|
-
const isActive = typeof item === "object" && item.active;
|
|
49995
|
-
const fill = isActive ? this.theme.colors.foreground : this.theme.colors.muted;
|
|
49996
|
-
svg += `<text x="${offsetX}" y="16" font-size="14" fill="${fill}">${this.escapeXml(label)}</text>`;
|
|
49997
|
-
offsetX += label.length * 8 + 24;
|
|
49998
|
-
});
|
|
49999
|
-
this.currentY += 32;
|
|
50000
|
-
}
|
|
50001
|
-
svg += "</g>";
|
|
50002
|
-
return svg;
|
|
50003
|
-
}
|
|
50004
|
-
renderTabs(node) {
|
|
50005
|
-
const items = node.items || [];
|
|
50006
|
-
const x = this.currentX;
|
|
50007
|
-
const y = this.currentY;
|
|
50008
|
-
const tabHeight = 40;
|
|
50009
|
-
let svg = `<g transform="translate(${x}, ${y})">`;
|
|
50010
|
-
let offsetX = 0;
|
|
50011
|
-
items.forEach((item) => {
|
|
50012
|
-
const label = typeof item === "string" ? item : item;
|
|
50013
|
-
const tabWidth = label.length * 10 + 24;
|
|
50014
|
-
svg += `<rect x="${offsetX}" width="${tabWidth}" height="${tabHeight}" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
50015
|
-
svg += `<text x="${offsetX + tabWidth / 2}" y="${tabHeight / 2 + 5}" font-size="14" text-anchor="middle">${this.escapeXml(label)}</text>`;
|
|
50016
|
-
offsetX += tabWidth;
|
|
50017
|
-
});
|
|
50018
|
-
svg += "</g>";
|
|
50019
|
-
this.currentY += tabHeight + 12;
|
|
50020
|
-
return svg;
|
|
50021
|
-
}
|
|
50022
|
-
renderBreadcrumb(node) {
|
|
50023
|
-
const items = node.items || [];
|
|
50024
|
-
const separator = "/";
|
|
50025
|
-
const x = this.currentX;
|
|
50026
|
-
const y = this.currentY;
|
|
50027
|
-
let svg = `<g transform="translate(${x}, ${y})">`;
|
|
50028
|
-
let offsetX = 0;
|
|
50029
|
-
items.forEach((item, idx) => {
|
|
50030
|
-
const label = typeof item === "string" ? item : item.label;
|
|
50031
|
-
const isLast = idx === items.length - 1;
|
|
50032
|
-
const fill = isLast ? this.theme.colors.foreground : this.theme.colors.muted;
|
|
50033
|
-
svg += `<text x="${offsetX}" y="16" font-size="14" fill="${fill}">${this.escapeXml(label)}</text>`;
|
|
50034
|
-
offsetX += label.length * 8 + 8;
|
|
50035
|
-
if (!isLast) {
|
|
50036
|
-
svg += `<text x="${offsetX}" y="16" font-size="14" fill="${this.theme.colors.muted}">${separator}</text>`;
|
|
50037
|
-
offsetX += 16;
|
|
50038
|
-
}
|
|
50039
|
-
});
|
|
50040
|
-
svg += "</g>";
|
|
50041
|
-
this.currentY += 28;
|
|
50042
|
-
return svg;
|
|
50043
|
-
}
|
|
50044
|
-
// ===========================================
|
|
50045
|
-
// Utility Methods
|
|
50046
|
-
// ===========================================
|
|
50047
|
-
getFontSize(size) {
|
|
50048
|
-
const sizes = {
|
|
50049
|
-
xs: 12,
|
|
50050
|
-
sm: 14,
|
|
50051
|
-
base: 16,
|
|
50052
|
-
md: 16,
|
|
50053
|
-
lg: 18,
|
|
50054
|
-
xl: 20,
|
|
50055
|
-
"2xl": 24,
|
|
50056
|
-
"3xl": 30
|
|
50057
|
-
};
|
|
50058
|
-
return sizes[size] || 16;
|
|
50059
|
-
}
|
|
50060
|
-
resolveFontSize(size) {
|
|
50061
|
-
if (!size) return 16;
|
|
50062
|
-
if (typeof size === "string") {
|
|
50063
|
-
return this.getFontSize(size);
|
|
50064
|
-
}
|
|
50065
|
-
if (typeof size === "object" && "value" in size) {
|
|
50066
|
-
if (size.unit === "px") return size.value;
|
|
50067
|
-
if (size.unit === "rem") return size.value * 16;
|
|
50068
|
-
if (size.unit === "em") return size.value * 16;
|
|
50069
|
-
return size.value;
|
|
50070
|
-
}
|
|
50071
|
-
return 16;
|
|
50072
|
-
}
|
|
50073
|
-
getTitleFontSize(level) {
|
|
50074
|
-
const sizes = {
|
|
50075
|
-
1: 32,
|
|
50076
|
-
2: 28,
|
|
50077
|
-
3: 24,
|
|
50078
|
-
4: 20,
|
|
50079
|
-
5: 18,
|
|
50080
|
-
6: 16
|
|
50081
|
-
};
|
|
50082
|
-
return sizes[level] || 24;
|
|
50083
|
-
}
|
|
50084
|
-
escapeXml(str) {
|
|
50085
|
-
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
50086
|
-
}
|
|
50087
|
-
};
|
|
50088
|
-
function createSvgRenderer(options) {
|
|
50089
|
-
return new SvgRenderer(options);
|
|
50090
|
-
}
|
|
50091
|
-
function renderToSvg(doc, options) {
|
|
50092
|
-
const renderer = new SvgRenderer(options);
|
|
50093
|
-
return renderer.render(doc);
|
|
50094
|
-
}
|
|
50095
|
-
|
|
50096
49669
|
// src/renderer/index.ts
|
|
50097
49670
|
function render(document, options = {}) {
|
|
50098
49671
|
const renderer = createHtmlRenderer(options);
|
|
@@ -50129,7 +49702,7 @@ ${html}
|
|
|
50129
49702
|
</body>
|
|
50130
49703
|
</html>`;
|
|
50131
49704
|
}
|
|
50132
|
-
function
|
|
49705
|
+
function renderToSvg(document, options = {}) {
|
|
50133
49706
|
const firstPage = document.children[0];
|
|
50134
49707
|
let width = options.width ?? 800;
|
|
50135
49708
|
let height = options.height ?? 600;
|
|
@@ -50140,15 +49713,22 @@ function renderToSvg2(document, options = {}) {
|
|
|
50140
49713
|
height = viewport.height;
|
|
50141
49714
|
}
|
|
50142
49715
|
}
|
|
50143
|
-
const padding = options.padding ?? 20;
|
|
50144
49716
|
const background = options.background ?? "#ffffff";
|
|
50145
49717
|
const { html, css } = render(document, { theme: "light" });
|
|
50146
49718
|
const svg = `<?xml version="1.0" encoding="UTF-8"?>
|
|
50147
49719
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
50148
49720
|
viewBox="0 0 ${width} ${height}" width="${width}" height="${height}">
|
|
50149
49721
|
<rect width="100%" height="100%" fill="${background}"/>
|
|
50150
|
-
<foreignObject x="
|
|
50151
|
-
<div xmlns="http://www.w3.org/1999/xhtml" style="
|
|
49722
|
+
<foreignObject x="0" y="0" width="${width}" height="${height}">
|
|
49723
|
+
<div xmlns="http://www.w3.org/1999/xhtml" style="
|
|
49724
|
+
width: ${width}px;
|
|
49725
|
+
height: ${height}px;
|
|
49726
|
+
overflow: hidden;
|
|
49727
|
+
display: flex;
|
|
49728
|
+
justify-content: center;
|
|
49729
|
+
align-items: center;
|
|
49730
|
+
box-sizing: border-box;
|
|
49731
|
+
">
|
|
50152
49732
|
<style type="text/css">
|
|
50153
49733
|
${css}
|
|
50154
49734
|
</style>
|
|
@@ -50158,14 +49738,9 @@ ${css}
|
|
|
50158
49738
|
</svg>`;
|
|
50159
49739
|
return { svg, width, height };
|
|
50160
49740
|
}
|
|
50161
|
-
function renderToPureSvg(document, options = {}) {
|
|
50162
|
-
return renderToSvg(document, options);
|
|
50163
|
-
}
|
|
50164
49741
|
export {
|
|
50165
49742
|
HtmlRenderer,
|
|
50166
|
-
SvgRenderer,
|
|
50167
49743
|
createHtmlRenderer,
|
|
50168
|
-
createSvgRenderer,
|
|
50169
49744
|
darkTheme,
|
|
50170
49745
|
defaultTheme,
|
|
50171
49746
|
generateComponentStyles,
|
|
@@ -50176,8 +49751,7 @@ export {
|
|
|
50176
49751
|
render,
|
|
50177
49752
|
renderIconSvg,
|
|
50178
49753
|
renderToHtml,
|
|
50179
|
-
|
|
50180
|
-
renderToSvg2 as renderToSvg
|
|
49754
|
+
renderToSvg
|
|
50181
49755
|
};
|
|
50182
49756
|
/**
|
|
50183
49757
|
* Lucide Icons Data
|