@wireweave/core 1.1.0 → 1.2.0-beta.1
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 +2 -1
package/dist/renderer.cjs
CHANGED
|
@@ -21,9 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var renderer_exports = {};
|
|
22
22
|
__export(renderer_exports, {
|
|
23
23
|
HtmlRenderer: () => HtmlRenderer,
|
|
24
|
-
SvgRenderer: () => SvgRenderer,
|
|
25
24
|
createHtmlRenderer: () => createHtmlRenderer,
|
|
26
|
-
createSvgRenderer: () => createSvgRenderer,
|
|
27
25
|
darkTheme: () => darkTheme,
|
|
28
26
|
defaultTheme: () => defaultTheme,
|
|
29
27
|
generateComponentStyles: () => generateComponentStyles,
|
|
@@ -34,8 +32,7 @@ __export(renderer_exports, {
|
|
|
34
32
|
render: () => render,
|
|
35
33
|
renderIconSvg: () => renderIconSvg,
|
|
36
34
|
renderToHtml: () => renderToHtml,
|
|
37
|
-
|
|
38
|
-
renderToSvg: () => renderToSvg2
|
|
35
|
+
renderToSvg: () => renderToSvg
|
|
39
36
|
});
|
|
40
37
|
module.exports = __toCommonJS(renderer_exports);
|
|
41
38
|
|
|
@@ -92,23 +89,7 @@ function getTheme(name) {
|
|
|
92
89
|
return name === "dark" ? darkTheme : defaultTheme;
|
|
93
90
|
}
|
|
94
91
|
|
|
95
|
-
// src/renderer/styles
|
|
96
|
-
function generateComponentStyles(_theme, prefix = "wf") {
|
|
97
|
-
const parts = [
|
|
98
|
-
generateContainerStyles(prefix),
|
|
99
|
-
generateTextStyles(prefix),
|
|
100
|
-
generateInputStyles(_theme, prefix),
|
|
101
|
-
generateButtonStyles(_theme, prefix),
|
|
102
|
-
generateDisplayStyles(_theme, prefix),
|
|
103
|
-
generateDataStyles(_theme, prefix),
|
|
104
|
-
generateFeedbackStyles(_theme, prefix),
|
|
105
|
-
generateOverlayStyles(_theme, prefix),
|
|
106
|
-
generateNavigationStyles(_theme, prefix),
|
|
107
|
-
generateSemanticMarkerStyles(_theme, prefix),
|
|
108
|
-
generateAccessibilityStyles(prefix)
|
|
109
|
-
];
|
|
110
|
-
return parts.join("\n\n");
|
|
111
|
-
}
|
|
92
|
+
// src/renderer/styles/container.ts
|
|
112
93
|
function generateContainerStyles(prefix) {
|
|
113
94
|
return `/* Container Components */
|
|
114
95
|
.${prefix}-card {
|
|
@@ -118,12 +99,17 @@ function generateContainerStyles(prefix) {
|
|
|
118
99
|
padding: 16px;
|
|
119
100
|
}
|
|
120
101
|
|
|
121
|
-
/* Cards in flex rows
|
|
102
|
+
/* Cards in flex rows: respect explicit width, shrink if needed */
|
|
122
103
|
.${prefix}-row > .${prefix}-card {
|
|
123
|
-
flex:
|
|
104
|
+
flex: 0 1 auto;
|
|
124
105
|
min-width: 0;
|
|
125
106
|
}
|
|
126
107
|
|
|
108
|
+
/* Cards without explicit width should expand to fill space */
|
|
109
|
+
.${prefix}-row > .${prefix}-card-flex {
|
|
110
|
+
flex: 1 1 0%;
|
|
111
|
+
}
|
|
112
|
+
|
|
127
113
|
.${prefix}-card-title {
|
|
128
114
|
margin: 0 0 12px 0;
|
|
129
115
|
font-size: 18px;
|
|
@@ -243,6 +229,8 @@ function generateContainerStyles(prefix) {
|
|
|
243
229
|
padding: 16px;
|
|
244
230
|
}`;
|
|
245
231
|
}
|
|
232
|
+
|
|
233
|
+
// src/renderer/styles/text.ts
|
|
246
234
|
function generateTextStyles(prefix) {
|
|
247
235
|
return `/* Text Components */
|
|
248
236
|
.${prefix}-text {
|
|
@@ -277,6 +265,11 @@ function generateTextStyles(prefix) {
|
|
|
277
265
|
line-height: 1.25;
|
|
278
266
|
}
|
|
279
267
|
|
|
268
|
+
/* Remove bottom margin when title is in a row (inline with other elements) */
|
|
269
|
+
.${prefix}-row .${prefix}-title {
|
|
270
|
+
margin-bottom: 0;
|
|
271
|
+
}
|
|
272
|
+
|
|
280
273
|
h1.${prefix}-title { font-size: 36px; }
|
|
281
274
|
h2.${prefix}-title { font-size: 30px; }
|
|
282
275
|
h3.${prefix}-title { font-size: 24px; }
|
|
@@ -294,6 +287,8 @@ h6.${prefix}-title { font-size: 16px; }
|
|
|
294
287
|
opacity: 0.7;
|
|
295
288
|
}`;
|
|
296
289
|
}
|
|
290
|
+
|
|
291
|
+
// src/renderer/styles/input.ts
|
|
297
292
|
function generateInputStyles(_theme, prefix) {
|
|
298
293
|
return `/* Input Components */
|
|
299
294
|
.${prefix}-form-field {
|
|
@@ -493,6 +488,8 @@ function generateInputStyles(_theme, prefix) {
|
|
|
493
488
|
cursor: pointer;
|
|
494
489
|
}`;
|
|
495
490
|
}
|
|
491
|
+
|
|
492
|
+
// src/renderer/styles/button.ts
|
|
496
493
|
function generateButtonStyles(_theme, prefix) {
|
|
497
494
|
return `/* Button Components */
|
|
498
495
|
.${prefix}-button {
|
|
@@ -620,6 +617,8 @@ function generateButtonStyles(_theme, prefix) {
|
|
|
620
617
|
.${prefix}-button.${prefix}-justify-end { justify-content: flex-end; }
|
|
621
618
|
.${prefix}-button.${prefix}-justify-between { justify-content: space-between; }`;
|
|
622
619
|
}
|
|
620
|
+
|
|
621
|
+
// src/renderer/styles/display.ts
|
|
623
622
|
function generateDisplayStyles(_theme, prefix) {
|
|
624
623
|
return `/* Display Components */
|
|
625
624
|
.${prefix}-image {
|
|
@@ -671,6 +670,30 @@ img.${prefix}-image {
|
|
|
671
670
|
font-size: 14px;
|
|
672
671
|
}
|
|
673
672
|
|
|
673
|
+
.${prefix}-placeholder-with-children {
|
|
674
|
+
position: relative;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
.${prefix}-placeholder-label {
|
|
678
|
+
position: absolute;
|
|
679
|
+
top: 50%;
|
|
680
|
+
left: 50%;
|
|
681
|
+
transform: translate(-50%, -50%);
|
|
682
|
+
z-index: 0;
|
|
683
|
+
pointer-events: none;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
.${prefix}-placeholder-overlay {
|
|
687
|
+
position: absolute;
|
|
688
|
+
top: 0;
|
|
689
|
+
left: 0;
|
|
690
|
+
right: 0;
|
|
691
|
+
bottom: 0;
|
|
692
|
+
z-index: 1;
|
|
693
|
+
display: flex;
|
|
694
|
+
flex-direction: column;
|
|
695
|
+
}
|
|
696
|
+
|
|
674
697
|
.${prefix}-avatar {
|
|
675
698
|
display: inline-flex;
|
|
676
699
|
align-items: center;
|
|
@@ -786,12 +809,12 @@ svg.${prefix}-icon {
|
|
|
786
809
|
display: block;
|
|
787
810
|
}
|
|
788
811
|
|
|
789
|
-
/* Icon size tokens */
|
|
812
|
+
/* Icon size tokens - matches SVG renderer */
|
|
790
813
|
svg.${prefix}-icon-xs { width: 12px; height: 12px; }
|
|
791
|
-
svg.${prefix}-icon-sm { width:
|
|
792
|
-
svg.${prefix}-icon-md { width:
|
|
793
|
-
svg.${prefix}-icon-lg { width:
|
|
794
|
-
svg.${prefix}-icon-xl { width:
|
|
814
|
+
svg.${prefix}-icon-sm { width: 16px; height: 16px; }
|
|
815
|
+
svg.${prefix}-icon-md { width: 20px; height: 20px; }
|
|
816
|
+
svg.${prefix}-icon-lg { width: 24px; height: 24px; }
|
|
817
|
+
svg.${prefix}-icon-xl { width: 32px; height: 32px; }
|
|
795
818
|
|
|
796
819
|
.${prefix}-icon svg {
|
|
797
820
|
display: block;
|
|
@@ -803,6 +826,8 @@ svg.${prefix}-icon-xl { width: 24px; height: 24px; }
|
|
|
803
826
|
justify-content: center;
|
|
804
827
|
}`;
|
|
805
828
|
}
|
|
829
|
+
|
|
830
|
+
// src/renderer/styles/data.ts
|
|
806
831
|
function generateDataStyles(_theme, prefix) {
|
|
807
832
|
return `/* Data Components */
|
|
808
833
|
.${prefix}-table {
|
|
@@ -861,6 +886,8 @@ function generateDataStyles(_theme, prefix) {
|
|
|
861
886
|
border-bottom: none;
|
|
862
887
|
}`;
|
|
863
888
|
}
|
|
889
|
+
|
|
890
|
+
// src/renderer/styles/feedback.ts
|
|
864
891
|
function generateFeedbackStyles(_theme, prefix) {
|
|
865
892
|
return `/* Feedback Components */
|
|
866
893
|
.${prefix}-alert {
|
|
@@ -952,6 +979,8 @@ function generateFeedbackStyles(_theme, prefix) {
|
|
|
952
979
|
to { transform: rotate(360deg); }
|
|
953
980
|
}`;
|
|
954
981
|
}
|
|
982
|
+
|
|
983
|
+
// src/renderer/styles/overlay.ts
|
|
955
984
|
function generateOverlayStyles(_theme, prefix) {
|
|
956
985
|
return `/* Overlay Components */
|
|
957
986
|
.${prefix}-tooltip-wrapper {
|
|
@@ -1050,6 +1079,8 @@ function generateOverlayStyles(_theme, prefix) {
|
|
|
1050
1079
|
cursor: not-allowed;
|
|
1051
1080
|
}`;
|
|
1052
1081
|
}
|
|
1082
|
+
|
|
1083
|
+
// src/renderer/styles/navigation.ts
|
|
1053
1084
|
function generateNavigationStyles(_theme, prefix) {
|
|
1054
1085
|
return `/* Navigation Components */
|
|
1055
1086
|
.${prefix}-nav {
|
|
@@ -1087,6 +1118,27 @@ function generateNavigationStyles(_theme, prefix) {
|
|
|
1087
1118
|
cursor: not-allowed;
|
|
1088
1119
|
}
|
|
1089
1120
|
|
|
1121
|
+
.${prefix}-nav-group {
|
|
1122
|
+
display: flex;
|
|
1123
|
+
flex-direction: column;
|
|
1124
|
+
gap: 4px;
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
.${prefix}-nav-group-label {
|
|
1128
|
+
font-size: 11px;
|
|
1129
|
+
font-weight: 500;
|
|
1130
|
+
color: var(--${prefix}-muted);
|
|
1131
|
+
text-transform: uppercase;
|
|
1132
|
+
letter-spacing: 0.05em;
|
|
1133
|
+
padding: 8px 16px 4px;
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
.${prefix}-nav-divider {
|
|
1137
|
+
margin: 8px 0;
|
|
1138
|
+
border: none;
|
|
1139
|
+
border-top: 1px solid var(--${prefix}-border);
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1090
1142
|
.${prefix}-tabs {
|
|
1091
1143
|
border-bottom: 1px solid var(--${prefix}-border);
|
|
1092
1144
|
}
|
|
@@ -1141,6 +1193,8 @@ function generateNavigationStyles(_theme, prefix) {
|
|
|
1141
1193
|
color: var(--${prefix}-muted);
|
|
1142
1194
|
}`;
|
|
1143
1195
|
}
|
|
1196
|
+
|
|
1197
|
+
// src/renderer/styles/semantic.ts
|
|
1144
1198
|
function generateSemanticMarkerStyles(_theme, prefix) {
|
|
1145
1199
|
return `/* Semantic Markers */
|
|
1146
1200
|
|
|
@@ -1227,6 +1281,8 @@ function generateSemanticMarkerStyles(_theme, prefix) {
|
|
|
1227
1281
|
color: var(--${prefix}-muted);
|
|
1228
1282
|
}`;
|
|
1229
1283
|
}
|
|
1284
|
+
|
|
1285
|
+
// src/renderer/styles/accessibility.ts
|
|
1230
1286
|
function generateAccessibilityStyles(prefix) {
|
|
1231
1287
|
return `/* Accessibility Utilities */
|
|
1232
1288
|
.sr-only {
|
|
@@ -1264,6 +1320,24 @@ function generateAccessibilityStyles(prefix) {
|
|
|
1264
1320
|
}`;
|
|
1265
1321
|
}
|
|
1266
1322
|
|
|
1323
|
+
// src/renderer/styles-components.ts
|
|
1324
|
+
function generateComponentStyles(_theme, prefix = "wf") {
|
|
1325
|
+
const parts = [
|
|
1326
|
+
generateContainerStyles(prefix),
|
|
1327
|
+
generateTextStyles(prefix),
|
|
1328
|
+
generateInputStyles(_theme, prefix),
|
|
1329
|
+
generateButtonStyles(_theme, prefix),
|
|
1330
|
+
generateDisplayStyles(_theme, prefix),
|
|
1331
|
+
generateDataStyles(_theme, prefix),
|
|
1332
|
+
generateFeedbackStyles(_theme, prefix),
|
|
1333
|
+
generateOverlayStyles(_theme, prefix),
|
|
1334
|
+
generateNavigationStyles(_theme, prefix),
|
|
1335
|
+
generateSemanticMarkerStyles(_theme, prefix),
|
|
1336
|
+
generateAccessibilityStyles(prefix)
|
|
1337
|
+
];
|
|
1338
|
+
return parts.join("\n\n");
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1267
1341
|
// src/renderer/styles.ts
|
|
1268
1342
|
function generateStyles(theme, prefix = "wf") {
|
|
1269
1343
|
const parts = [
|
|
@@ -1304,7 +1378,6 @@ function generateBaseStyles(prefix) {
|
|
|
1304
1378
|
font-family: var(--${prefix}-font);
|
|
1305
1379
|
color: var(--${prefix}-fg);
|
|
1306
1380
|
background: var(--${prefix}-bg);
|
|
1307
|
-
min-height: 100vh;
|
|
1308
1381
|
box-sizing: border-box;
|
|
1309
1382
|
position: relative;
|
|
1310
1383
|
display: flex;
|
|
@@ -1315,10 +1388,19 @@ function generateBaseStyles(prefix) {
|
|
|
1315
1388
|
overflow: hidden;
|
|
1316
1389
|
}
|
|
1317
1390
|
|
|
1391
|
+
/* Col direct child of page should fill page height */
|
|
1392
|
+
.${prefix}-page > .${prefix}-col {
|
|
1393
|
+
flex: 1;
|
|
1394
|
+
min-height: 0;
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1318
1397
|
/* Row containing sidebar should fill remaining space */
|
|
1319
1398
|
.${prefix}-page > .${prefix}-row:has(.${prefix}-sidebar),
|
|
1320
|
-
.${prefix}-page > .${prefix}-row:has(.${prefix}-main)
|
|
1399
|
+
.${prefix}-page > .${prefix}-row:has(.${prefix}-main),
|
|
1400
|
+
.${prefix}-page > .${prefix}-col > .${prefix}-row:has(.${prefix}-sidebar),
|
|
1401
|
+
.${prefix}-page > .${prefix}-col > .${prefix}-row:has(.${prefix}-main) {
|
|
1321
1402
|
flex: 1;
|
|
1403
|
+
min-height: 0;
|
|
1322
1404
|
align-items: stretch;
|
|
1323
1405
|
}
|
|
1324
1406
|
|
|
@@ -1361,10 +1443,15 @@ function generateGridClasses(_theme, prefix) {
|
|
|
1361
1443
|
box-sizing: border-box;
|
|
1362
1444
|
}
|
|
1363
1445
|
|
|
1446
|
+
/* When explicit width is set, don't flex-grow */
|
|
1447
|
+
.${prefix}-row[style*="width:"],
|
|
1448
|
+
.${prefix}-col[style*="width:"] {
|
|
1449
|
+
flex: 0 0 auto;
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1364
1452
|
`;
|
|
1365
1453
|
for (let i = 1; i <= 12; i++) {
|
|
1366
|
-
|
|
1367
|
-
css += `.${prefix}-col-${i} { flex: 0 0 auto; width: ${width}%; }
|
|
1454
|
+
css += `.${prefix}-col-${i} { flex: ${i} 0 0%; min-width: 0; }
|
|
1368
1455
|
`;
|
|
1369
1456
|
}
|
|
1370
1457
|
return css;
|
|
@@ -1532,6 +1619,26 @@ function generateLayoutClasses(prefix) {
|
|
|
1532
1619
|
.${prefix}-main {
|
|
1533
1620
|
flex: 1;
|
|
1534
1621
|
padding: 16px;
|
|
1622
|
+
display: flex;
|
|
1623
|
+
flex-direction: column;
|
|
1624
|
+
min-height: 0;
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
/* Scrollable main content */
|
|
1628
|
+
.${prefix}-main.${prefix}-scroll {
|
|
1629
|
+
overflow-y: auto;
|
|
1630
|
+
overflow-x: hidden;
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
/* Col containing scrollable main needs min-height: 0 for scroll to work */
|
|
1634
|
+
.${prefix}-col:has(> .${prefix}-main.${prefix}-scroll) {
|
|
1635
|
+
min-height: 0;
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
/* Main content should align to top, not stretch to fill */
|
|
1639
|
+
/* But allow explicit flex=1 to override */
|
|
1640
|
+
.${prefix}-main > .${prefix}-col:not(.${prefix}-flex-1) {
|
|
1641
|
+
flex: 0 0 auto;
|
|
1535
1642
|
}
|
|
1536
1643
|
|
|
1537
1644
|
.${prefix}-footer {
|
|
@@ -1548,6 +1655,7 @@ function generateLayoutClasses(prefix) {
|
|
|
1548
1655
|
border-right: 1px solid var(--${prefix}-border);
|
|
1549
1656
|
padding: 16px 16px 16px 20px;
|
|
1550
1657
|
flex-shrink: 0;
|
|
1658
|
+
align-self: stretch;
|
|
1551
1659
|
}
|
|
1552
1660
|
|
|
1553
1661
|
.${prefix}-sidebar-right {
|
|
@@ -1761,6 +1869,248 @@ function resolveViewport(viewport, device) {
|
|
|
1761
1869
|
return DEFAULT_VIEWPORT;
|
|
1762
1870
|
}
|
|
1763
1871
|
|
|
1872
|
+
// src/renderer/html/components.ts
|
|
1873
|
+
function buildClassString(classes) {
|
|
1874
|
+
return classes.filter(Boolean).join(" ");
|
|
1875
|
+
}
|
|
1876
|
+
var SIZE_TOKENS = {
|
|
1877
|
+
icon: { xs: 12, sm: 14, md: 16, lg: 20, xl: 24 },
|
|
1878
|
+
avatar: { xs: 24, sm: 32, md: 40, lg: 48, xl: 64 },
|
|
1879
|
+
spinner: { xs: 12, sm: 16, md: 24, lg: 32, xl: 48 }
|
|
1880
|
+
};
|
|
1881
|
+
function resolveSizeValue(size, componentType, prefix) {
|
|
1882
|
+
if (size === void 0) {
|
|
1883
|
+
return {};
|
|
1884
|
+
}
|
|
1885
|
+
if (typeof size === "string") {
|
|
1886
|
+
const tokens = SIZE_TOKENS[componentType];
|
|
1887
|
+
if (size in tokens) {
|
|
1888
|
+
return { className: `${prefix}-${componentType}-${size}` };
|
|
1889
|
+
}
|
|
1890
|
+
const parsed = parseInt(size, 10);
|
|
1891
|
+
if (!isNaN(parsed)) {
|
|
1892
|
+
return { style: `width: ${parsed}px; height: ${parsed}px;` };
|
|
1893
|
+
}
|
|
1894
|
+
return {};
|
|
1895
|
+
}
|
|
1896
|
+
if (typeof size === "number") {
|
|
1897
|
+
return { style: `width: ${size}px; height: ${size}px;` };
|
|
1898
|
+
}
|
|
1899
|
+
return {};
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
// src/renderer/html/renderers/layout.ts
|
|
1903
|
+
function renderHeader(node, ctx) {
|
|
1904
|
+
const classes = ctx.buildClassString([
|
|
1905
|
+
`${ctx.prefix}-header`,
|
|
1906
|
+
node.border === false ? `${ctx.prefix}-no-border` : void 0,
|
|
1907
|
+
...ctx.getCommonClasses(node)
|
|
1908
|
+
]);
|
|
1909
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1910
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1911
|
+
const children = ctx.renderChildren(node.children);
|
|
1912
|
+
return `<header class="${classes}"${styleAttr}>
|
|
1913
|
+
${children}
|
|
1914
|
+
</header>`;
|
|
1915
|
+
}
|
|
1916
|
+
function renderMain(node, ctx) {
|
|
1917
|
+
const classes = ctx.buildClassString([
|
|
1918
|
+
`${ctx.prefix}-main`,
|
|
1919
|
+
node.scroll ? `${ctx.prefix}-scroll` : void 0,
|
|
1920
|
+
...ctx.getCommonClasses(node)
|
|
1921
|
+
]);
|
|
1922
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1923
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1924
|
+
const children = ctx.renderChildren(node.children);
|
|
1925
|
+
return `<main class="${classes}"${styleAttr}>
|
|
1926
|
+
${children}
|
|
1927
|
+
</main>`;
|
|
1928
|
+
}
|
|
1929
|
+
function renderFooter(node, ctx) {
|
|
1930
|
+
const classes = ctx.buildClassString([
|
|
1931
|
+
`${ctx.prefix}-footer`,
|
|
1932
|
+
node.border === false ? `${ctx.prefix}-no-border` : void 0,
|
|
1933
|
+
...ctx.getCommonClasses(node)
|
|
1934
|
+
]);
|
|
1935
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1936
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1937
|
+
const children = ctx.renderChildren(node.children);
|
|
1938
|
+
return `<footer class="${classes}"${styleAttr}>
|
|
1939
|
+
${children}
|
|
1940
|
+
</footer>`;
|
|
1941
|
+
}
|
|
1942
|
+
function renderSidebar(node, ctx) {
|
|
1943
|
+
const classes = ctx.buildClassString([
|
|
1944
|
+
`${ctx.prefix}-sidebar`,
|
|
1945
|
+
node.position === "right" ? `${ctx.prefix}-sidebar-right` : void 0,
|
|
1946
|
+
...ctx.getCommonClasses(node)
|
|
1947
|
+
]);
|
|
1948
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1949
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1950
|
+
const children = ctx.renderChildren(node.children);
|
|
1951
|
+
return `<aside class="${classes}"${styleAttr}>
|
|
1952
|
+
${children}
|
|
1953
|
+
</aside>`;
|
|
1954
|
+
}
|
|
1955
|
+
function renderSection(node, ctx) {
|
|
1956
|
+
const classes = ctx.buildClassString([
|
|
1957
|
+
`${ctx.prefix}-section`,
|
|
1958
|
+
...ctx.getCommonClasses(node)
|
|
1959
|
+
]);
|
|
1960
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1961
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1962
|
+
const title = node.title ? `<h2 class="${ctx.prefix}-title">${ctx.escapeHtml(node.title)}</h2>
|
|
1963
|
+
` : "";
|
|
1964
|
+
const children = ctx.renderChildren(node.children);
|
|
1965
|
+
return `<section class="${classes}"${styleAttr}>
|
|
1966
|
+
${title}${children}
|
|
1967
|
+
</section>`;
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
// src/renderer/html/renderers/grid.ts
|
|
1971
|
+
function renderRow(node, ctx) {
|
|
1972
|
+
const classes = ctx.buildClassString([
|
|
1973
|
+
`${ctx.prefix}-row`,
|
|
1974
|
+
...ctx.getCommonClasses(node)
|
|
1975
|
+
]);
|
|
1976
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1977
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1978
|
+
const children = ctx.renderChildren(node.children);
|
|
1979
|
+
return `<div class="${classes}"${styleAttr}>
|
|
1980
|
+
${children}
|
|
1981
|
+
</div>`;
|
|
1982
|
+
}
|
|
1983
|
+
function renderCol(node, ctx) {
|
|
1984
|
+
const classes = ctx.buildClassString([
|
|
1985
|
+
`${ctx.prefix}-col`,
|
|
1986
|
+
node.span ? `${ctx.prefix}-col-${node.span}` : void 0,
|
|
1987
|
+
// Responsive breakpoint classes
|
|
1988
|
+
node.sm ? `${ctx.prefix}-col-sm-${node.sm}` : void 0,
|
|
1989
|
+
node.md ? `${ctx.prefix}-col-md-${node.md}` : void 0,
|
|
1990
|
+
node.lg ? `${ctx.prefix}-col-lg-${node.lg}` : void 0,
|
|
1991
|
+
node.xl ? `${ctx.prefix}-col-xl-${node.xl}` : void 0,
|
|
1992
|
+
...ctx.getCommonClasses(node)
|
|
1993
|
+
]);
|
|
1994
|
+
const styles = ctx.buildColStyles(node);
|
|
1995
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1996
|
+
const children = ctx.renderChildren(node.children);
|
|
1997
|
+
return `<div class="${classes}"${styleAttr}>
|
|
1998
|
+
${children}
|
|
1999
|
+
</div>`;
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
// src/renderer/html/renderers/container.ts
|
|
2003
|
+
function renderCard(node, ctx) {
|
|
2004
|
+
const hasExplicitWidth = node.w !== void 0;
|
|
2005
|
+
const classes = ctx.buildClassString([
|
|
2006
|
+
`${ctx.prefix}-card`,
|
|
2007
|
+
!hasExplicitWidth ? `${ctx.prefix}-card-flex` : void 0,
|
|
2008
|
+
node.shadow ? `${ctx.prefix}-card-shadow-${node.shadow}` : void 0,
|
|
2009
|
+
...ctx.getCommonClasses(node)
|
|
2010
|
+
]);
|
|
2011
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2012
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2013
|
+
const title = node.title ? `<h3 class="${ctx.prefix}-title">${ctx.escapeHtml(node.title)}</h3>
|
|
2014
|
+
` : "";
|
|
2015
|
+
const children = ctx.renderChildren(node.children);
|
|
2016
|
+
return `<div class="${classes}"${styleAttr}>
|
|
2017
|
+
${title}${children}
|
|
2018
|
+
</div>`;
|
|
2019
|
+
}
|
|
2020
|
+
function renderModal(node, ctx) {
|
|
2021
|
+
const classes = ctx.buildClassString([
|
|
2022
|
+
`${ctx.prefix}-modal`,
|
|
2023
|
+
...ctx.getCommonClasses(node)
|
|
2024
|
+
]);
|
|
2025
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2026
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2027
|
+
const title = node.title ? `<h2 class="${ctx.prefix}-title">${ctx.escapeHtml(node.title)}</h2>
|
|
2028
|
+
` : "";
|
|
2029
|
+
const children = ctx.renderChildren(node.children);
|
|
2030
|
+
return `<div class="${ctx.prefix}-modal-backdrop">
|
|
2031
|
+
<div class="${classes}"${styleAttr} role="dialog" aria-modal="true">
|
|
2032
|
+
${title}${children}
|
|
2033
|
+
</div>
|
|
2034
|
+
</div>`;
|
|
2035
|
+
}
|
|
2036
|
+
function renderDrawer(node, ctx) {
|
|
2037
|
+
const position = node.position || "left";
|
|
2038
|
+
const classes = ctx.buildClassString([
|
|
2039
|
+
`${ctx.prefix}-drawer`,
|
|
2040
|
+
`${ctx.prefix}-drawer-${position}`,
|
|
2041
|
+
...ctx.getCommonClasses(node)
|
|
2042
|
+
]);
|
|
2043
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2044
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2045
|
+
const title = node.title ? `<h2 class="${ctx.prefix}-title">${ctx.escapeHtml(node.title)}</h2>
|
|
2046
|
+
` : "";
|
|
2047
|
+
const children = ctx.renderChildren(node.children);
|
|
2048
|
+
return `<aside class="${classes}"${styleAttr}>
|
|
2049
|
+
${title}${children}
|
|
2050
|
+
</aside>`;
|
|
2051
|
+
}
|
|
2052
|
+
function renderAccordion(node, ctx) {
|
|
2053
|
+
const classes = ctx.buildClassString([
|
|
2054
|
+
`${ctx.prefix}-accordion`,
|
|
2055
|
+
...ctx.getCommonClasses(node)
|
|
2056
|
+
]);
|
|
2057
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2058
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2059
|
+
const title = node.title ? `<button class="${ctx.prefix}-accordion-header">${ctx.escapeHtml(node.title)}</button>
|
|
2060
|
+
` : "";
|
|
2061
|
+
const children = ctx.renderChildren(node.children);
|
|
2062
|
+
return `<div class="${classes}"${styleAttr}>
|
|
2063
|
+
${title}<div class="${ctx.prefix}-accordion-content">
|
|
2064
|
+
${children}
|
|
2065
|
+
</div>
|
|
2066
|
+
</div>`;
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
// src/renderer/html/renderers/text.ts
|
|
2070
|
+
function renderText(node, ctx) {
|
|
2071
|
+
const classes = ctx.buildClassString([
|
|
2072
|
+
`${ctx.prefix}-text`,
|
|
2073
|
+
node.size ? `${ctx.prefix}-text-${node.size}` : void 0,
|
|
2074
|
+
node.weight ? `${ctx.prefix}-text-${node.weight}` : void 0,
|
|
2075
|
+
node.align ? `${ctx.prefix}-text-${node.align}` : void 0,
|
|
2076
|
+
node.muted ? `${ctx.prefix}-text-muted` : void 0,
|
|
2077
|
+
...ctx.getCommonClasses(node)
|
|
2078
|
+
]);
|
|
2079
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2080
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2081
|
+
return `<p class="${classes}"${styleAttr}>${ctx.escapeHtml(node.content)}</p>`;
|
|
2082
|
+
}
|
|
2083
|
+
function renderTitle(node, ctx) {
|
|
2084
|
+
const level = node.level || 1;
|
|
2085
|
+
const tag = `h${level}`;
|
|
2086
|
+
const classes = ctx.buildClassString([
|
|
2087
|
+
`${ctx.prefix}-title`,
|
|
2088
|
+
node.size ? `${ctx.prefix}-text-${node.size}` : void 0,
|
|
2089
|
+
node.align ? `${ctx.prefix}-text-${node.align}` : void 0,
|
|
2090
|
+
...ctx.getCommonClasses(node)
|
|
2091
|
+
]);
|
|
2092
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2093
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2094
|
+
return `<${tag} class="${classes}"${styleAttr}>${ctx.escapeHtml(node.content)}</${tag}>`;
|
|
2095
|
+
}
|
|
2096
|
+
function renderLink(node, ctx) {
|
|
2097
|
+
const classes = ctx.buildClassString([
|
|
2098
|
+
`${ctx.prefix}-link`,
|
|
2099
|
+
...ctx.getCommonClasses(node)
|
|
2100
|
+
]);
|
|
2101
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2102
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2103
|
+
const attrs = {
|
|
2104
|
+
class: classes,
|
|
2105
|
+
href: node.href || "#"
|
|
2106
|
+
};
|
|
2107
|
+
if (node.external) {
|
|
2108
|
+
attrs.target = "_blank";
|
|
2109
|
+
attrs.rel = "noopener noreferrer";
|
|
2110
|
+
}
|
|
2111
|
+
return `<a${ctx.buildAttrsString(attrs)}${styleAttr}>${ctx.escapeHtml(node.content)}</a>`;
|
|
2112
|
+
}
|
|
2113
|
+
|
|
1764
2114
|
// src/icons/lucide-icons.ts
|
|
1765
2115
|
var lucideIcons = {
|
|
1766
2116
|
"a-arrow-down": [
|
|
@@ -48117,14 +48467,39 @@ var lucideIcons = {
|
|
|
48117
48467
|
]
|
|
48118
48468
|
]
|
|
48119
48469
|
};
|
|
48470
|
+
var iconAliases = {
|
|
48471
|
+
"home": "house",
|
|
48472
|
+
"plus-square": "square-plus",
|
|
48473
|
+
"minus-square": "square-minus",
|
|
48474
|
+
"x-square": "square-x",
|
|
48475
|
+
"check-square": "square-check",
|
|
48476
|
+
"edit": "pencil",
|
|
48477
|
+
"edit-2": "pencil",
|
|
48478
|
+
"edit-3": "pencil-line",
|
|
48479
|
+
"trash": "trash-2",
|
|
48480
|
+
"delete": "trash-2",
|
|
48481
|
+
"close": "x",
|
|
48482
|
+
"menu": "menu",
|
|
48483
|
+
"hamburger": "menu",
|
|
48484
|
+
"dots": "more-horizontal",
|
|
48485
|
+
"dots-vertical": "more-vertical",
|
|
48486
|
+
"cog": "settings",
|
|
48487
|
+
"gear": "settings"
|
|
48488
|
+
};
|
|
48120
48489
|
function getIconData(name) {
|
|
48121
48490
|
if (lucideIcons[name]) {
|
|
48122
48491
|
return lucideIcons[name];
|
|
48123
48492
|
}
|
|
48493
|
+
if (iconAliases[name] && lucideIcons[iconAliases[name]]) {
|
|
48494
|
+
return lucideIcons[iconAliases[name]];
|
|
48495
|
+
}
|
|
48124
48496
|
const kebabName = name.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
48125
48497
|
if (lucideIcons[kebabName]) {
|
|
48126
48498
|
return lucideIcons[kebabName];
|
|
48127
48499
|
}
|
|
48500
|
+
if (iconAliases[kebabName] && lucideIcons[iconAliases[kebabName]]) {
|
|
48501
|
+
return lucideIcons[iconAliases[kebabName]];
|
|
48502
|
+
}
|
|
48128
48503
|
return void 0;
|
|
48129
48504
|
}
|
|
48130
48505
|
function renderIconSvg(data, _size = 24, strokeWidth = 2, className = "", styleAttr = "") {
|
|
@@ -48135,34 +48510,658 @@ function renderIconSvg(data, _size = 24, strokeWidth = 2, className = "", styleA
|
|
|
48135
48510
|
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>`;
|
|
48136
48511
|
}
|
|
48137
48512
|
|
|
48138
|
-
// src/renderer/html/
|
|
48139
|
-
function
|
|
48140
|
-
|
|
48513
|
+
// src/renderer/html/renderers/button.ts
|
|
48514
|
+
function renderButton(node, ctx) {
|
|
48515
|
+
const isIconOnly = node.icon && (!node.content.trim() || node.content === "Button");
|
|
48516
|
+
const classes = ctx.buildClassString([
|
|
48517
|
+
`${ctx.prefix}-button`,
|
|
48518
|
+
node.primary ? `${ctx.prefix}-button-primary` : void 0,
|
|
48519
|
+
node.secondary ? `${ctx.prefix}-button-secondary` : void 0,
|
|
48520
|
+
node.outline ? `${ctx.prefix}-button-outline` : void 0,
|
|
48521
|
+
node.ghost ? `${ctx.prefix}-button-ghost` : void 0,
|
|
48522
|
+
node.danger ? `${ctx.prefix}-button-danger` : void 0,
|
|
48523
|
+
node.size ? `${ctx.prefix}-button-${node.size}` : void 0,
|
|
48524
|
+
node.disabled ? `${ctx.prefix}-button-disabled` : void 0,
|
|
48525
|
+
node.loading ? `${ctx.prefix}-button-loading` : void 0,
|
|
48526
|
+
isIconOnly ? `${ctx.prefix}-button-icon-only` : void 0,
|
|
48527
|
+
...ctx.getCommonClasses(node)
|
|
48528
|
+
]);
|
|
48529
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48530
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48531
|
+
const attrs = {
|
|
48532
|
+
class: classes,
|
|
48533
|
+
disabled: node.disabled
|
|
48534
|
+
};
|
|
48535
|
+
let icon = "";
|
|
48536
|
+
if (node.icon) {
|
|
48537
|
+
const iconData = getIconData(node.icon);
|
|
48538
|
+
if (iconData) {
|
|
48539
|
+
icon = renderIconSvg(iconData, 16, 2, `${ctx.prefix}-icon`);
|
|
48540
|
+
} else {
|
|
48541
|
+
icon = `<span class="${ctx.prefix}-icon">[${ctx.escapeHtml(node.icon)}]</span>`;
|
|
48542
|
+
}
|
|
48543
|
+
}
|
|
48544
|
+
const loading = node.loading ? `<span class="${ctx.prefix}-spinner ${ctx.prefix}-spinner-sm"></span>` : "";
|
|
48545
|
+
const content = isIconOnly ? "" : ctx.escapeHtml(node.content);
|
|
48546
|
+
return `<button${ctx.buildAttrsString(attrs)}${styleAttr}>${loading}${icon}${content}</button>`;
|
|
48141
48547
|
}
|
|
48142
|
-
|
|
48143
|
-
|
|
48144
|
-
|
|
48145
|
-
|
|
48146
|
-
}
|
|
48147
|
-
|
|
48148
|
-
|
|
48149
|
-
|
|
48548
|
+
|
|
48549
|
+
// src/renderer/html/renderers/feedback.ts
|
|
48550
|
+
function renderAlert(node, ctx) {
|
|
48551
|
+
const classes = ctx.buildClassString([
|
|
48552
|
+
`${ctx.prefix}-alert`,
|
|
48553
|
+
node.variant ? `${ctx.prefix}-alert-${node.variant}` : void 0,
|
|
48554
|
+
...ctx.getCommonClasses(node)
|
|
48555
|
+
]);
|
|
48556
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48557
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48558
|
+
const dismissBtn = node.dismissible ? ` <button class="${ctx.prefix}-alert-close" aria-label="Close">×</button>` : "";
|
|
48559
|
+
return `<div class="${classes}"${styleAttr} role="alert">${ctx.escapeHtml(node.content)}${dismissBtn}</div>`;
|
|
48560
|
+
}
|
|
48561
|
+
function renderToast(node, ctx) {
|
|
48562
|
+
const classes = ctx.buildClassString([
|
|
48563
|
+
`${ctx.prefix}-toast`,
|
|
48564
|
+
node.position ? `${ctx.prefix}-toast-${node.position}` : void 0,
|
|
48565
|
+
node.variant ? `${ctx.prefix}-toast-${node.variant}` : void 0,
|
|
48566
|
+
...ctx.getCommonClasses(node)
|
|
48567
|
+
]);
|
|
48568
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48569
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48570
|
+
return `<div class="${classes}"${styleAttr} role="status">${ctx.escapeHtml(node.content)}</div>`;
|
|
48571
|
+
}
|
|
48572
|
+
function renderProgress(node, ctx) {
|
|
48573
|
+
const classes = ctx.buildClassString([
|
|
48574
|
+
`${ctx.prefix}-progress`,
|
|
48575
|
+
...ctx.getCommonClasses(node)
|
|
48576
|
+
]);
|
|
48577
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48578
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48579
|
+
const value = node.value || 0;
|
|
48580
|
+
const max = node.max || 100;
|
|
48581
|
+
const percentage = Math.round(value / max * 100);
|
|
48582
|
+
const label = node.label ? `<span class="${ctx.prefix}-progress-label">${ctx.escapeHtml(node.label)}</span>` : "";
|
|
48583
|
+
if (node.indeterminate) {
|
|
48584
|
+
return `<div class="${classes} ${ctx.prefix}-progress-indeterminate"${styleAttr} role="progressbar">${label}</div>`;
|
|
48150
48585
|
}
|
|
48151
|
-
|
|
48152
|
-
|
|
48153
|
-
|
|
48154
|
-
|
|
48586
|
+
return `<div class="${classes}"${styleAttr} role="progressbar" aria-valuenow="${value}" aria-valuemin="0" aria-valuemax="${max}">
|
|
48587
|
+
${label}
|
|
48588
|
+
<div class="${ctx.prefix}-progress-bar" style="width: ${percentage}%"></div>
|
|
48589
|
+
</div>`;
|
|
48590
|
+
}
|
|
48591
|
+
function renderSpinner(node, ctx) {
|
|
48592
|
+
const sizeResolved = resolveSizeValue(node.size, "spinner", ctx.prefix);
|
|
48593
|
+
const classes = ctx.buildClassString([
|
|
48594
|
+
`${ctx.prefix}-spinner`,
|
|
48595
|
+
sizeResolved.className,
|
|
48596
|
+
...ctx.getCommonClasses(node)
|
|
48597
|
+
]);
|
|
48598
|
+
const baseStyles = ctx.buildCommonStyles(node);
|
|
48599
|
+
const sizeStyle = sizeResolved.style || "";
|
|
48600
|
+
const combinedStyles = baseStyles && sizeStyle ? `${baseStyles}; ${sizeStyle}` : baseStyles || sizeStyle;
|
|
48601
|
+
const styleAttr = combinedStyles ? ` style="${combinedStyles}"` : "";
|
|
48602
|
+
const label = node.label || "Loading...";
|
|
48603
|
+
return `<span class="${classes}"${styleAttr} role="status" aria-label="${ctx.escapeHtml(label)}"></span>`;
|
|
48604
|
+
}
|
|
48605
|
+
|
|
48606
|
+
// src/renderer/html/renderers/input.ts
|
|
48607
|
+
function renderInput(node, ctx) {
|
|
48608
|
+
const inputClasses = ctx.buildClassString([
|
|
48609
|
+
`${ctx.prefix}-input`,
|
|
48610
|
+
node.icon ? `${ctx.prefix}-input-with-icon` : void 0,
|
|
48611
|
+
...ctx.getCommonClasses(node)
|
|
48612
|
+
]);
|
|
48613
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48614
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48615
|
+
const attrs = {
|
|
48616
|
+
class: inputClasses,
|
|
48617
|
+
type: node.inputType || "text",
|
|
48618
|
+
placeholder: node.placeholder,
|
|
48619
|
+
value: node.value,
|
|
48620
|
+
disabled: node.disabled,
|
|
48621
|
+
required: node.required,
|
|
48622
|
+
readonly: node.readonly
|
|
48623
|
+
};
|
|
48624
|
+
const inputElement = `<input${ctx.buildAttrsString(attrs)} />`;
|
|
48625
|
+
if (node.icon) {
|
|
48626
|
+
const iconData = getIconData(node.icon);
|
|
48627
|
+
let iconHtml;
|
|
48628
|
+
if (iconData) {
|
|
48629
|
+
iconHtml = renderIconSvg(iconData, 16, 2, `${ctx.prefix}-input-icon`);
|
|
48630
|
+
} else {
|
|
48631
|
+
iconHtml = `<span class="${ctx.prefix}-input-icon">[${ctx.escapeHtml(node.icon)}]</span>`;
|
|
48155
48632
|
}
|
|
48156
|
-
const
|
|
48157
|
-
|
|
48158
|
-
|
|
48633
|
+
const wrapperClasses = ctx.buildClassString([`${ctx.prefix}-input-wrapper`]);
|
|
48634
|
+
const wrapper = `<div class="${wrapperClasses}"${styleAttr}>${iconHtml}${inputElement}</div>`;
|
|
48635
|
+
const shouldShowLabel = node.label && !(node.label === "Label" && node.placeholder);
|
|
48636
|
+
if (shouldShowLabel) {
|
|
48637
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48638
|
+
${wrapper}`;
|
|
48159
48639
|
}
|
|
48160
|
-
return
|
|
48640
|
+
return wrapper;
|
|
48161
48641
|
}
|
|
48162
|
-
|
|
48163
|
-
|
|
48642
|
+
const input = `<input${ctx.buildAttrsString(attrs)}${styleAttr} />`;
|
|
48643
|
+
const shouldShowLabel2 = node.label && !(node.label === "Label" && node.placeholder);
|
|
48644
|
+
if (shouldShowLabel2) {
|
|
48645
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48646
|
+
${input}`;
|
|
48164
48647
|
}
|
|
48165
|
-
return
|
|
48648
|
+
return input;
|
|
48649
|
+
}
|
|
48650
|
+
function renderTextarea(node, ctx) {
|
|
48651
|
+
const classes = ctx.buildClassString([
|
|
48652
|
+
`${ctx.prefix}-input`,
|
|
48653
|
+
...ctx.getCommonClasses(node)
|
|
48654
|
+
]);
|
|
48655
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48656
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48657
|
+
const attrs = {
|
|
48658
|
+
class: classes,
|
|
48659
|
+
placeholder: node.placeholder,
|
|
48660
|
+
disabled: node.disabled,
|
|
48661
|
+
required: node.required,
|
|
48662
|
+
rows: node.rows?.toString()
|
|
48663
|
+
};
|
|
48664
|
+
const textarea = `<textarea${ctx.buildAttrsString(attrs)}${styleAttr}>${ctx.escapeHtml(node.value || "")}</textarea>`;
|
|
48665
|
+
if (node.label) {
|
|
48666
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48667
|
+
${textarea}`;
|
|
48668
|
+
}
|
|
48669
|
+
return textarea;
|
|
48670
|
+
}
|
|
48671
|
+
function renderSelect(node, ctx) {
|
|
48672
|
+
const classes = ctx.buildClassString([
|
|
48673
|
+
`${ctx.prefix}-input`,
|
|
48674
|
+
...ctx.getCommonClasses(node)
|
|
48675
|
+
]);
|
|
48676
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48677
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48678
|
+
const attrs = {
|
|
48679
|
+
class: classes,
|
|
48680
|
+
disabled: node.disabled,
|
|
48681
|
+
required: node.required
|
|
48682
|
+
};
|
|
48683
|
+
const options = node.options.map((opt) => {
|
|
48684
|
+
if (typeof opt === "string") {
|
|
48685
|
+
const selected2 = opt === node.value ? " selected" : "";
|
|
48686
|
+
return `<option value="${ctx.escapeHtml(opt)}"${selected2}>${ctx.escapeHtml(opt)}</option>`;
|
|
48687
|
+
}
|
|
48688
|
+
const selected = opt.value === node.value ? " selected" : "";
|
|
48689
|
+
return `<option value="${ctx.escapeHtml(opt.value)}"${selected}>${ctx.escapeHtml(opt.label)}</option>`;
|
|
48690
|
+
}).join("\n");
|
|
48691
|
+
const placeholder = node.placeholder ? `<option value="" disabled selected>${ctx.escapeHtml(node.placeholder)}</option>
|
|
48692
|
+
` : "";
|
|
48693
|
+
const select = `<select${ctx.buildAttrsString(attrs)}${styleAttr}>
|
|
48694
|
+
${placeholder}${options}
|
|
48695
|
+
</select>`;
|
|
48696
|
+
if (node.label) {
|
|
48697
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48698
|
+
${select}`;
|
|
48699
|
+
}
|
|
48700
|
+
return select;
|
|
48701
|
+
}
|
|
48702
|
+
function renderCheckbox(node, ctx) {
|
|
48703
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48704
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48705
|
+
const attrs = {
|
|
48706
|
+
type: "checkbox",
|
|
48707
|
+
checked: node.checked,
|
|
48708
|
+
disabled: node.disabled
|
|
48709
|
+
};
|
|
48710
|
+
const checkbox = `<input${ctx.buildAttrsString(attrs)} />`;
|
|
48711
|
+
if (node.label) {
|
|
48712
|
+
return `<label class="${ctx.prefix}-checkbox"${styleAttr}>${checkbox}<span>${ctx.escapeHtml(node.label)}</span></label>`;
|
|
48713
|
+
}
|
|
48714
|
+
return checkbox;
|
|
48715
|
+
}
|
|
48716
|
+
function renderRadio(node, ctx) {
|
|
48717
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48718
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48719
|
+
const attrs = {
|
|
48720
|
+
type: "radio",
|
|
48721
|
+
name: node.name,
|
|
48722
|
+
checked: node.checked,
|
|
48723
|
+
disabled: node.disabled
|
|
48724
|
+
};
|
|
48725
|
+
const radio = `<input${ctx.buildAttrsString(attrs)} />`;
|
|
48726
|
+
if (node.label) {
|
|
48727
|
+
return `<label class="${ctx.prefix}-radio"${styleAttr}>${radio}<span>${ctx.escapeHtml(node.label)}</span></label>`;
|
|
48728
|
+
}
|
|
48729
|
+
return radio;
|
|
48730
|
+
}
|
|
48731
|
+
function renderSwitch(node, ctx) {
|
|
48732
|
+
const classes = ctx.buildClassString([
|
|
48733
|
+
`${ctx.prefix}-switch`,
|
|
48734
|
+
...ctx.getCommonClasses(node)
|
|
48735
|
+
]);
|
|
48736
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48737
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48738
|
+
const attrs = {
|
|
48739
|
+
type: "checkbox",
|
|
48740
|
+
role: "switch",
|
|
48741
|
+
checked: node.checked,
|
|
48742
|
+
disabled: node.disabled
|
|
48743
|
+
};
|
|
48744
|
+
const switchEl = `<input${ctx.buildAttrsString(attrs)} />`;
|
|
48745
|
+
if (node.label) {
|
|
48746
|
+
return `<label class="${classes}"${styleAttr}>${switchEl} ${ctx.escapeHtml(node.label)}</label>`;
|
|
48747
|
+
}
|
|
48748
|
+
return `<label class="${classes}"${styleAttr}>${switchEl}</label>`;
|
|
48749
|
+
}
|
|
48750
|
+
function renderSlider(node, ctx) {
|
|
48751
|
+
const classes = ctx.buildClassString([
|
|
48752
|
+
`${ctx.prefix}-slider`,
|
|
48753
|
+
...ctx.getCommonClasses(node)
|
|
48754
|
+
]);
|
|
48755
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48756
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48757
|
+
const attrs = {
|
|
48758
|
+
class: classes,
|
|
48759
|
+
type: "range",
|
|
48760
|
+
min: node.min?.toString(),
|
|
48761
|
+
max: node.max?.toString(),
|
|
48762
|
+
step: node.step?.toString(),
|
|
48763
|
+
value: node.value?.toString(),
|
|
48764
|
+
disabled: node.disabled
|
|
48765
|
+
};
|
|
48766
|
+
const slider = `<input${ctx.buildAttrsString(attrs)}${styleAttr} />`;
|
|
48767
|
+
if (node.label) {
|
|
48768
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48769
|
+
${slider}`;
|
|
48770
|
+
}
|
|
48771
|
+
return slider;
|
|
48772
|
+
}
|
|
48773
|
+
|
|
48774
|
+
// src/renderer/html/renderers/display.ts
|
|
48775
|
+
function renderImage(node, ctx) {
|
|
48776
|
+
const classes = ctx.buildClassString([
|
|
48777
|
+
`${ctx.prefix}-image`,
|
|
48778
|
+
...ctx.getCommonClasses(node)
|
|
48779
|
+
]);
|
|
48780
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48781
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48782
|
+
if (node.src) {
|
|
48783
|
+
const attrs = {
|
|
48784
|
+
class: classes,
|
|
48785
|
+
src: node.src,
|
|
48786
|
+
alt: node.alt || "Image"
|
|
48787
|
+
};
|
|
48788
|
+
const imgStyleAttr = styles ? `; ${styles}` : "";
|
|
48789
|
+
return `<img${ctx.buildAttrsString(attrs)}${imgStyleAttr ? ` style="${imgStyleAttr.slice(2)}"` : ""} />`;
|
|
48790
|
+
}
|
|
48791
|
+
const label = node.alt || "Image";
|
|
48792
|
+
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>`;
|
|
48793
|
+
return `<div class="${classes}"${styleAttr} role="img" aria-label="${ctx.escapeHtml(label)}">${icon}<span>${ctx.escapeHtml(label)}</span></div>`;
|
|
48794
|
+
}
|
|
48795
|
+
function renderPlaceholder(node, ctx) {
|
|
48796
|
+
const classes = ctx.buildClassString([
|
|
48797
|
+
`${ctx.prefix}-placeholder`,
|
|
48798
|
+
node.children && node.children.length > 0 ? `${ctx.prefix}-placeholder-with-children` : void 0,
|
|
48799
|
+
...ctx.getCommonClasses(node)
|
|
48800
|
+
]);
|
|
48801
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48802
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48803
|
+
const label = node.label ? ctx.escapeHtml(node.label) : "Placeholder";
|
|
48804
|
+
if (node.children && node.children.length > 0) {
|
|
48805
|
+
const childrenHtml = ctx.renderChildren(node.children);
|
|
48806
|
+
return `<div class="${classes}"${styleAttr}>
|
|
48807
|
+
<span class="${ctx.prefix}-placeholder-label">${label}</span>
|
|
48808
|
+
<div class="${ctx.prefix}-placeholder-overlay">${childrenHtml}</div>
|
|
48809
|
+
</div>`;
|
|
48810
|
+
}
|
|
48811
|
+
return `<div class="${classes}"${styleAttr}>${label}</div>`;
|
|
48812
|
+
}
|
|
48813
|
+
function renderAvatar(node, ctx) {
|
|
48814
|
+
const sizeResolved = resolveSizeValue(node.size, "avatar", ctx.prefix);
|
|
48815
|
+
const classes = ctx.buildClassString([
|
|
48816
|
+
`${ctx.prefix}-avatar`,
|
|
48817
|
+
sizeResolved.className,
|
|
48818
|
+
...ctx.getCommonClasses(node)
|
|
48819
|
+
]);
|
|
48820
|
+
const baseStyles = ctx.buildCommonStyles(node);
|
|
48821
|
+
const sizeStyle = sizeResolved.style || "";
|
|
48822
|
+
const combinedStyles = baseStyles && sizeStyle ? `${baseStyles}; ${sizeStyle}` : baseStyles || sizeStyle;
|
|
48823
|
+
const styleAttr = combinedStyles ? ` style="${combinedStyles}"` : "";
|
|
48824
|
+
const initials = node.name ? node.name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) : "?";
|
|
48825
|
+
return `<div class="${classes}"${styleAttr} role="img" aria-label="${ctx.escapeHtml(node.name || "Avatar")}">${initials}</div>`;
|
|
48826
|
+
}
|
|
48827
|
+
function renderBadge(node, ctx) {
|
|
48828
|
+
if (node.icon) {
|
|
48829
|
+
const iconData = getIconData(node.icon);
|
|
48830
|
+
const classes2 = ctx.buildClassString([
|
|
48831
|
+
`${ctx.prefix}-badge-icon`,
|
|
48832
|
+
node.size ? `${ctx.prefix}-badge-icon-${node.size}` : void 0,
|
|
48833
|
+
node.variant ? `${ctx.prefix}-badge-icon-${node.variant}` : void 0,
|
|
48834
|
+
...ctx.getCommonClasses(node)
|
|
48835
|
+
]);
|
|
48836
|
+
const styles2 = ctx.buildCommonStyles(node);
|
|
48837
|
+
const styleAttr2 = styles2 ? ` style="${styles2}"` : "";
|
|
48838
|
+
if (iconData) {
|
|
48839
|
+
const svg = renderIconSvg(iconData, 24, 2, `${ctx.prefix}-icon`);
|
|
48840
|
+
return `<span class="${classes2}"${styleAttr2} aria-label="${ctx.escapeHtml(node.icon)}">${svg}</span>`;
|
|
48841
|
+
}
|
|
48842
|
+
return `<span class="${classes2}"${styleAttr2} aria-label="unknown icon">?</span>`;
|
|
48843
|
+
}
|
|
48844
|
+
const isDot = !node.content || node.content.trim() === "";
|
|
48845
|
+
const classes = ctx.buildClassString([
|
|
48846
|
+
`${ctx.prefix}-badge`,
|
|
48847
|
+
isDot ? `${ctx.prefix}-badge-dot` : void 0,
|
|
48848
|
+
node.variant ? `${ctx.prefix}-badge-${node.variant}` : void 0,
|
|
48849
|
+
node.pill ? `${ctx.prefix}-badge-pill` : void 0,
|
|
48850
|
+
...ctx.getCommonClasses(node)
|
|
48851
|
+
]);
|
|
48852
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48853
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48854
|
+
return `<span class="${classes}"${styleAttr}>${ctx.escapeHtml(node.content)}</span>`;
|
|
48855
|
+
}
|
|
48856
|
+
function renderIcon(node, ctx) {
|
|
48857
|
+
const iconData = getIconData(node.name);
|
|
48858
|
+
const sizeResolved = resolveSizeValue(node.size, "icon", ctx.prefix);
|
|
48859
|
+
const wrapperClasses = ctx.buildClassString([
|
|
48860
|
+
`${ctx.prefix}-icon-wrapper`,
|
|
48861
|
+
node.muted ? `${ctx.prefix}-text-muted` : void 0,
|
|
48862
|
+
...ctx.getCommonClasses(node)
|
|
48863
|
+
]);
|
|
48864
|
+
const baseStyles = ctx.buildCommonStyles(node);
|
|
48865
|
+
if (iconData) {
|
|
48866
|
+
const iconClasses = buildClassString([
|
|
48867
|
+
`${ctx.prefix}-icon`,
|
|
48868
|
+
sizeResolved.className
|
|
48869
|
+
]);
|
|
48870
|
+
const svgStyleAttr = sizeResolved.style ? ` style="${sizeResolved.style}"` : "";
|
|
48871
|
+
const svg = renderIconSvg(iconData, 24, 2, iconClasses, svgStyleAttr);
|
|
48872
|
+
const wrapperStyleAttr2 = baseStyles ? ` style="${baseStyles}"` : "";
|
|
48873
|
+
return `<span class="${wrapperClasses}"${wrapperStyleAttr2} aria-hidden="true">${svg}</span>`;
|
|
48874
|
+
}
|
|
48875
|
+
const size = sizeResolved.style?.match(/(\d+)px/)?.[1] || "24";
|
|
48876
|
+
const sizeNum = parseInt(size, 10);
|
|
48877
|
+
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">
|
|
48878
|
+
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" stroke-dasharray="4 2" fill="none" opacity="0.5"/>
|
|
48879
|
+
<text x="12" y="16" text-anchor="middle" font-size="10" fill="currentColor" opacity="0.7">?</text>
|
|
48880
|
+
</svg>`;
|
|
48881
|
+
const wrapperStyleAttr = baseStyles ? ` style="${baseStyles}"` : "";
|
|
48882
|
+
return `<span class="${wrapperClasses}"${wrapperStyleAttr} aria-hidden="true" title="Unknown icon: ${ctx.escapeHtml(node.name)}">${placeholderSvg}</span>`;
|
|
48883
|
+
}
|
|
48884
|
+
|
|
48885
|
+
// src/renderer/html/renderers/overlay.ts
|
|
48886
|
+
function renderTooltip(node, ctx) {
|
|
48887
|
+
const classes = ctx.buildClassString([
|
|
48888
|
+
`${ctx.prefix}-tooltip-wrapper`,
|
|
48889
|
+
...ctx.getCommonClasses(node)
|
|
48890
|
+
]);
|
|
48891
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48892
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48893
|
+
const position = node.position || "top";
|
|
48894
|
+
const children = ctx.renderChildren(node.children);
|
|
48895
|
+
return `<div class="${classes}"${styleAttr}>
|
|
48896
|
+
${children}
|
|
48897
|
+
<div class="${ctx.prefix}-tooltip ${ctx.prefix}-tooltip-${position}" role="tooltip">${ctx.escapeHtml(node.content)}</div>
|
|
48898
|
+
</div>`;
|
|
48899
|
+
}
|
|
48900
|
+
function renderPopover(node, ctx) {
|
|
48901
|
+
const classes = ctx.buildClassString([
|
|
48902
|
+
`${ctx.prefix}-popover`,
|
|
48903
|
+
...ctx.getCommonClasses(node)
|
|
48904
|
+
]);
|
|
48905
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48906
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48907
|
+
const title = node.title ? `<div class="${ctx.prefix}-popover-header">${ctx.escapeHtml(node.title)}</div>
|
|
48908
|
+
` : "";
|
|
48909
|
+
const children = ctx.renderChildren(node.children);
|
|
48910
|
+
return `<div class="${classes}"${styleAttr}>
|
|
48911
|
+
${title}<div class="${ctx.prefix}-popover-body">
|
|
48912
|
+
${children}
|
|
48913
|
+
</div>
|
|
48914
|
+
</div>`;
|
|
48915
|
+
}
|
|
48916
|
+
function renderDropdown(node, ctx) {
|
|
48917
|
+
const classes = ctx.buildClassString([
|
|
48918
|
+
`${ctx.prefix}-dropdown`,
|
|
48919
|
+
...ctx.getCommonClasses(node)
|
|
48920
|
+
]);
|
|
48921
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48922
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48923
|
+
const items = node.items.map((item) => {
|
|
48924
|
+
if ("type" in item && item.type === "divider") {
|
|
48925
|
+
return `<hr class="${ctx.prefix}-divider" />`;
|
|
48926
|
+
}
|
|
48927
|
+
const dropdownItem = item;
|
|
48928
|
+
const itemClasses = ctx.buildClassString([
|
|
48929
|
+
`${ctx.prefix}-dropdown-item`,
|
|
48930
|
+
dropdownItem.danger ? `${ctx.prefix}-dropdown-item-danger` : void 0,
|
|
48931
|
+
dropdownItem.disabled ? `${ctx.prefix}-dropdown-item-disabled` : void 0
|
|
48932
|
+
]);
|
|
48933
|
+
return `<button class="${itemClasses}"${dropdownItem.disabled ? " disabled" : ""}>${ctx.escapeHtml(dropdownItem.label)}</button>`;
|
|
48934
|
+
}).join("\n");
|
|
48935
|
+
return `<div class="${classes}"${styleAttr}>
|
|
48936
|
+
${items}
|
|
48937
|
+
</div>`;
|
|
48938
|
+
}
|
|
48939
|
+
|
|
48940
|
+
// src/renderer/html/renderers/navigation.ts
|
|
48941
|
+
function renderIconHtml(iconName, prefix) {
|
|
48942
|
+
return `<span class="${prefix}-icon" data-icon="${iconName}"></span>`;
|
|
48943
|
+
}
|
|
48944
|
+
function renderNavItem(item, ctx) {
|
|
48945
|
+
const linkClasses = ctx.buildClassString([
|
|
48946
|
+
`${ctx.prefix}-nav-link`,
|
|
48947
|
+
item.active ? `${ctx.prefix}-nav-link-active` : void 0,
|
|
48948
|
+
item.disabled ? `${ctx.prefix}-nav-link-disabled` : void 0
|
|
48949
|
+
]);
|
|
48950
|
+
const iconHtml = item.icon ? renderIconHtml(item.icon, ctx.prefix) + " " : "";
|
|
48951
|
+
return `<a class="${linkClasses}" href="${item.href || "#"}">${iconHtml}${ctx.escapeHtml(item.label)}</a>`;
|
|
48952
|
+
}
|
|
48953
|
+
function renderNavChildren(children, ctx) {
|
|
48954
|
+
return children.map((child) => {
|
|
48955
|
+
if (child.type === "divider") {
|
|
48956
|
+
return `<hr class="${ctx.prefix}-nav-divider" />`;
|
|
48957
|
+
}
|
|
48958
|
+
if (child.type === "group") {
|
|
48959
|
+
const groupItems = child.items.map((item) => {
|
|
48960
|
+
if (item.type === "divider") {
|
|
48961
|
+
return `<hr class="${ctx.prefix}-nav-divider" />`;
|
|
48962
|
+
}
|
|
48963
|
+
return renderNavItem(item, ctx);
|
|
48964
|
+
}).join("\n");
|
|
48965
|
+
return `<div class="${ctx.prefix}-nav-group">
|
|
48966
|
+
<div class="${ctx.prefix}-nav-group-label">${ctx.escapeHtml(child.label)}</div>
|
|
48967
|
+
${groupItems}
|
|
48968
|
+
</div>`;
|
|
48969
|
+
}
|
|
48970
|
+
if (child.type === "item") {
|
|
48971
|
+
return renderNavItem(child, ctx);
|
|
48972
|
+
}
|
|
48973
|
+
return "";
|
|
48974
|
+
}).join("\n");
|
|
48975
|
+
}
|
|
48976
|
+
function renderNav(node, ctx) {
|
|
48977
|
+
const classes = ctx.buildClassString([
|
|
48978
|
+
`${ctx.prefix}-nav`,
|
|
48979
|
+
node.vertical ? `${ctx.prefix}-nav-vertical` : void 0,
|
|
48980
|
+
...ctx.getCommonClasses(node)
|
|
48981
|
+
]);
|
|
48982
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48983
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48984
|
+
if (node.children && node.children.length > 0) {
|
|
48985
|
+
const content = renderNavChildren(node.children, ctx);
|
|
48986
|
+
return `<nav class="${classes}"${styleAttr}>
|
|
48987
|
+
${content}
|
|
48988
|
+
</nav>`;
|
|
48989
|
+
}
|
|
48990
|
+
const items = node.items.map((item) => {
|
|
48991
|
+
if (typeof item === "string") {
|
|
48992
|
+
return `<a class="${ctx.prefix}-nav-link" href="#">${ctx.escapeHtml(item)}</a>`;
|
|
48993
|
+
}
|
|
48994
|
+
const linkClasses = ctx.buildClassString([
|
|
48995
|
+
`${ctx.prefix}-nav-link`,
|
|
48996
|
+
item.active ? `${ctx.prefix}-nav-link-active` : void 0,
|
|
48997
|
+
item.disabled ? `${ctx.prefix}-nav-link-disabled` : void 0
|
|
48998
|
+
]);
|
|
48999
|
+
const iconHtml = item.icon ? renderIconHtml(item.icon, ctx.prefix) + " " : "";
|
|
49000
|
+
return `<a class="${linkClasses}" href="${item.href || "#"}">${iconHtml}${ctx.escapeHtml(item.label)}</a>`;
|
|
49001
|
+
}).join("\n");
|
|
49002
|
+
return `<nav class="${classes}"${styleAttr}>
|
|
49003
|
+
${items}
|
|
49004
|
+
</nav>`;
|
|
49005
|
+
}
|
|
49006
|
+
function renderTabs(node, ctx) {
|
|
49007
|
+
const classes = ctx.buildClassString([
|
|
49008
|
+
`${ctx.prefix}-tabs`,
|
|
49009
|
+
...ctx.getCommonClasses(node)
|
|
49010
|
+
]);
|
|
49011
|
+
const styles = ctx.buildCommonStyles(node);
|
|
49012
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49013
|
+
const tabList = node.items.map((label, idx) => {
|
|
49014
|
+
const isActive = idx === (node.active || 0);
|
|
49015
|
+
const tabClasses = `${ctx.prefix}-tab${isActive ? ` ${ctx.prefix}-tab-active` : ""}`;
|
|
49016
|
+
return `<button class="${tabClasses}" role="tab" aria-selected="${isActive}">${ctx.escapeHtml(label)}</button>`;
|
|
49017
|
+
}).join("\n");
|
|
49018
|
+
return `<div class="${classes}"${styleAttr}>
|
|
49019
|
+
<div class="${ctx.prefix}-tab-list" role="tablist">
|
|
49020
|
+
${tabList}
|
|
49021
|
+
</div>
|
|
49022
|
+
</div>`;
|
|
49023
|
+
}
|
|
49024
|
+
function renderBreadcrumb(node, ctx) {
|
|
49025
|
+
const classes = ctx.buildClassString([
|
|
49026
|
+
`${ctx.prefix}-breadcrumb`,
|
|
49027
|
+
...ctx.getCommonClasses(node)
|
|
49028
|
+
]);
|
|
49029
|
+
const styles = ctx.buildCommonStyles(node);
|
|
49030
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49031
|
+
const items = node.items.map((item, idx) => {
|
|
49032
|
+
const isLast = idx === node.items.length - 1;
|
|
49033
|
+
if (typeof item === "string") {
|
|
49034
|
+
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>`;
|
|
49035
|
+
}
|
|
49036
|
+
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>`;
|
|
49037
|
+
}).join(" / ");
|
|
49038
|
+
return `<nav class="${classes}"${styleAttr} aria-label="Breadcrumb">${items}</nav>`;
|
|
49039
|
+
}
|
|
49040
|
+
|
|
49041
|
+
// src/renderer/html/semantic.ts
|
|
49042
|
+
function renderSemanticMarker(component, variant, prefix) {
|
|
49043
|
+
switch (component) {
|
|
49044
|
+
case "avatar":
|
|
49045
|
+
const avatarSize = variant || "sm";
|
|
49046
|
+
return `<span class="${prefix}-semantic-avatar ${prefix}-semantic-avatar-${avatarSize}" data-semantic="avatar" data-variant="${avatarSize}" aria-hidden="true"></span>`;
|
|
49047
|
+
case "dot":
|
|
49048
|
+
const dotVariant = variant || "default";
|
|
49049
|
+
return `<span class="${prefix}-semantic-dot ${prefix}-semantic-dot-${dotVariant}" data-semantic="dot" data-variant="${dotVariant}" aria-hidden="true"></span>`;
|
|
49050
|
+
case "icon":
|
|
49051
|
+
const iconName = variant || "default";
|
|
49052
|
+
return `<span class="${prefix}-semantic-icon" data-semantic="icon" data-variant="${iconName}" aria-hidden="true">[${iconName}]</span>`;
|
|
49053
|
+
default:
|
|
49054
|
+
return `<span class="${prefix}-semantic-unknown" data-semantic="${component}" data-variant="${variant || ""}">[${component}${variant ? ":" + variant : ""}]</span>`;
|
|
49055
|
+
}
|
|
49056
|
+
}
|
|
49057
|
+
function renderSemanticMarkerWithContent(component, variant, content, prefix, escapeHtml) {
|
|
49058
|
+
switch (component) {
|
|
49059
|
+
case "badge":
|
|
49060
|
+
const badgeVariant = variant || "default";
|
|
49061
|
+
const escapedContent = escapeHtml(content);
|
|
49062
|
+
return `<span class="${prefix}-semantic-badge ${prefix}-semantic-badge-${badgeVariant}" data-semantic="badge" data-variant="${badgeVariant}">${escapedContent}</span>`;
|
|
49063
|
+
default:
|
|
49064
|
+
return renderSemanticMarker(component, variant, prefix) + escapeHtml(content);
|
|
49065
|
+
}
|
|
49066
|
+
}
|
|
49067
|
+
function renderSemanticMarkers(text, prefix, escapeHtml) {
|
|
49068
|
+
const markerPattern = /\[([a-z]+)(?::([a-z0-9-]+))?\](\s*)/gi;
|
|
49069
|
+
let result = "";
|
|
49070
|
+
let lastIndex = 0;
|
|
49071
|
+
let match;
|
|
49072
|
+
while ((match = markerPattern.exec(text)) !== null) {
|
|
49073
|
+
if (match.index > lastIndex) {
|
|
49074
|
+
result += escapeHtml(text.substring(lastIndex, match.index));
|
|
49075
|
+
}
|
|
49076
|
+
const [fullMatch, component, variant] = match;
|
|
49077
|
+
const comp = component.toLowerCase();
|
|
49078
|
+
const varnt = variant?.toLowerCase();
|
|
49079
|
+
if (comp === "badge") {
|
|
49080
|
+
const afterMarker = text.substring(match.index + fullMatch.length);
|
|
49081
|
+
const contentMatch = afterMarker.match(/^([^\n\[]+?)(?=\n|\[|$)/);
|
|
49082
|
+
const badgeContent = contentMatch ? contentMatch[1].trim() : "";
|
|
49083
|
+
result += renderSemanticMarkerWithContent(comp, varnt, badgeContent, prefix, escapeHtml);
|
|
49084
|
+
lastIndex = match.index + fullMatch.length + (contentMatch ? contentMatch[0].length : 0);
|
|
49085
|
+
markerPattern.lastIndex = lastIndex;
|
|
49086
|
+
} else {
|
|
49087
|
+
result += renderSemanticMarker(comp, varnt, prefix);
|
|
49088
|
+
lastIndex = match.index + fullMatch.length;
|
|
49089
|
+
}
|
|
49090
|
+
}
|
|
49091
|
+
if (lastIndex < text.length) {
|
|
49092
|
+
result += escapeHtml(text.substring(lastIndex));
|
|
49093
|
+
}
|
|
49094
|
+
if (lastIndex === 0) {
|
|
49095
|
+
return escapeHtml(text);
|
|
49096
|
+
}
|
|
49097
|
+
return result;
|
|
49098
|
+
}
|
|
49099
|
+
function renderTableCellContent(content, prefix, escapeHtml) {
|
|
49100
|
+
const avatarMatch = content.match(/^\[avatar(?::([a-z0-9-]+))?\]\s*/i);
|
|
49101
|
+
if (avatarMatch) {
|
|
49102
|
+
const avatarVariant = avatarMatch[1]?.toLowerCase();
|
|
49103
|
+
const avatarHtml = renderSemanticMarker("avatar", avatarVariant, prefix);
|
|
49104
|
+
const restContent = content.slice(avatarMatch[0].length);
|
|
49105
|
+
const restHtml = renderSemanticMarkers(restContent, prefix, escapeHtml);
|
|
49106
|
+
const lines = restHtml.split("\n");
|
|
49107
|
+
const textHtml = lines.length > 1 ? lines.map((line) => `<span>${line}</span>`).join("") : restHtml;
|
|
49108
|
+
return `<div class="${prefix}-cell-avatar-layout">${avatarHtml}<div class="${prefix}-cell-avatar-text">${textHtml}</div></div>`;
|
|
49109
|
+
}
|
|
49110
|
+
const withMarkers = renderSemanticMarkers(content, prefix, escapeHtml);
|
|
49111
|
+
return withMarkers.replace(/\n/g, "<br>");
|
|
49112
|
+
}
|
|
49113
|
+
|
|
49114
|
+
// src/renderer/html/renderers/data.ts
|
|
49115
|
+
function renderTable(node, ctx) {
|
|
49116
|
+
const classes = ctx.buildClassString([
|
|
49117
|
+
`${ctx.prefix}-table`,
|
|
49118
|
+
node.striped ? `${ctx.prefix}-table-striped` : void 0,
|
|
49119
|
+
node.bordered ? `${ctx.prefix}-table-bordered` : void 0,
|
|
49120
|
+
node.hover ? `${ctx.prefix}-table-hover` : void 0,
|
|
49121
|
+
...ctx.getCommonClasses(node)
|
|
49122
|
+
]);
|
|
49123
|
+
const styles = ctx.buildCommonStyles(node);
|
|
49124
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49125
|
+
const thead = `<thead><tr>${node.columns.map((col) => `<th>${ctx.escapeHtml(col)}</th>`).join("")}</tr></thead>`;
|
|
49126
|
+
const tbody = `<tbody>${node.rows.map(
|
|
49127
|
+
(row) => `<tr>${row.map((cell) => {
|
|
49128
|
+
if (typeof cell === "string") {
|
|
49129
|
+
return `<td>${renderTableCellContent(cell, ctx.prefix, ctx.escapeHtml)}</td>`;
|
|
49130
|
+
}
|
|
49131
|
+
return `<td>${ctx.renderNode(cell)}</td>`;
|
|
49132
|
+
}).join("")}</tr>`
|
|
49133
|
+
).join("")}</tbody>`;
|
|
49134
|
+
return `<table class="${classes}"${styleAttr}>
|
|
49135
|
+
${thead}
|
|
49136
|
+
${tbody}
|
|
49137
|
+
</table>`;
|
|
49138
|
+
}
|
|
49139
|
+
function renderList(node, ctx) {
|
|
49140
|
+
const tag = node.ordered ? "ol" : "ul";
|
|
49141
|
+
const classes = ctx.buildClassString([
|
|
49142
|
+
`${ctx.prefix}-list`,
|
|
49143
|
+
node.ordered ? `${ctx.prefix}-list-ordered` : void 0,
|
|
49144
|
+
node.none ? `${ctx.prefix}-list-none` : void 0,
|
|
49145
|
+
...ctx.getCommonClasses(node)
|
|
49146
|
+
]);
|
|
49147
|
+
const styles = ctx.buildCommonStyles(node);
|
|
49148
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49149
|
+
const items = node.items.map((item) => {
|
|
49150
|
+
if (typeof item === "string") {
|
|
49151
|
+
return `<li class="${ctx.prefix}-list-item">${ctx.escapeHtml(item)}</li>`;
|
|
49152
|
+
}
|
|
49153
|
+
return `<li class="${ctx.prefix}-list-item">${ctx.escapeHtml(item.content)}</li>`;
|
|
49154
|
+
}).join("\n");
|
|
49155
|
+
return `<${tag} class="${classes}"${styleAttr}>
|
|
49156
|
+
${items}
|
|
49157
|
+
</${tag}>`;
|
|
49158
|
+
}
|
|
49159
|
+
|
|
49160
|
+
// src/renderer/html/renderers/divider.ts
|
|
49161
|
+
function renderDivider(node, ctx) {
|
|
49162
|
+
const styles = ctx.buildCommonStyles(node);
|
|
49163
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49164
|
+
return `<hr class="${ctx.prefix}-divider"${styleAttr} />`;
|
|
48166
49165
|
}
|
|
48167
49166
|
|
|
48168
49167
|
// src/renderer/html/index.ts
|
|
@@ -48204,8 +49203,97 @@ function resolveSizeValueToCss(value) {
|
|
|
48204
49203
|
return void 0;
|
|
48205
49204
|
}
|
|
48206
49205
|
var HtmlRenderer = class extends BaseRenderer {
|
|
49206
|
+
/**
|
|
49207
|
+
* Node type to renderer method mapping
|
|
49208
|
+
*/
|
|
49209
|
+
nodeRenderers;
|
|
48207
49210
|
constructor(options = {}) {
|
|
48208
49211
|
super(options);
|
|
49212
|
+
this.nodeRenderers = this.createNodeRenderers();
|
|
49213
|
+
}
|
|
49214
|
+
/**
|
|
49215
|
+
* Get render context for external renderer functions
|
|
49216
|
+
*/
|
|
49217
|
+
getRenderContext() {
|
|
49218
|
+
return {
|
|
49219
|
+
prefix: this.prefix,
|
|
49220
|
+
escapeHtml: this.escapeHtml.bind(this),
|
|
49221
|
+
buildClassString: this.buildClassString.bind(this),
|
|
49222
|
+
buildAttrsString: this.buildAttrsString.bind(this),
|
|
49223
|
+
buildCommonStyles: this.buildCommonStyles.bind(this),
|
|
49224
|
+
getCommonClasses: this.getCommonClasses.bind(this),
|
|
49225
|
+
renderChildren: this.renderChildren.bind(this),
|
|
49226
|
+
renderNode: this.renderNode.bind(this)
|
|
49227
|
+
};
|
|
49228
|
+
}
|
|
49229
|
+
/**
|
|
49230
|
+
* Get grid render context (extends RenderContext with buildColStyles)
|
|
49231
|
+
*/
|
|
49232
|
+
getGridRenderContext() {
|
|
49233
|
+
return {
|
|
49234
|
+
...this.getRenderContext(),
|
|
49235
|
+
buildColStyles: this.buildColStyles.bind(this)
|
|
49236
|
+
};
|
|
49237
|
+
}
|
|
49238
|
+
/**
|
|
49239
|
+
* Create the node renderer mapping
|
|
49240
|
+
*/
|
|
49241
|
+
createNodeRenderers() {
|
|
49242
|
+
return {
|
|
49243
|
+
// Layout nodes
|
|
49244
|
+
Page: (node) => this.renderPage(node),
|
|
49245
|
+
Header: (node) => this.renderHeader(node),
|
|
49246
|
+
Main: (node) => this.renderMain(node),
|
|
49247
|
+
Footer: (node) => this.renderFooter(node),
|
|
49248
|
+
Sidebar: (node) => this.renderSidebar(node),
|
|
49249
|
+
Section: (node) => this.renderSection(node),
|
|
49250
|
+
// Grid nodes
|
|
49251
|
+
Row: (node) => this.renderRow(node),
|
|
49252
|
+
Col: (node) => this.renderCol(node),
|
|
49253
|
+
// Container nodes
|
|
49254
|
+
Card: (node) => this.renderCard(node),
|
|
49255
|
+
Modal: (node) => this.renderModal(node),
|
|
49256
|
+
Drawer: (node) => this.renderDrawer(node),
|
|
49257
|
+
Accordion: (node) => this.renderAccordion(node),
|
|
49258
|
+
// Text nodes
|
|
49259
|
+
Text: (node) => this.renderText(node),
|
|
49260
|
+
Title: (node) => this.renderTitle(node),
|
|
49261
|
+
Link: (node) => this.renderLink(node),
|
|
49262
|
+
// Input nodes
|
|
49263
|
+
Input: (node) => this.renderInput(node),
|
|
49264
|
+
Textarea: (node) => this.renderTextarea(node),
|
|
49265
|
+
Select: (node) => this.renderSelect(node),
|
|
49266
|
+
Checkbox: (node) => this.renderCheckbox(node),
|
|
49267
|
+
Radio: (node) => this.renderRadio(node),
|
|
49268
|
+
Switch: (node) => this.renderSwitch(node),
|
|
49269
|
+
Slider: (node) => this.renderSlider(node),
|
|
49270
|
+
// Button
|
|
49271
|
+
Button: (node) => this.renderButton(node),
|
|
49272
|
+
// Display nodes
|
|
49273
|
+
Image: (node) => this.renderImage(node),
|
|
49274
|
+
Placeholder: (node) => this.renderPlaceholder(node),
|
|
49275
|
+
Avatar: (node) => this.renderAvatar(node),
|
|
49276
|
+
Badge: (node) => this.renderBadge(node),
|
|
49277
|
+
Icon: (node) => this.renderIcon(node),
|
|
49278
|
+
// Data nodes
|
|
49279
|
+
Table: (node) => this.renderTable(node),
|
|
49280
|
+
List: (node) => this.renderList(node),
|
|
49281
|
+
// Feedback nodes
|
|
49282
|
+
Alert: (node) => this.renderAlert(node),
|
|
49283
|
+
Toast: (node) => this.renderToast(node),
|
|
49284
|
+
Progress: (node) => this.renderProgress(node),
|
|
49285
|
+
Spinner: (node) => this.renderSpinner(node),
|
|
49286
|
+
// Overlay nodes
|
|
49287
|
+
Tooltip: (node) => this.renderTooltip(node),
|
|
49288
|
+
Popover: (node) => this.renderPopover(node),
|
|
49289
|
+
Dropdown: (node) => this.renderDropdown(node),
|
|
49290
|
+
// Navigation nodes
|
|
49291
|
+
Nav: (node) => this.renderNav(node),
|
|
49292
|
+
Tabs: (node) => this.renderTabs(node),
|
|
49293
|
+
Breadcrumb: (node) => this.renderBreadcrumb(node),
|
|
49294
|
+
// Other
|
|
49295
|
+
Divider: (node) => this.renderDivider(node)
|
|
49296
|
+
};
|
|
48209
49297
|
}
|
|
48210
49298
|
/**
|
|
48211
49299
|
* Render a page node
|
|
@@ -48234,7 +49322,7 @@ var HtmlRenderer = class extends BaseRenderer {
|
|
|
48234
49322
|
const title = node.title ? `<title>${this.escapeHtml(node.title)}</title>
|
|
48235
49323
|
` : "";
|
|
48236
49324
|
const commonStyles = this.buildCommonStyles(node);
|
|
48237
|
-
const viewportStyle = `width: ${viewport.width}px; height: ${viewport.height}px`;
|
|
49325
|
+
const viewportStyle = `position: relative; width: ${viewport.width}px; height: ${viewport.height}px; overflow: hidden`;
|
|
48238
49326
|
const combinedStyle = commonStyles ? `${viewportStyle}; ${commonStyles}` : viewportStyle;
|
|
48239
49327
|
const dataAttrs = `data-viewport-width="${viewport.width}" data-viewport-height="${viewport.height}" data-viewport-label="${viewport.label}"`;
|
|
48240
49328
|
return `<div class="${classes}" style="${combinedStyle}" ${dataAttrs}>
|
|
@@ -48245,104 +49333,11 @@ ${title}${children}
|
|
|
48245
49333
|
* Render any AST node
|
|
48246
49334
|
*/
|
|
48247
49335
|
renderNode(node) {
|
|
48248
|
-
|
|
48249
|
-
|
|
48250
|
-
|
|
48251
|
-
return this.renderPage(node);
|
|
48252
|
-
case "Header":
|
|
48253
|
-
return this.renderHeader(node);
|
|
48254
|
-
case "Main":
|
|
48255
|
-
return this.renderMain(node);
|
|
48256
|
-
case "Footer":
|
|
48257
|
-
return this.renderFooter(node);
|
|
48258
|
-
case "Sidebar":
|
|
48259
|
-
return this.renderSidebar(node);
|
|
48260
|
-
case "Section":
|
|
48261
|
-
return this.renderSection(node);
|
|
48262
|
-
// Grid nodes
|
|
48263
|
-
case "Row":
|
|
48264
|
-
return this.renderRow(node);
|
|
48265
|
-
case "Col":
|
|
48266
|
-
return this.renderCol(node);
|
|
48267
|
-
// Container nodes
|
|
48268
|
-
case "Card":
|
|
48269
|
-
return this.renderCard(node);
|
|
48270
|
-
case "Modal":
|
|
48271
|
-
return this.renderModal(node);
|
|
48272
|
-
case "Drawer":
|
|
48273
|
-
return this.renderDrawer(node);
|
|
48274
|
-
case "Accordion":
|
|
48275
|
-
return this.renderAccordion(node);
|
|
48276
|
-
// Text nodes
|
|
48277
|
-
case "Text":
|
|
48278
|
-
return this.renderText(node);
|
|
48279
|
-
case "Title":
|
|
48280
|
-
return this.renderTitle(node);
|
|
48281
|
-
case "Link":
|
|
48282
|
-
return this.renderLink(node);
|
|
48283
|
-
// Input nodes
|
|
48284
|
-
case "Input":
|
|
48285
|
-
return this.renderInput(node);
|
|
48286
|
-
case "Textarea":
|
|
48287
|
-
return this.renderTextarea(node);
|
|
48288
|
-
case "Select":
|
|
48289
|
-
return this.renderSelect(node);
|
|
48290
|
-
case "Checkbox":
|
|
48291
|
-
return this.renderCheckbox(node);
|
|
48292
|
-
case "Radio":
|
|
48293
|
-
return this.renderRadio(node);
|
|
48294
|
-
case "Switch":
|
|
48295
|
-
return this.renderSwitch(node);
|
|
48296
|
-
case "Slider":
|
|
48297
|
-
return this.renderSlider(node);
|
|
48298
|
-
// Button
|
|
48299
|
-
case "Button":
|
|
48300
|
-
return this.renderButton(node);
|
|
48301
|
-
// Display nodes
|
|
48302
|
-
case "Image":
|
|
48303
|
-
return this.renderImage(node);
|
|
48304
|
-
case "Placeholder":
|
|
48305
|
-
return this.renderPlaceholder(node);
|
|
48306
|
-
case "Avatar":
|
|
48307
|
-
return this.renderAvatar(node);
|
|
48308
|
-
case "Badge":
|
|
48309
|
-
return this.renderBadge(node);
|
|
48310
|
-
case "Icon":
|
|
48311
|
-
return this.renderIcon(node);
|
|
48312
|
-
// Data nodes
|
|
48313
|
-
case "Table":
|
|
48314
|
-
return this.renderTable(node);
|
|
48315
|
-
case "List":
|
|
48316
|
-
return this.renderList(node);
|
|
48317
|
-
// Feedback nodes
|
|
48318
|
-
case "Alert":
|
|
48319
|
-
return this.renderAlert(node);
|
|
48320
|
-
case "Toast":
|
|
48321
|
-
return this.renderToast(node);
|
|
48322
|
-
case "Progress":
|
|
48323
|
-
return this.renderProgress(node);
|
|
48324
|
-
case "Spinner":
|
|
48325
|
-
return this.renderSpinner(node);
|
|
48326
|
-
// Overlay nodes
|
|
48327
|
-
case "Tooltip":
|
|
48328
|
-
return this.renderTooltip(node);
|
|
48329
|
-
case "Popover":
|
|
48330
|
-
return this.renderPopover(node);
|
|
48331
|
-
case "Dropdown":
|
|
48332
|
-
return this.renderDropdown(node);
|
|
48333
|
-
// Navigation nodes
|
|
48334
|
-
case "Nav":
|
|
48335
|
-
return this.renderNav(node);
|
|
48336
|
-
case "Tabs":
|
|
48337
|
-
return this.renderTabs(node);
|
|
48338
|
-
case "Breadcrumb":
|
|
48339
|
-
return this.renderBreadcrumb(node);
|
|
48340
|
-
// Other
|
|
48341
|
-
case "Divider":
|
|
48342
|
-
return this.renderDivider(node);
|
|
48343
|
-
default:
|
|
48344
|
-
return `<!-- Unknown node type: ${node.type} -->`;
|
|
49336
|
+
const renderer = this.nodeRenderers[node.type];
|
|
49337
|
+
if (renderer) {
|
|
49338
|
+
return renderer(node);
|
|
48345
49339
|
}
|
|
49340
|
+
return `<!-- Unknown node type: ${node.type} -->`;
|
|
48346
49341
|
}
|
|
48347
49342
|
/**
|
|
48348
49343
|
* Render children nodes
|
|
@@ -48385,106 +49380,36 @@ ${title}${children}
|
|
|
48385
49380
|
// Layout Node Renderers
|
|
48386
49381
|
// ===========================================
|
|
48387
49382
|
renderHeader(node) {
|
|
48388
|
-
|
|
48389
|
-
`${this.prefix}-header`,
|
|
48390
|
-
node.border === false ? `${this.prefix}-no-border` : void 0,
|
|
48391
|
-
...this.getCommonClasses(node)
|
|
48392
|
-
]);
|
|
48393
|
-
const styles = this.buildCommonStyles(node);
|
|
48394
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48395
|
-
const children = this.renderChildren(node.children);
|
|
48396
|
-
return `<header class="${classes}"${styleAttr}>
|
|
48397
|
-
${children}
|
|
48398
|
-
</header>`;
|
|
49383
|
+
return renderHeader(node, this.getRenderContext());
|
|
48399
49384
|
}
|
|
48400
49385
|
renderMain(node) {
|
|
48401
|
-
|
|
48402
|
-
`${this.prefix}-main`,
|
|
48403
|
-
...this.getCommonClasses(node)
|
|
48404
|
-
]);
|
|
48405
|
-
const styles = this.buildCommonStyles(node);
|
|
48406
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48407
|
-
const children = this.renderChildren(node.children);
|
|
48408
|
-
return `<main class="${classes}"${styleAttr}>
|
|
48409
|
-
${children}
|
|
48410
|
-
</main>`;
|
|
49386
|
+
return renderMain(node, this.getRenderContext());
|
|
48411
49387
|
}
|
|
48412
49388
|
renderFooter(node) {
|
|
48413
|
-
|
|
48414
|
-
`${this.prefix}-footer`,
|
|
48415
|
-
node.border === false ? `${this.prefix}-no-border` : void 0,
|
|
48416
|
-
...this.getCommonClasses(node)
|
|
48417
|
-
]);
|
|
48418
|
-
const styles = this.buildCommonStyles(node);
|
|
48419
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48420
|
-
const children = this.renderChildren(node.children);
|
|
48421
|
-
return `<footer class="${classes}"${styleAttr}>
|
|
48422
|
-
${children}
|
|
48423
|
-
</footer>`;
|
|
49389
|
+
return renderFooter(node, this.getRenderContext());
|
|
48424
49390
|
}
|
|
48425
49391
|
renderSidebar(node) {
|
|
48426
|
-
|
|
48427
|
-
`${this.prefix}-sidebar`,
|
|
48428
|
-
node.position === "right" ? `${this.prefix}-sidebar-right` : void 0,
|
|
48429
|
-
...this.getCommonClasses(node)
|
|
48430
|
-
]);
|
|
48431
|
-
const styles = this.buildCommonStyles(node);
|
|
48432
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48433
|
-
const children = this.renderChildren(node.children);
|
|
48434
|
-
return `<aside class="${classes}"${styleAttr}>
|
|
48435
|
-
${children}
|
|
48436
|
-
</aside>`;
|
|
49392
|
+
return renderSidebar(node, this.getRenderContext());
|
|
48437
49393
|
}
|
|
48438
49394
|
renderSection(node) {
|
|
48439
|
-
|
|
48440
|
-
`${this.prefix}-section`,
|
|
48441
|
-
...this.getCommonClasses(node)
|
|
48442
|
-
]);
|
|
48443
|
-
const styles = this.buildCommonStyles(node);
|
|
48444
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48445
|
-
const title = node.title ? `<h2 class="${this.prefix}-title">${this.escapeHtml(node.title)}</h2>
|
|
48446
|
-
` : "";
|
|
48447
|
-
const children = this.renderChildren(node.children);
|
|
48448
|
-
return `<section class="${classes}"${styleAttr}>
|
|
48449
|
-
${title}${children}
|
|
48450
|
-
</section>`;
|
|
49395
|
+
return renderSection(node, this.getRenderContext());
|
|
48451
49396
|
}
|
|
48452
49397
|
// ===========================================
|
|
48453
49398
|
// Grid Node Renderers
|
|
48454
49399
|
// ===========================================
|
|
48455
49400
|
renderRow(node) {
|
|
48456
|
-
|
|
48457
|
-
`${this.prefix}-row`,
|
|
48458
|
-
...this.getCommonClasses(node)
|
|
48459
|
-
]);
|
|
48460
|
-
const styles = this.buildCommonStyles(node);
|
|
48461
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48462
|
-
const children = this.renderChildren(node.children);
|
|
48463
|
-
return `<div class="${classes}"${styleAttr}>
|
|
48464
|
-
${children}
|
|
48465
|
-
</div>`;
|
|
49401
|
+
return renderRow(node, this.getRenderContext());
|
|
48466
49402
|
}
|
|
48467
49403
|
renderCol(node) {
|
|
48468
|
-
|
|
48469
|
-
`${this.prefix}-col`,
|
|
48470
|
-
node.span ? `${this.prefix}-col-${node.span}` : void 0,
|
|
48471
|
-
// Responsive breakpoint classes
|
|
48472
|
-
node.sm ? `${this.prefix}-col-sm-${node.sm}` : void 0,
|
|
48473
|
-
node.md ? `${this.prefix}-col-md-${node.md}` : void 0,
|
|
48474
|
-
node.lg ? `${this.prefix}-col-lg-${node.lg}` : void 0,
|
|
48475
|
-
node.xl ? `${this.prefix}-col-xl-${node.xl}` : void 0,
|
|
48476
|
-
...this.getCommonClasses(node)
|
|
48477
|
-
]);
|
|
48478
|
-
const styles = this.buildColStyles(node);
|
|
48479
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48480
|
-
const children = this.renderChildren(node.children);
|
|
48481
|
-
return `<div class="${classes}"${styleAttr}>
|
|
48482
|
-
${children}
|
|
48483
|
-
</div>`;
|
|
49404
|
+
return renderCol(node, this.getGridRenderContext());
|
|
48484
49405
|
}
|
|
48485
49406
|
/**
|
|
48486
49407
|
* Build common inline styles for all values
|
|
48487
49408
|
*
|
|
49409
|
+
* Position values (x, y) for absolute positioning:
|
|
49410
|
+
* - When x or y is specified, element gets position: absolute
|
|
49411
|
+
* - x → left, y → top
|
|
49412
|
+
*
|
|
48488
49413
|
* Spacing values (p, m, gap) use token system:
|
|
48489
49414
|
* - number: spacing token (e.g., p=4 → padding: 16px from token table)
|
|
48490
49415
|
* - ValueWithUnit: direct CSS value (e.g., p=16px → padding: 16px)
|
|
@@ -48499,6 +49424,33 @@ ${children}
|
|
|
48499
49424
|
*/
|
|
48500
49425
|
buildCommonStyles(props) {
|
|
48501
49426
|
const styles = [];
|
|
49427
|
+
this.buildPositionStyles(props, styles);
|
|
49428
|
+
this.buildSizeStyles(props, styles);
|
|
49429
|
+
this.buildPaddingStyles(props, styles);
|
|
49430
|
+
this.buildMarginStyles(props, styles);
|
|
49431
|
+
this.buildGapStyles(props, styles);
|
|
49432
|
+
return styles.join("; ");
|
|
49433
|
+
}
|
|
49434
|
+
/**
|
|
49435
|
+
* Build position styles (absolute positioning)
|
|
49436
|
+
*/
|
|
49437
|
+
buildPositionStyles(props, styles) {
|
|
49438
|
+
if (props.x !== void 0 || props.y !== void 0) {
|
|
49439
|
+
styles.push("position: absolute");
|
|
49440
|
+
if (props.x !== void 0) {
|
|
49441
|
+
const xValue = resolveSizeValueToCss(props.x);
|
|
49442
|
+
if (xValue) styles.push(`left: ${xValue}`);
|
|
49443
|
+
}
|
|
49444
|
+
if (props.y !== void 0) {
|
|
49445
|
+
const yValue = resolveSizeValueToCss(props.y);
|
|
49446
|
+
if (yValue) styles.push(`top: ${yValue}`);
|
|
49447
|
+
}
|
|
49448
|
+
}
|
|
49449
|
+
}
|
|
49450
|
+
/**
|
|
49451
|
+
* Build size styles (width, height, min/max)
|
|
49452
|
+
*/
|
|
49453
|
+
buildSizeStyles(props, styles) {
|
|
48502
49454
|
const wValue = resolveSizeValueToCss(props.w);
|
|
48503
49455
|
if (wValue) {
|
|
48504
49456
|
styles.push(`width: ${wValue}`);
|
|
@@ -48524,6 +49476,11 @@ ${children}
|
|
|
48524
49476
|
if (maxHValue) {
|
|
48525
49477
|
styles.push(`max-height: ${maxHValue}`);
|
|
48526
49478
|
}
|
|
49479
|
+
}
|
|
49480
|
+
/**
|
|
49481
|
+
* Build padding styles (p, px, py, pt, pr, pb, pl)
|
|
49482
|
+
*/
|
|
49483
|
+
buildPaddingStyles(props, styles) {
|
|
48527
49484
|
const pValue = resolveSpacingValue(props.p);
|
|
48528
49485
|
if (pValue) {
|
|
48529
49486
|
styles.push(`padding: ${pValue}`);
|
|
@@ -48554,6 +49511,11 @@ ${children}
|
|
|
48554
49511
|
if (plValue) {
|
|
48555
49512
|
styles.push(`padding-left: ${plValue}`);
|
|
48556
49513
|
}
|
|
49514
|
+
}
|
|
49515
|
+
/**
|
|
49516
|
+
* Build margin styles (m, mx, my, mt, mr, mb, ml)
|
|
49517
|
+
*/
|
|
49518
|
+
buildMarginStyles(props, styles) {
|
|
48557
49519
|
const mValue = resolveSpacingValue(props.m);
|
|
48558
49520
|
if (mValue) {
|
|
48559
49521
|
styles.push(`margin: ${mValue}`);
|
|
@@ -48584,11 +49546,15 @@ ${children}
|
|
|
48584
49546
|
if (mlValue) {
|
|
48585
49547
|
styles.push(`margin-left: ${mlValue}`);
|
|
48586
49548
|
}
|
|
49549
|
+
}
|
|
49550
|
+
/**
|
|
49551
|
+
* Build gap styles
|
|
49552
|
+
*/
|
|
49553
|
+
buildGapStyles(props, styles) {
|
|
48587
49554
|
const gapValue = resolveSpacingValue(props.gap);
|
|
48588
49555
|
if (gapValue) {
|
|
48589
49556
|
styles.push(`gap: ${gapValue}`);
|
|
48590
49557
|
}
|
|
48591
|
-
return styles.join("; ");
|
|
48592
49558
|
}
|
|
48593
49559
|
/**
|
|
48594
49560
|
* Build inline styles for Col node (extends common styles with order)
|
|
@@ -48608,1532 +49574,136 @@ ${children}
|
|
|
48608
49574
|
// Container Node Renderers
|
|
48609
49575
|
// ===========================================
|
|
48610
49576
|
renderCard(node) {
|
|
48611
|
-
|
|
48612
|
-
`${this.prefix}-card`,
|
|
48613
|
-
node.shadow ? `${this.prefix}-card-shadow-${node.shadow}` : void 0,
|
|
48614
|
-
...this.getCommonClasses(node)
|
|
48615
|
-
]);
|
|
48616
|
-
const styles = this.buildCommonStyles(node);
|
|
48617
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48618
|
-
const title = node.title ? `<h3 class="${this.prefix}-title">${this.escapeHtml(node.title)}</h3>
|
|
48619
|
-
` : "";
|
|
48620
|
-
const children = this.renderChildren(node.children);
|
|
48621
|
-
return `<div class="${classes}"${styleAttr}>
|
|
48622
|
-
${title}${children}
|
|
48623
|
-
</div>`;
|
|
49577
|
+
return renderCard(node, this.getRenderContext());
|
|
48624
49578
|
}
|
|
48625
49579
|
renderModal(node) {
|
|
48626
|
-
|
|
48627
|
-
`${this.prefix}-modal`,
|
|
48628
|
-
...this.getCommonClasses(node)
|
|
48629
|
-
]);
|
|
48630
|
-
const styles = this.buildCommonStyles(node);
|
|
48631
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48632
|
-
const title = node.title ? `<h2 class="${this.prefix}-title">${this.escapeHtml(node.title)}</h2>
|
|
48633
|
-
` : "";
|
|
48634
|
-
const children = this.renderChildren(node.children);
|
|
48635
|
-
return `<div class="${this.prefix}-modal-backdrop">
|
|
48636
|
-
<div class="${classes}"${styleAttr} role="dialog" aria-modal="true">
|
|
48637
|
-
${title}${children}
|
|
48638
|
-
</div>
|
|
48639
|
-
</div>`;
|
|
49580
|
+
return renderModal(node, this.getRenderContext());
|
|
48640
49581
|
}
|
|
48641
49582
|
renderDrawer(node) {
|
|
48642
|
-
|
|
48643
|
-
const classes = this.buildClassString([
|
|
48644
|
-
`${this.prefix}-drawer`,
|
|
48645
|
-
`${this.prefix}-drawer-${position}`,
|
|
48646
|
-
...this.getCommonClasses(node)
|
|
48647
|
-
]);
|
|
48648
|
-
const styles = this.buildCommonStyles(node);
|
|
48649
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48650
|
-
const title = node.title ? `<h2 class="${this.prefix}-title">${this.escapeHtml(node.title)}</h2>
|
|
48651
|
-
` : "";
|
|
48652
|
-
const children = this.renderChildren(node.children);
|
|
48653
|
-
return `<aside class="${classes}"${styleAttr}>
|
|
48654
|
-
${title}${children}
|
|
48655
|
-
</aside>`;
|
|
49583
|
+
return renderDrawer(node, this.getRenderContext());
|
|
48656
49584
|
}
|
|
48657
49585
|
renderAccordion(node) {
|
|
48658
|
-
|
|
48659
|
-
`${this.prefix}-accordion`,
|
|
48660
|
-
...this.getCommonClasses(node)
|
|
48661
|
-
]);
|
|
48662
|
-
const styles = this.buildCommonStyles(node);
|
|
48663
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48664
|
-
const title = node.title ? `<button class="${this.prefix}-accordion-header">${this.escapeHtml(node.title)}</button>
|
|
48665
|
-
` : "";
|
|
48666
|
-
const children = this.renderChildren(node.children);
|
|
48667
|
-
return `<div class="${classes}"${styleAttr}>
|
|
48668
|
-
${title}<div class="${this.prefix}-accordion-content">
|
|
48669
|
-
${children}
|
|
48670
|
-
</div>
|
|
48671
|
-
</div>`;
|
|
49586
|
+
return renderAccordion(node, this.getRenderContext());
|
|
48672
49587
|
}
|
|
48673
49588
|
// ===========================================
|
|
48674
49589
|
// Text Node Renderers
|
|
48675
49590
|
// ===========================================
|
|
48676
49591
|
renderText(node) {
|
|
48677
|
-
|
|
48678
|
-
`${this.prefix}-text`,
|
|
48679
|
-
node.size ? `${this.prefix}-text-${node.size}` : void 0,
|
|
48680
|
-
node.weight ? `${this.prefix}-text-${node.weight}` : void 0,
|
|
48681
|
-
node.align ? `${this.prefix}-text-${node.align}` : void 0,
|
|
48682
|
-
node.muted ? `${this.prefix}-text-muted` : void 0,
|
|
48683
|
-
...this.getCommonClasses(node)
|
|
48684
|
-
]);
|
|
48685
|
-
const styles = this.buildCommonStyles(node);
|
|
48686
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48687
|
-
return `<p class="${classes}"${styleAttr}>${this.escapeHtml(node.content)}</p>`;
|
|
49592
|
+
return renderText(node, this.getRenderContext());
|
|
48688
49593
|
}
|
|
48689
49594
|
renderTitle(node) {
|
|
48690
|
-
|
|
48691
|
-
const tag = `h${level}`;
|
|
48692
|
-
const classes = this.buildClassString([
|
|
48693
|
-
`${this.prefix}-title`,
|
|
48694
|
-
node.size ? `${this.prefix}-text-${node.size}` : void 0,
|
|
48695
|
-
node.align ? `${this.prefix}-text-${node.align}` : void 0,
|
|
48696
|
-
...this.getCommonClasses(node)
|
|
48697
|
-
]);
|
|
48698
|
-
const styles = this.buildCommonStyles(node);
|
|
48699
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48700
|
-
return `<${tag} class="${classes}"${styleAttr}>${this.escapeHtml(node.content)}</${tag}>`;
|
|
49595
|
+
return renderTitle(node, this.getRenderContext());
|
|
48701
49596
|
}
|
|
48702
49597
|
renderLink(node) {
|
|
48703
|
-
|
|
48704
|
-
`${this.prefix}-link`,
|
|
48705
|
-
...this.getCommonClasses(node)
|
|
48706
|
-
]);
|
|
48707
|
-
const styles = this.buildCommonStyles(node);
|
|
48708
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48709
|
-
const attrs = {
|
|
48710
|
-
class: classes,
|
|
48711
|
-
href: node.href || "#"
|
|
48712
|
-
};
|
|
48713
|
-
if (node.external) {
|
|
48714
|
-
attrs.target = "_blank";
|
|
48715
|
-
attrs.rel = "noopener noreferrer";
|
|
48716
|
-
}
|
|
48717
|
-
return `<a${this.buildAttrsString(attrs)}${styleAttr}>${this.escapeHtml(node.content)}</a>`;
|
|
49598
|
+
return renderLink(node, this.getRenderContext());
|
|
48718
49599
|
}
|
|
48719
49600
|
// ===========================================
|
|
48720
49601
|
// Input Node Renderers
|
|
48721
49602
|
// ===========================================
|
|
48722
49603
|
renderInput(node) {
|
|
48723
|
-
|
|
48724
|
-
`${this.prefix}-input`,
|
|
48725
|
-
node.icon ? `${this.prefix}-input-with-icon` : void 0,
|
|
48726
|
-
...this.getCommonClasses(node)
|
|
48727
|
-
]);
|
|
48728
|
-
const styles = this.buildCommonStyles(node);
|
|
48729
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48730
|
-
const attrs = {
|
|
48731
|
-
class: inputClasses,
|
|
48732
|
-
type: node.inputType || "text",
|
|
48733
|
-
placeholder: node.placeholder,
|
|
48734
|
-
value: node.value,
|
|
48735
|
-
disabled: node.disabled,
|
|
48736
|
-
required: node.required,
|
|
48737
|
-
readonly: node.readonly
|
|
48738
|
-
};
|
|
48739
|
-
const inputElement = `<input${this.buildAttrsString(attrs)} />`;
|
|
48740
|
-
if (node.icon) {
|
|
48741
|
-
const iconData = getIconData(node.icon);
|
|
48742
|
-
let iconHtml;
|
|
48743
|
-
if (iconData) {
|
|
48744
|
-
iconHtml = renderIconSvg(iconData, 16, 2, `${this.prefix}-input-icon`);
|
|
48745
|
-
} else {
|
|
48746
|
-
iconHtml = `<span class="${this.prefix}-input-icon">[${this.escapeHtml(node.icon)}]</span>`;
|
|
48747
|
-
}
|
|
48748
|
-
const wrapperClasses = this.buildClassString([`${this.prefix}-input-wrapper`]);
|
|
48749
|
-
const wrapper = `<div class="${wrapperClasses}"${styleAttr}>${iconHtml}${inputElement}</div>`;
|
|
48750
|
-
if (node.label) {
|
|
48751
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48752
|
-
${wrapper}`;
|
|
48753
|
-
}
|
|
48754
|
-
return wrapper;
|
|
48755
|
-
}
|
|
48756
|
-
const input = `<input${this.buildAttrsString(attrs)}${styleAttr} />`;
|
|
48757
|
-
if (node.label) {
|
|
48758
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48759
|
-
${input}`;
|
|
48760
|
-
}
|
|
48761
|
-
return input;
|
|
49604
|
+
return renderInput(node, this.getRenderContext());
|
|
48762
49605
|
}
|
|
48763
49606
|
renderTextarea(node) {
|
|
48764
|
-
|
|
48765
|
-
`${this.prefix}-input`,
|
|
48766
|
-
...this.getCommonClasses(node)
|
|
48767
|
-
]);
|
|
48768
|
-
const styles = this.buildCommonStyles(node);
|
|
48769
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48770
|
-
const attrs = {
|
|
48771
|
-
class: classes,
|
|
48772
|
-
placeholder: node.placeholder,
|
|
48773
|
-
disabled: node.disabled,
|
|
48774
|
-
required: node.required,
|
|
48775
|
-
rows: node.rows?.toString()
|
|
48776
|
-
};
|
|
48777
|
-
const textarea = `<textarea${this.buildAttrsString(attrs)}${styleAttr}>${this.escapeHtml(node.value || "")}</textarea>`;
|
|
48778
|
-
if (node.label) {
|
|
48779
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48780
|
-
${textarea}`;
|
|
48781
|
-
}
|
|
48782
|
-
return textarea;
|
|
49607
|
+
return renderTextarea(node, this.getRenderContext());
|
|
48783
49608
|
}
|
|
48784
49609
|
renderSelect(node) {
|
|
48785
|
-
|
|
48786
|
-
`${this.prefix}-input`,
|
|
48787
|
-
...this.getCommonClasses(node)
|
|
48788
|
-
]);
|
|
48789
|
-
const styles = this.buildCommonStyles(node);
|
|
48790
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48791
|
-
const attrs = {
|
|
48792
|
-
class: classes,
|
|
48793
|
-
disabled: node.disabled,
|
|
48794
|
-
required: node.required
|
|
48795
|
-
};
|
|
48796
|
-
const options = node.options.map((opt) => {
|
|
48797
|
-
if (typeof opt === "string") {
|
|
48798
|
-
const selected2 = opt === node.value ? " selected" : "";
|
|
48799
|
-
return `<option value="${this.escapeHtml(opt)}"${selected2}>${this.escapeHtml(opt)}</option>`;
|
|
48800
|
-
}
|
|
48801
|
-
const selected = opt.value === node.value ? " selected" : "";
|
|
48802
|
-
return `<option value="${this.escapeHtml(opt.value)}"${selected}>${this.escapeHtml(opt.label)}</option>`;
|
|
48803
|
-
}).join("\n");
|
|
48804
|
-
const placeholder = node.placeholder ? `<option value="" disabled selected>${this.escapeHtml(node.placeholder)}</option>
|
|
48805
|
-
` : "";
|
|
48806
|
-
const select = `<select${this.buildAttrsString(attrs)}${styleAttr}>
|
|
48807
|
-
${placeholder}${options}
|
|
48808
|
-
</select>`;
|
|
48809
|
-
if (node.label) {
|
|
48810
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48811
|
-
${select}`;
|
|
48812
|
-
}
|
|
48813
|
-
return select;
|
|
49610
|
+
return renderSelect(node, this.getRenderContext());
|
|
48814
49611
|
}
|
|
48815
49612
|
renderCheckbox(node) {
|
|
48816
|
-
|
|
48817
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48818
|
-
const attrs = {
|
|
48819
|
-
type: "checkbox",
|
|
48820
|
-
checked: node.checked,
|
|
48821
|
-
disabled: node.disabled
|
|
48822
|
-
};
|
|
48823
|
-
const checkbox = `<input${this.buildAttrsString(attrs)} />`;
|
|
48824
|
-
if (node.label) {
|
|
48825
|
-
return `<label class="${this.prefix}-checkbox"${styleAttr}>${checkbox}<span>${this.escapeHtml(node.label)}</span></label>`;
|
|
48826
|
-
}
|
|
48827
|
-
return checkbox;
|
|
49613
|
+
return renderCheckbox(node, this.getRenderContext());
|
|
48828
49614
|
}
|
|
48829
49615
|
renderRadio(node) {
|
|
48830
|
-
|
|
48831
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48832
|
-
const attrs = {
|
|
48833
|
-
type: "radio",
|
|
48834
|
-
name: node.name,
|
|
48835
|
-
checked: node.checked,
|
|
48836
|
-
disabled: node.disabled
|
|
48837
|
-
};
|
|
48838
|
-
const radio = `<input${this.buildAttrsString(attrs)} />`;
|
|
48839
|
-
if (node.label) {
|
|
48840
|
-
return `<label class="${this.prefix}-radio"${styleAttr}>${radio}<span>${this.escapeHtml(node.label)}</span></label>`;
|
|
48841
|
-
}
|
|
48842
|
-
return radio;
|
|
49616
|
+
return renderRadio(node, this.getRenderContext());
|
|
48843
49617
|
}
|
|
48844
49618
|
renderSwitch(node) {
|
|
48845
|
-
|
|
48846
|
-
`${this.prefix}-switch`,
|
|
48847
|
-
...this.getCommonClasses(node)
|
|
48848
|
-
]);
|
|
48849
|
-
const styles = this.buildCommonStyles(node);
|
|
48850
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48851
|
-
const attrs = {
|
|
48852
|
-
type: "checkbox",
|
|
48853
|
-
role: "switch",
|
|
48854
|
-
checked: node.checked,
|
|
48855
|
-
disabled: node.disabled
|
|
48856
|
-
};
|
|
48857
|
-
const switchEl = `<input${this.buildAttrsString(attrs)} />`;
|
|
48858
|
-
if (node.label) {
|
|
48859
|
-
return `<label class="${classes}"${styleAttr}>${switchEl} ${this.escapeHtml(node.label)}</label>`;
|
|
48860
|
-
}
|
|
48861
|
-
return `<label class="${classes}"${styleAttr}>${switchEl}</label>`;
|
|
49619
|
+
return renderSwitch(node, this.getRenderContext());
|
|
48862
49620
|
}
|
|
48863
49621
|
renderSlider(node) {
|
|
48864
|
-
|
|
48865
|
-
`${this.prefix}-slider`,
|
|
48866
|
-
...this.getCommonClasses(node)
|
|
48867
|
-
]);
|
|
48868
|
-
const styles = this.buildCommonStyles(node);
|
|
48869
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48870
|
-
const attrs = {
|
|
48871
|
-
class: classes,
|
|
48872
|
-
type: "range",
|
|
48873
|
-
min: node.min?.toString(),
|
|
48874
|
-
max: node.max?.toString(),
|
|
48875
|
-
step: node.step?.toString(),
|
|
48876
|
-
value: node.value?.toString(),
|
|
48877
|
-
disabled: node.disabled
|
|
48878
|
-
};
|
|
48879
|
-
const slider = `<input${this.buildAttrsString(attrs)}${styleAttr} />`;
|
|
48880
|
-
if (node.label) {
|
|
48881
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48882
|
-
${slider}`;
|
|
48883
|
-
}
|
|
48884
|
-
return slider;
|
|
49622
|
+
return renderSlider(node, this.getRenderContext());
|
|
48885
49623
|
}
|
|
48886
49624
|
// ===========================================
|
|
48887
49625
|
// Button Renderer
|
|
48888
49626
|
// ===========================================
|
|
48889
49627
|
renderButton(node) {
|
|
48890
|
-
|
|
48891
|
-
const classes = this.buildClassString([
|
|
48892
|
-
`${this.prefix}-button`,
|
|
48893
|
-
node.primary ? `${this.prefix}-button-primary` : void 0,
|
|
48894
|
-
node.secondary ? `${this.prefix}-button-secondary` : void 0,
|
|
48895
|
-
node.outline ? `${this.prefix}-button-outline` : void 0,
|
|
48896
|
-
node.ghost ? `${this.prefix}-button-ghost` : void 0,
|
|
48897
|
-
node.danger ? `${this.prefix}-button-danger` : void 0,
|
|
48898
|
-
node.size ? `${this.prefix}-button-${node.size}` : void 0,
|
|
48899
|
-
node.disabled ? `${this.prefix}-button-disabled` : void 0,
|
|
48900
|
-
node.loading ? `${this.prefix}-button-loading` : void 0,
|
|
48901
|
-
isIconOnly ? `${this.prefix}-button-icon-only` : void 0,
|
|
48902
|
-
...this.getCommonClasses(node)
|
|
48903
|
-
]);
|
|
48904
|
-
const styles = this.buildCommonStyles(node);
|
|
48905
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48906
|
-
const attrs = {
|
|
48907
|
-
class: classes,
|
|
48908
|
-
disabled: node.disabled
|
|
48909
|
-
};
|
|
48910
|
-
let icon = "";
|
|
48911
|
-
if (node.icon) {
|
|
48912
|
-
const iconData = getIconData(node.icon);
|
|
48913
|
-
if (iconData) {
|
|
48914
|
-
icon = renderIconSvg(iconData, 16, 2, `${this.prefix}-icon`);
|
|
48915
|
-
} else {
|
|
48916
|
-
icon = `<span class="${this.prefix}-icon">[${this.escapeHtml(node.icon)}]</span>`;
|
|
48917
|
-
}
|
|
48918
|
-
}
|
|
48919
|
-
const loading = node.loading ? `<span class="${this.prefix}-spinner ${this.prefix}-spinner-sm"></span>` : "";
|
|
48920
|
-
const content = this.escapeHtml(node.content);
|
|
48921
|
-
return `<button${this.buildAttrsString(attrs)}${styleAttr}>${loading}${icon}${content}</button>`;
|
|
49628
|
+
return renderButton(node, this.getRenderContext());
|
|
48922
49629
|
}
|
|
48923
49630
|
// ===========================================
|
|
48924
49631
|
// Display Node Renderers
|
|
48925
49632
|
// ===========================================
|
|
48926
49633
|
renderImage(node) {
|
|
48927
|
-
|
|
48928
|
-
`${this.prefix}-image`,
|
|
48929
|
-
...this.getCommonClasses(node)
|
|
48930
|
-
]);
|
|
48931
|
-
const styles = this.buildCommonStyles(node);
|
|
48932
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48933
|
-
if (node.src) {
|
|
48934
|
-
const attrs = {
|
|
48935
|
-
class: classes,
|
|
48936
|
-
src: node.src,
|
|
48937
|
-
alt: node.alt || "Image"
|
|
48938
|
-
};
|
|
48939
|
-
const imgStyleAttr = styles ? `; ${styles}` : "";
|
|
48940
|
-
return `<img${this.buildAttrsString(attrs)}${imgStyleAttr ? ` style="${imgStyleAttr.slice(2)}"` : ""} />`;
|
|
48941
|
-
}
|
|
48942
|
-
const label = node.alt || "Image";
|
|
48943
|
-
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>`;
|
|
48944
|
-
return `<div class="${classes}"${styleAttr} role="img" aria-label="${this.escapeHtml(label)}">${icon}<span>${this.escapeHtml(label)}</span></div>`;
|
|
49634
|
+
return renderImage(node, this.getRenderContext());
|
|
48945
49635
|
}
|
|
48946
49636
|
renderPlaceholder(node) {
|
|
48947
|
-
|
|
48948
|
-
`${this.prefix}-placeholder`,
|
|
48949
|
-
...this.getCommonClasses(node)
|
|
48950
|
-
]);
|
|
48951
|
-
const styles = this.buildCommonStyles(node);
|
|
48952
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48953
|
-
const label = node.label ? this.escapeHtml(node.label) : "Placeholder";
|
|
48954
|
-
return `<div class="${classes}"${styleAttr}>${label}</div>`;
|
|
49637
|
+
return renderPlaceholder(node, this.getRenderContext());
|
|
48955
49638
|
}
|
|
48956
49639
|
renderAvatar(node) {
|
|
48957
|
-
|
|
48958
|
-
const classes = this.buildClassString([
|
|
48959
|
-
`${this.prefix}-avatar`,
|
|
48960
|
-
sizeResolved.className,
|
|
48961
|
-
...this.getCommonClasses(node)
|
|
48962
|
-
]);
|
|
48963
|
-
const baseStyles = this.buildCommonStyles(node);
|
|
48964
|
-
const sizeStyle = sizeResolved.style || "";
|
|
48965
|
-
const combinedStyles = baseStyles && sizeStyle ? `${baseStyles}; ${sizeStyle}` : baseStyles || sizeStyle;
|
|
48966
|
-
const styleAttr = combinedStyles ? ` style="${combinedStyles}"` : "";
|
|
48967
|
-
const initials = node.name ? node.name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) : "?";
|
|
48968
|
-
return `<div class="${classes}"${styleAttr} role="img" aria-label="${this.escapeHtml(node.name || "Avatar")}">${initials}</div>`;
|
|
49640
|
+
return renderAvatar(node, this.getRenderContext());
|
|
48969
49641
|
}
|
|
48970
49642
|
renderBadge(node) {
|
|
48971
|
-
|
|
48972
|
-
const iconData = getIconData(node.icon);
|
|
48973
|
-
const classes2 = this.buildClassString([
|
|
48974
|
-
`${this.prefix}-badge-icon`,
|
|
48975
|
-
node.size ? `${this.prefix}-badge-icon-${node.size}` : void 0,
|
|
48976
|
-
node.variant ? `${this.prefix}-badge-icon-${node.variant}` : void 0,
|
|
48977
|
-
...this.getCommonClasses(node)
|
|
48978
|
-
]);
|
|
48979
|
-
const styles2 = this.buildCommonStyles(node);
|
|
48980
|
-
const styleAttr2 = styles2 ? ` style="${styles2}"` : "";
|
|
48981
|
-
if (iconData) {
|
|
48982
|
-
const svg = renderIconSvg(iconData, 24, 2, `${this.prefix}-icon`);
|
|
48983
|
-
return `<span class="${classes2}"${styleAttr2} aria-label="${this.escapeHtml(node.icon)}">${svg}</span>`;
|
|
48984
|
-
}
|
|
48985
|
-
return `<span class="${classes2}"${styleAttr2} aria-label="unknown icon">?</span>`;
|
|
48986
|
-
}
|
|
48987
|
-
const isDot = !node.content || node.content.trim() === "";
|
|
48988
|
-
const classes = this.buildClassString([
|
|
48989
|
-
`${this.prefix}-badge`,
|
|
48990
|
-
isDot ? `${this.prefix}-badge-dot` : void 0,
|
|
48991
|
-
node.variant ? `${this.prefix}-badge-${node.variant}` : void 0,
|
|
48992
|
-
node.pill ? `${this.prefix}-badge-pill` : void 0,
|
|
48993
|
-
...this.getCommonClasses(node)
|
|
48994
|
-
]);
|
|
48995
|
-
const styles = this.buildCommonStyles(node);
|
|
48996
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48997
|
-
return `<span class="${classes}"${styleAttr}>${this.escapeHtml(node.content)}</span>`;
|
|
49643
|
+
return renderBadge(node, this.getRenderContext());
|
|
48998
49644
|
}
|
|
48999
49645
|
renderIcon(node) {
|
|
49000
|
-
|
|
49001
|
-
const sizeResolved = resolveSizeValue(node.size, "icon", this.prefix);
|
|
49002
|
-
const wrapperClasses = this.buildClassString([
|
|
49003
|
-
`${this.prefix}-icon-wrapper`,
|
|
49004
|
-
node.muted ? `${this.prefix}-text-muted` : void 0,
|
|
49005
|
-
...this.getCommonClasses(node)
|
|
49006
|
-
]);
|
|
49007
|
-
const baseStyles = this.buildCommonStyles(node);
|
|
49008
|
-
if (iconData) {
|
|
49009
|
-
const iconClasses = buildClassString([
|
|
49010
|
-
`${this.prefix}-icon`,
|
|
49011
|
-
sizeResolved.className
|
|
49012
|
-
]);
|
|
49013
|
-
const svgStyleAttr = sizeResolved.style ? ` style="${sizeResolved.style}"` : "";
|
|
49014
|
-
const svg = renderIconSvg(iconData, 24, 2, iconClasses, svgStyleAttr);
|
|
49015
|
-
const wrapperStyleAttr2 = baseStyles ? ` style="${baseStyles}"` : "";
|
|
49016
|
-
return `<span class="${wrapperClasses}"${wrapperStyleAttr2} aria-hidden="true">${svg}</span>`;
|
|
49017
|
-
}
|
|
49018
|
-
const size = sizeResolved.style?.match(/(\d+)px/)?.[1] || "24";
|
|
49019
|
-
const sizeNum = parseInt(size, 10);
|
|
49020
|
-
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">
|
|
49021
|
-
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" stroke-dasharray="4 2" fill="none" opacity="0.5"/>
|
|
49022
|
-
<text x="12" y="16" text-anchor="middle" font-size="10" fill="currentColor" opacity="0.7">?</text>
|
|
49023
|
-
</svg>`;
|
|
49024
|
-
const wrapperStyleAttr = baseStyles ? ` style="${baseStyles}"` : "";
|
|
49025
|
-
return `<span class="${wrapperClasses}"${wrapperStyleAttr} aria-hidden="true" title="Unknown icon: ${this.escapeHtml(node.name)}">${placeholderSvg}</span>`;
|
|
49646
|
+
return renderIcon(node, this.getRenderContext());
|
|
49026
49647
|
}
|
|
49027
49648
|
// ===========================================
|
|
49028
49649
|
// Data Node Renderers
|
|
49029
49650
|
// ===========================================
|
|
49030
49651
|
renderTable(node) {
|
|
49031
|
-
|
|
49032
|
-
`${this.prefix}-table`,
|
|
49033
|
-
node.striped ? `${this.prefix}-table-striped` : void 0,
|
|
49034
|
-
node.bordered ? `${this.prefix}-table-bordered` : void 0,
|
|
49035
|
-
node.hover ? `${this.prefix}-table-hover` : void 0,
|
|
49036
|
-
...this.getCommonClasses(node)
|
|
49037
|
-
]);
|
|
49038
|
-
const styles = this.buildCommonStyles(node);
|
|
49039
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49040
|
-
const thead = `<thead><tr>${node.columns.map((col) => `<th>${this.escapeHtml(col)}</th>`).join("")}</tr></thead>`;
|
|
49041
|
-
const tbody = `<tbody>${node.rows.map(
|
|
49042
|
-
(row) => `<tr>${row.map((cell) => {
|
|
49043
|
-
if (typeof cell === "string") {
|
|
49044
|
-
return `<td>${this.renderTableCellContent(cell)}</td>`;
|
|
49045
|
-
}
|
|
49046
|
-
return `<td>${this.renderNode(cell)}</td>`;
|
|
49047
|
-
}).join("")}</tr>`
|
|
49048
|
-
).join("")}</tbody>`;
|
|
49049
|
-
return `<table class="${classes}"${styleAttr}>
|
|
49050
|
-
${thead}
|
|
49051
|
-
${tbody}
|
|
49052
|
-
</table>`;
|
|
49652
|
+
return renderTable(node, this.getRenderContext());
|
|
49053
49653
|
}
|
|
49054
49654
|
renderList(node) {
|
|
49055
|
-
|
|
49056
|
-
const classes = this.buildClassString([
|
|
49057
|
-
`${this.prefix}-list`,
|
|
49058
|
-
node.ordered ? `${this.prefix}-list-ordered` : void 0,
|
|
49059
|
-
node.none ? `${this.prefix}-list-none` : void 0,
|
|
49060
|
-
...this.getCommonClasses(node)
|
|
49061
|
-
]);
|
|
49062
|
-
const styles = this.buildCommonStyles(node);
|
|
49063
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49064
|
-
const items = node.items.map((item) => {
|
|
49065
|
-
if (typeof item === "string") {
|
|
49066
|
-
return `<li class="${this.prefix}-list-item">${this.escapeHtml(item)}</li>`;
|
|
49067
|
-
}
|
|
49068
|
-
return `<li class="${this.prefix}-list-item">${this.escapeHtml(item.content)}</li>`;
|
|
49069
|
-
}).join("\n");
|
|
49070
|
-
return `<${tag} class="${classes}"${styleAttr}>
|
|
49071
|
-
${items}
|
|
49072
|
-
</${tag}>`;
|
|
49655
|
+
return renderList(node, this.getRenderContext());
|
|
49073
49656
|
}
|
|
49074
49657
|
// ===========================================
|
|
49075
49658
|
// Feedback Node Renderers
|
|
49076
49659
|
// ===========================================
|
|
49077
49660
|
renderAlert(node) {
|
|
49078
|
-
|
|
49079
|
-
`${this.prefix}-alert`,
|
|
49080
|
-
node.variant ? `${this.prefix}-alert-${node.variant}` : void 0,
|
|
49081
|
-
...this.getCommonClasses(node)
|
|
49082
|
-
]);
|
|
49083
|
-
const styles = this.buildCommonStyles(node);
|
|
49084
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49085
|
-
const dismissBtn = node.dismissible ? ` <button class="${this.prefix}-alert-close" aria-label="Close">×</button>` : "";
|
|
49086
|
-
return `<div class="${classes}"${styleAttr} role="alert">${this.escapeHtml(node.content)}${dismissBtn}</div>`;
|
|
49661
|
+
return renderAlert(node, this.getRenderContext());
|
|
49087
49662
|
}
|
|
49088
49663
|
renderToast(node) {
|
|
49089
|
-
|
|
49090
|
-
`${this.prefix}-toast`,
|
|
49091
|
-
node.position ? `${this.prefix}-toast-${node.position}` : void 0,
|
|
49092
|
-
node.variant ? `${this.prefix}-toast-${node.variant}` : void 0,
|
|
49093
|
-
...this.getCommonClasses(node)
|
|
49094
|
-
]);
|
|
49095
|
-
const styles = this.buildCommonStyles(node);
|
|
49096
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49097
|
-
return `<div class="${classes}"${styleAttr} role="status">${this.escapeHtml(node.content)}</div>`;
|
|
49664
|
+
return renderToast(node, this.getRenderContext());
|
|
49098
49665
|
}
|
|
49099
49666
|
renderProgress(node) {
|
|
49100
|
-
|
|
49101
|
-
`${this.prefix}-progress`,
|
|
49102
|
-
...this.getCommonClasses(node)
|
|
49103
|
-
]);
|
|
49104
|
-
const styles = this.buildCommonStyles(node);
|
|
49105
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49106
|
-
const value = node.value || 0;
|
|
49107
|
-
const max = node.max || 100;
|
|
49108
|
-
const percentage = Math.round(value / max * 100);
|
|
49109
|
-
const label = node.label ? `<span class="${this.prefix}-progress-label">${this.escapeHtml(node.label)}</span>` : "";
|
|
49110
|
-
if (node.indeterminate) {
|
|
49111
|
-
return `<div class="${classes} ${this.prefix}-progress-indeterminate"${styleAttr} role="progressbar">${label}</div>`;
|
|
49112
|
-
}
|
|
49113
|
-
return `<div class="${classes}"${styleAttr} role="progressbar" aria-valuenow="${value}" aria-valuemin="0" aria-valuemax="${max}">
|
|
49114
|
-
${label}
|
|
49115
|
-
<div class="${this.prefix}-progress-bar" style="width: ${percentage}%"></div>
|
|
49116
|
-
</div>`;
|
|
49667
|
+
return renderProgress(node, this.getRenderContext());
|
|
49117
49668
|
}
|
|
49118
49669
|
renderSpinner(node) {
|
|
49119
|
-
|
|
49120
|
-
const classes = this.buildClassString([
|
|
49121
|
-
`${this.prefix}-spinner`,
|
|
49122
|
-
sizeResolved.className,
|
|
49123
|
-
...this.getCommonClasses(node)
|
|
49124
|
-
]);
|
|
49125
|
-
const baseStyles = this.buildCommonStyles(node);
|
|
49126
|
-
const sizeStyle = sizeResolved.style || "";
|
|
49127
|
-
const combinedStyles = baseStyles && sizeStyle ? `${baseStyles}; ${sizeStyle}` : baseStyles || sizeStyle;
|
|
49128
|
-
const styleAttr = combinedStyles ? ` style="${combinedStyles}"` : "";
|
|
49129
|
-
const label = node.label || "Loading...";
|
|
49130
|
-
return `<span class="${classes}"${styleAttr} role="status" aria-label="${this.escapeHtml(label)}"></span>`;
|
|
49670
|
+
return renderSpinner(node, this.getRenderContext());
|
|
49131
49671
|
}
|
|
49132
49672
|
// ===========================================
|
|
49133
49673
|
// Overlay Node Renderers
|
|
49134
49674
|
// ===========================================
|
|
49135
49675
|
renderTooltip(node) {
|
|
49136
|
-
|
|
49137
|
-
`${this.prefix}-tooltip-wrapper`,
|
|
49138
|
-
...this.getCommonClasses(node)
|
|
49139
|
-
]);
|
|
49140
|
-
const styles = this.buildCommonStyles(node);
|
|
49141
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49142
|
-
const position = node.position || "top";
|
|
49143
|
-
const children = this.renderChildren(node.children);
|
|
49144
|
-
return `<div class="${classes}"${styleAttr}>
|
|
49145
|
-
${children}
|
|
49146
|
-
<div class="${this.prefix}-tooltip ${this.prefix}-tooltip-${position}" role="tooltip">${this.escapeHtml(node.content)}</div>
|
|
49147
|
-
</div>`;
|
|
49676
|
+
return renderTooltip(node, this.getRenderContext());
|
|
49148
49677
|
}
|
|
49149
49678
|
renderPopover(node) {
|
|
49150
|
-
|
|
49151
|
-
`${this.prefix}-popover`,
|
|
49152
|
-
...this.getCommonClasses(node)
|
|
49153
|
-
]);
|
|
49154
|
-
const styles = this.buildCommonStyles(node);
|
|
49155
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49156
|
-
const title = node.title ? `<div class="${this.prefix}-popover-header">${this.escapeHtml(node.title)}</div>
|
|
49157
|
-
` : "";
|
|
49158
|
-
const children = this.renderChildren(node.children);
|
|
49159
|
-
return `<div class="${classes}"${styleAttr}>
|
|
49160
|
-
${title}<div class="${this.prefix}-popover-body">
|
|
49161
|
-
${children}
|
|
49162
|
-
</div>
|
|
49163
|
-
</div>`;
|
|
49679
|
+
return renderPopover(node, this.getRenderContext());
|
|
49164
49680
|
}
|
|
49165
49681
|
renderDropdown(node) {
|
|
49166
|
-
|
|
49167
|
-
`${this.prefix}-dropdown`,
|
|
49168
|
-
...this.getCommonClasses(node)
|
|
49169
|
-
]);
|
|
49170
|
-
const styles = this.buildCommonStyles(node);
|
|
49171
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49172
|
-
const items = node.items.map((item) => {
|
|
49173
|
-
if ("type" in item && item.type === "divider") {
|
|
49174
|
-
return `<hr class="${this.prefix}-divider" />`;
|
|
49175
|
-
}
|
|
49176
|
-
const dropdownItem = item;
|
|
49177
|
-
const itemClasses = this.buildClassString([
|
|
49178
|
-
`${this.prefix}-dropdown-item`,
|
|
49179
|
-
dropdownItem.danger ? `${this.prefix}-dropdown-item-danger` : void 0,
|
|
49180
|
-
dropdownItem.disabled ? `${this.prefix}-dropdown-item-disabled` : void 0
|
|
49181
|
-
]);
|
|
49182
|
-
return `<button class="${itemClasses}"${dropdownItem.disabled ? " disabled" : ""}>${this.escapeHtml(dropdownItem.label)}</button>`;
|
|
49183
|
-
}).join("\n");
|
|
49184
|
-
return `<div class="${classes}"${styleAttr}>
|
|
49185
|
-
${items}
|
|
49186
|
-
</div>`;
|
|
49682
|
+
return renderDropdown(node, this.getRenderContext());
|
|
49187
49683
|
}
|
|
49188
49684
|
// ===========================================
|
|
49189
49685
|
// Navigation Node Renderers
|
|
49190
49686
|
// ===========================================
|
|
49191
49687
|
renderNav(node) {
|
|
49192
|
-
|
|
49193
|
-
`${this.prefix}-nav`,
|
|
49194
|
-
node.vertical ? `${this.prefix}-nav-vertical` : void 0,
|
|
49195
|
-
...this.getCommonClasses(node)
|
|
49196
|
-
]);
|
|
49197
|
-
const styles = this.buildCommonStyles(node);
|
|
49198
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49199
|
-
const items = node.items.map((item) => {
|
|
49200
|
-
if (typeof item === "string") {
|
|
49201
|
-
return `<a class="${this.prefix}-nav-link" href="#">${this.escapeHtml(item)}</a>`;
|
|
49202
|
-
}
|
|
49203
|
-
const linkClasses = this.buildClassString([
|
|
49204
|
-
`${this.prefix}-nav-link`,
|
|
49205
|
-
item.active ? `${this.prefix}-nav-link-active` : void 0,
|
|
49206
|
-
item.disabled ? `${this.prefix}-nav-link-disabled` : void 0
|
|
49207
|
-
]);
|
|
49208
|
-
return `<a class="${linkClasses}" href="${item.href || "#"}">${this.escapeHtml(item.label)}</a>`;
|
|
49209
|
-
}).join("\n");
|
|
49210
|
-
return `<nav class="${classes}"${styleAttr}>
|
|
49211
|
-
${items}
|
|
49212
|
-
</nav>`;
|
|
49688
|
+
return renderNav(node, this.getRenderContext());
|
|
49213
49689
|
}
|
|
49214
49690
|
renderTabs(node) {
|
|
49215
|
-
|
|
49216
|
-
`${this.prefix}-tabs`,
|
|
49217
|
-
...this.getCommonClasses(node)
|
|
49218
|
-
]);
|
|
49219
|
-
const styles = this.buildCommonStyles(node);
|
|
49220
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49221
|
-
const tabList = node.items.map((label, idx) => {
|
|
49222
|
-
const isActive = idx === (node.active || 0);
|
|
49223
|
-
const tabClasses = `${this.prefix}-tab${isActive ? ` ${this.prefix}-tab-active` : ""}`;
|
|
49224
|
-
return `<button class="${tabClasses}" role="tab" aria-selected="${isActive}">${this.escapeHtml(label)}</button>`;
|
|
49225
|
-
}).join("\n");
|
|
49226
|
-
return `<div class="${classes}"${styleAttr}>
|
|
49227
|
-
<div class="${this.prefix}-tab-list" role="tablist">
|
|
49228
|
-
${tabList}
|
|
49229
|
-
</div>
|
|
49230
|
-
</div>`;
|
|
49691
|
+
return renderTabs(node, this.getRenderContext());
|
|
49231
49692
|
}
|
|
49232
49693
|
renderBreadcrumb(node) {
|
|
49233
|
-
|
|
49234
|
-
`${this.prefix}-breadcrumb`,
|
|
49235
|
-
...this.getCommonClasses(node)
|
|
49236
|
-
]);
|
|
49237
|
-
const styles = this.buildCommonStyles(node);
|
|
49238
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49239
|
-
const items = node.items.map((item, idx) => {
|
|
49240
|
-
const isLast = idx === node.items.length - 1;
|
|
49241
|
-
if (typeof item === "string") {
|
|
49242
|
-
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>`;
|
|
49243
|
-
}
|
|
49244
|
-
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>`;
|
|
49245
|
-
}).join(" / ");
|
|
49246
|
-
return `<nav class="${classes}"${styleAttr} aria-label="Breadcrumb">${items}</nav>`;
|
|
49694
|
+
return renderBreadcrumb(node, this.getRenderContext());
|
|
49247
49695
|
}
|
|
49248
49696
|
// ===========================================
|
|
49249
49697
|
// Divider Renderer
|
|
49250
49698
|
// ===========================================
|
|
49251
49699
|
renderDivider(node) {
|
|
49252
|
-
|
|
49253
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49254
|
-
return `<hr class="${this.prefix}-divider"${styleAttr} />`;
|
|
49255
|
-
}
|
|
49256
|
-
// ===========================================
|
|
49257
|
-
// Semantic Marker Rendering
|
|
49258
|
-
// ===========================================
|
|
49259
|
-
/**
|
|
49260
|
-
* Parse and render semantic markers in text content
|
|
49261
|
-
*
|
|
49262
|
-
* Semantic markers use the syntax [component:variant] to indicate
|
|
49263
|
-
* what a visual element represents. This helps LLMs understand
|
|
49264
|
-
* the meaning of placeholder content.
|
|
49265
|
-
*
|
|
49266
|
-
* Supported markers:
|
|
49267
|
-
* - [avatar] or [avatar:size] - User avatar (renders as circle placeholder)
|
|
49268
|
-
* - [badge:variant] TEXT - Status badge (TEXT is displayed inside the badge)
|
|
49269
|
-
* - [dot:variant] - Status dot (renders as small circle before text)
|
|
49270
|
-
* - [icon:name] - Icon placeholder
|
|
49271
|
-
*
|
|
49272
|
-
* Examples:
|
|
49273
|
-
* - "[avatar] John Doe" → renders avatar circle + "John Doe"
|
|
49274
|
-
* - "[badge:primary] PRO" → renders badge containing "PRO"
|
|
49275
|
-
* - "[dot:success] Active" → renders green dot + "Active"
|
|
49276
|
-
*/
|
|
49277
|
-
renderSemanticMarkers(text) {
|
|
49278
|
-
const markerPattern = /\[([a-z]+)(?::([a-z0-9-]+))?\](\s*)/gi;
|
|
49279
|
-
let result = "";
|
|
49280
|
-
let lastIndex = 0;
|
|
49281
|
-
let match;
|
|
49282
|
-
while ((match = markerPattern.exec(text)) !== null) {
|
|
49283
|
-
if (match.index > lastIndex) {
|
|
49284
|
-
result += this.escapeHtml(text.substring(lastIndex, match.index));
|
|
49285
|
-
}
|
|
49286
|
-
const [fullMatch, component, variant] = match;
|
|
49287
|
-
const comp = component.toLowerCase();
|
|
49288
|
-
const varnt = variant?.toLowerCase();
|
|
49289
|
-
if (comp === "badge") {
|
|
49290
|
-
const afterMarker = text.substring(match.index + fullMatch.length);
|
|
49291
|
-
const contentMatch = afterMarker.match(/^([^\n\[]+?)(?=\n|\[|$)/);
|
|
49292
|
-
const badgeContent = contentMatch ? contentMatch[1].trim() : "";
|
|
49293
|
-
result += this.renderSemanticMarkerWithContent(comp, varnt, badgeContent);
|
|
49294
|
-
lastIndex = match.index + fullMatch.length + (contentMatch ? contentMatch[0].length : 0);
|
|
49295
|
-
markerPattern.lastIndex = lastIndex;
|
|
49296
|
-
} else {
|
|
49297
|
-
result += this.renderSemanticMarker(comp, varnt);
|
|
49298
|
-
lastIndex = match.index + fullMatch.length;
|
|
49299
|
-
}
|
|
49300
|
-
}
|
|
49301
|
-
if (lastIndex < text.length) {
|
|
49302
|
-
result += this.escapeHtml(text.substring(lastIndex));
|
|
49303
|
-
}
|
|
49304
|
-
if (lastIndex === 0) {
|
|
49305
|
-
return this.escapeHtml(text);
|
|
49306
|
-
}
|
|
49307
|
-
return result;
|
|
49308
|
-
}
|
|
49309
|
-
/**
|
|
49310
|
-
* Render a single semantic marker to HTML (without content)
|
|
49311
|
-
*/
|
|
49312
|
-
renderSemanticMarker(component, variant) {
|
|
49313
|
-
const prefix = this.prefix;
|
|
49314
|
-
switch (component) {
|
|
49315
|
-
case "avatar":
|
|
49316
|
-
const avatarSize = variant || "sm";
|
|
49317
|
-
return `<span class="${prefix}-semantic-avatar ${prefix}-semantic-avatar-${avatarSize}" data-semantic="avatar" data-variant="${avatarSize}" aria-hidden="true"></span>`;
|
|
49318
|
-
case "dot":
|
|
49319
|
-
const dotVariant = variant || "default";
|
|
49320
|
-
return `<span class="${prefix}-semantic-dot ${prefix}-semantic-dot-${dotVariant}" data-semantic="dot" data-variant="${dotVariant}" aria-hidden="true"></span>`;
|
|
49321
|
-
case "icon":
|
|
49322
|
-
const iconName = variant || "default";
|
|
49323
|
-
return `<span class="${prefix}-semantic-icon" data-semantic="icon" data-variant="${iconName}" aria-hidden="true">[${iconName}]</span>`;
|
|
49324
|
-
default:
|
|
49325
|
-
return `<span class="${prefix}-semantic-unknown" data-semantic="${component}" data-variant="${variant || ""}">[${component}${variant ? ":" + variant : ""}]</span>`;
|
|
49326
|
-
}
|
|
49327
|
-
}
|
|
49328
|
-
/**
|
|
49329
|
-
* Render a semantic marker with text content (for badge)
|
|
49330
|
-
*/
|
|
49331
|
-
renderSemanticMarkerWithContent(component, variant, content) {
|
|
49332
|
-
const prefix = this.prefix;
|
|
49333
|
-
switch (component) {
|
|
49334
|
-
case "badge":
|
|
49335
|
-
const badgeVariant = variant || "default";
|
|
49336
|
-
const escapedContent = this.escapeHtml(content);
|
|
49337
|
-
return `<span class="${prefix}-semantic-badge ${prefix}-semantic-badge-${badgeVariant}" data-semantic="badge" data-variant="${badgeVariant}">${escapedContent}</span>`;
|
|
49338
|
-
default:
|
|
49339
|
-
return this.renderSemanticMarker(component, variant) + this.escapeHtml(content);
|
|
49340
|
-
}
|
|
49341
|
-
}
|
|
49342
|
-
/**
|
|
49343
|
-
* Process table cell content with semantic markers and newlines
|
|
49344
|
-
*
|
|
49345
|
-
* Special handling for avatar + text layout:
|
|
49346
|
-
* When content starts with [avatar], wraps in flex container
|
|
49347
|
-
* so avatar and text align horizontally, with text stacking vertically
|
|
49348
|
-
*/
|
|
49349
|
-
renderTableCellContent(content) {
|
|
49350
|
-
const avatarMatch = content.match(/^\[avatar(?::([a-z0-9-]+))?\]\s*/i);
|
|
49351
|
-
if (avatarMatch) {
|
|
49352
|
-
const avatarVariant = avatarMatch[1]?.toLowerCase();
|
|
49353
|
-
const avatarHtml = this.renderSemanticMarker("avatar", avatarVariant);
|
|
49354
|
-
const restContent = content.slice(avatarMatch[0].length);
|
|
49355
|
-
const restHtml = this.renderSemanticMarkers(restContent);
|
|
49356
|
-
const lines = restHtml.split("\n");
|
|
49357
|
-
const textHtml = lines.length > 1 ? lines.map((line) => `<span>${line}</span>`).join("") : restHtml;
|
|
49358
|
-
return `<div class="${this.prefix}-cell-avatar-layout">${avatarHtml}<div class="${this.prefix}-cell-avatar-text">${textHtml}</div></div>`;
|
|
49359
|
-
}
|
|
49360
|
-
const withMarkers = this.renderSemanticMarkers(content);
|
|
49361
|
-
return withMarkers.replace(/\n/g, "<br>");
|
|
49700
|
+
return renderDivider(node, this.getRenderContext());
|
|
49362
49701
|
}
|
|
49363
49702
|
};
|
|
49364
49703
|
function createHtmlRenderer(options) {
|
|
49365
49704
|
return new HtmlRenderer(options);
|
|
49366
49705
|
}
|
|
49367
49706
|
|
|
49368
|
-
// src/renderer/svg/index.ts
|
|
49369
|
-
var SvgRenderer = class {
|
|
49370
|
-
options;
|
|
49371
|
-
theme;
|
|
49372
|
-
currentX = 0;
|
|
49373
|
-
currentY = 0;
|
|
49374
|
-
contentWidth = 0;
|
|
49375
|
-
constructor(options = {}) {
|
|
49376
|
-
this.options = {
|
|
49377
|
-
width: options.width ?? 800,
|
|
49378
|
-
height: options.height ?? 600,
|
|
49379
|
-
scale: options.scale ?? 1,
|
|
49380
|
-
background: options.background ?? "#ffffff",
|
|
49381
|
-
padding: options.padding ?? 20,
|
|
49382
|
-
fontFamily: options.fontFamily ?? "system-ui, -apple-system, sans-serif"
|
|
49383
|
-
};
|
|
49384
|
-
this.theme = defaultTheme;
|
|
49385
|
-
this.contentWidth = this.options.width - this.options.padding * 2;
|
|
49386
|
-
}
|
|
49387
|
-
/**
|
|
49388
|
-
* Render a wireframe document to SVG
|
|
49389
|
-
*/
|
|
49390
|
-
render(doc) {
|
|
49391
|
-
this.currentX = this.options.padding;
|
|
49392
|
-
this.currentY = this.options.padding;
|
|
49393
|
-
const firstPage = doc.children[0];
|
|
49394
|
-
let width = this.options.width;
|
|
49395
|
-
let height = this.options.height;
|
|
49396
|
-
if (firstPage && (firstPage.viewport !== void 0 || firstPage.device !== void 0)) {
|
|
49397
|
-
const viewport = resolveViewport(firstPage.viewport, firstPage.device);
|
|
49398
|
-
width = viewport.width;
|
|
49399
|
-
height = viewport.height;
|
|
49400
|
-
this.contentWidth = width - this.options.padding * 2;
|
|
49401
|
-
}
|
|
49402
|
-
const content = doc.children.map((page) => this.renderPage(page)).join("\n");
|
|
49403
|
-
const svg = `<?xml version="1.0" encoding="UTF-8"?>
|
|
49404
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" width="${width}" height="${height}">
|
|
49405
|
-
<defs>
|
|
49406
|
-
${this.generateDefs()}
|
|
49407
|
-
</defs>
|
|
49408
|
-
<rect width="100%" height="100%" fill="${this.options.background}"/>
|
|
49409
|
-
<g transform="scale(${this.options.scale})">
|
|
49410
|
-
${content}
|
|
49411
|
-
</g>
|
|
49412
|
-
</svg>`;
|
|
49413
|
-
return { svg, width, height };
|
|
49414
|
-
}
|
|
49415
|
-
/**
|
|
49416
|
-
* Generate SVG defs (styles, patterns, etc.)
|
|
49417
|
-
*/
|
|
49418
|
-
generateDefs() {
|
|
49419
|
-
return `
|
|
49420
|
-
<style>
|
|
49421
|
-
text { font-family: ${this.options.fontFamily}; }
|
|
49422
|
-
.wf-title { font-weight: 600; }
|
|
49423
|
-
.wf-muted { fill: ${this.theme.colors.muted}; }
|
|
49424
|
-
</style>
|
|
49425
|
-
`;
|
|
49426
|
-
}
|
|
49427
|
-
/**
|
|
49428
|
-
* Render a page node
|
|
49429
|
-
*/
|
|
49430
|
-
renderPage(node) {
|
|
49431
|
-
const elements = [];
|
|
49432
|
-
if (node.title) {
|
|
49433
|
-
elements.push(this.renderPageTitle(node.title));
|
|
49434
|
-
}
|
|
49435
|
-
for (const child of node.children) {
|
|
49436
|
-
elements.push(this.renderNode(child));
|
|
49437
|
-
}
|
|
49438
|
-
return elements.join("\n");
|
|
49439
|
-
}
|
|
49440
|
-
/**
|
|
49441
|
-
* Render page title
|
|
49442
|
-
*/
|
|
49443
|
-
renderPageTitle(title) {
|
|
49444
|
-
const fontSize = 24;
|
|
49445
|
-
const y = this.currentY + fontSize;
|
|
49446
|
-
this.currentY += fontSize + 16;
|
|
49447
|
-
return `<text x="${this.currentX}" y="${y}" font-size="${fontSize}" font-weight="600" fill="${this.theme.colors.foreground}">${this.escapeXml(title)}</text>`;
|
|
49448
|
-
}
|
|
49449
|
-
/**
|
|
49450
|
-
* Render any AST node
|
|
49451
|
-
*/
|
|
49452
|
-
renderNode(node) {
|
|
49453
|
-
switch (node.type) {
|
|
49454
|
-
// Layout nodes
|
|
49455
|
-
case "Row":
|
|
49456
|
-
return this.renderRow(node);
|
|
49457
|
-
case "Col":
|
|
49458
|
-
return this.renderCol(node);
|
|
49459
|
-
case "Header":
|
|
49460
|
-
return this.renderHeader(node);
|
|
49461
|
-
case "Main":
|
|
49462
|
-
return this.renderMain(node);
|
|
49463
|
-
case "Footer":
|
|
49464
|
-
return this.renderFooter(node);
|
|
49465
|
-
case "Sidebar":
|
|
49466
|
-
return this.renderSidebar(node);
|
|
49467
|
-
// Container nodes
|
|
49468
|
-
case "Card":
|
|
49469
|
-
return this.renderCard(node);
|
|
49470
|
-
case "Modal":
|
|
49471
|
-
return this.renderModal(node);
|
|
49472
|
-
// Text nodes
|
|
49473
|
-
case "Text":
|
|
49474
|
-
return this.renderText(node);
|
|
49475
|
-
case "Title":
|
|
49476
|
-
return this.renderTitle(node);
|
|
49477
|
-
case "Link":
|
|
49478
|
-
return this.renderLink(node);
|
|
49479
|
-
// Input nodes
|
|
49480
|
-
case "Input":
|
|
49481
|
-
return this.renderInput(node);
|
|
49482
|
-
case "Textarea":
|
|
49483
|
-
return this.renderTextarea(node);
|
|
49484
|
-
case "Select":
|
|
49485
|
-
return this.renderSelect(node);
|
|
49486
|
-
case "Checkbox":
|
|
49487
|
-
return this.renderCheckbox(node);
|
|
49488
|
-
case "Radio":
|
|
49489
|
-
return this.renderRadio(node);
|
|
49490
|
-
case "Switch":
|
|
49491
|
-
return this.renderSwitch(node);
|
|
49492
|
-
// Button
|
|
49493
|
-
case "Button":
|
|
49494
|
-
return this.renderButton(node);
|
|
49495
|
-
// Display nodes
|
|
49496
|
-
case "Image":
|
|
49497
|
-
return this.renderImage(node);
|
|
49498
|
-
case "Placeholder":
|
|
49499
|
-
return this.renderPlaceholder(node);
|
|
49500
|
-
case "Avatar":
|
|
49501
|
-
return this.renderAvatar(node);
|
|
49502
|
-
case "Badge":
|
|
49503
|
-
return this.renderBadge(node);
|
|
49504
|
-
// Data nodes
|
|
49505
|
-
case "Table":
|
|
49506
|
-
return this.renderTable(node);
|
|
49507
|
-
case "List":
|
|
49508
|
-
return this.renderList(node);
|
|
49509
|
-
// Feedback nodes
|
|
49510
|
-
case "Alert":
|
|
49511
|
-
return this.renderAlert(node);
|
|
49512
|
-
case "Progress":
|
|
49513
|
-
return this.renderProgress(node);
|
|
49514
|
-
case "Spinner":
|
|
49515
|
-
return this.renderSpinner(node);
|
|
49516
|
-
// Navigation nodes
|
|
49517
|
-
case "Nav":
|
|
49518
|
-
return this.renderNav(node);
|
|
49519
|
-
case "Tabs":
|
|
49520
|
-
return this.renderTabs(node);
|
|
49521
|
-
case "Breadcrumb":
|
|
49522
|
-
return this.renderBreadcrumb(node);
|
|
49523
|
-
default:
|
|
49524
|
-
return `<!-- Unsupported: ${node.type} -->`;
|
|
49525
|
-
}
|
|
49526
|
-
}
|
|
49527
|
-
// ===========================================
|
|
49528
|
-
// Layout Renderers
|
|
49529
|
-
// ===========================================
|
|
49530
|
-
renderRow(node) {
|
|
49531
|
-
const savedX = this.currentX;
|
|
49532
|
-
const savedY = this.currentY;
|
|
49533
|
-
const elements = [];
|
|
49534
|
-
const totalSpan = node.children.reduce((sum, child) => {
|
|
49535
|
-
if ("span" in child && typeof child.span === "number") {
|
|
49536
|
-
return sum + child.span;
|
|
49537
|
-
}
|
|
49538
|
-
return sum + 1;
|
|
49539
|
-
}, 0);
|
|
49540
|
-
const colWidth = this.contentWidth / Math.max(totalSpan, 1);
|
|
49541
|
-
let maxHeight = 0;
|
|
49542
|
-
for (const child of node.children) {
|
|
49543
|
-
const span = "span" in child && typeof child.span === "number" ? child.span : 1;
|
|
49544
|
-
const childWidth = colWidth * span;
|
|
49545
|
-
const startY = this.currentY;
|
|
49546
|
-
elements.push(this.renderNode(child));
|
|
49547
|
-
const childHeight = this.currentY - startY;
|
|
49548
|
-
maxHeight = Math.max(maxHeight, childHeight);
|
|
49549
|
-
this.currentX += childWidth;
|
|
49550
|
-
this.currentY = savedY;
|
|
49551
|
-
}
|
|
49552
|
-
this.currentX = savedX;
|
|
49553
|
-
this.currentY = savedY + maxHeight;
|
|
49554
|
-
return elements.join("\n");
|
|
49555
|
-
}
|
|
49556
|
-
renderCol(node) {
|
|
49557
|
-
return node.children.map((child) => this.renderNode(child)).join("\n");
|
|
49558
|
-
}
|
|
49559
|
-
renderHeader(node) {
|
|
49560
|
-
const height = 60;
|
|
49561
|
-
const x = this.currentX;
|
|
49562
|
-
const y = this.currentY;
|
|
49563
|
-
const savedY = this.currentY;
|
|
49564
|
-
this.currentY += 16;
|
|
49565
|
-
const children = node.children.map((c) => this.renderNode(c)).join("\n");
|
|
49566
|
-
this.currentY = savedY + height + 8;
|
|
49567
|
-
return `
|
|
49568
|
-
<g transform="translate(${x}, ${y})">
|
|
49569
|
-
<rect width="${this.contentWidth}" height="${height}" fill="${this.theme.colors.background}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49570
|
-
${children}
|
|
49571
|
-
</g>`;
|
|
49572
|
-
}
|
|
49573
|
-
renderMain(node) {
|
|
49574
|
-
return node.children.map((c) => this.renderNode(c)).join("\n");
|
|
49575
|
-
}
|
|
49576
|
-
renderFooter(node) {
|
|
49577
|
-
const height = 60;
|
|
49578
|
-
const x = this.currentX;
|
|
49579
|
-
const y = this.currentY;
|
|
49580
|
-
const savedY = this.currentY;
|
|
49581
|
-
this.currentY += 16;
|
|
49582
|
-
const children = node.children.map((c) => this.renderNode(c)).join("\n");
|
|
49583
|
-
this.currentY = savedY + height + 8;
|
|
49584
|
-
return `
|
|
49585
|
-
<g transform="translate(${x}, ${y})">
|
|
49586
|
-
<rect width="${this.contentWidth}" height="${height}" fill="${this.theme.colors.background}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49587
|
-
${children}
|
|
49588
|
-
</g>`;
|
|
49589
|
-
}
|
|
49590
|
-
renderSidebar(node) {
|
|
49591
|
-
const width = 200;
|
|
49592
|
-
const height = 300;
|
|
49593
|
-
const x = this.currentX;
|
|
49594
|
-
const y = this.currentY;
|
|
49595
|
-
const savedY = this.currentY;
|
|
49596
|
-
this.currentY += 16;
|
|
49597
|
-
const children = node.children.map((c) => this.renderNode(c)).join("\n");
|
|
49598
|
-
this.currentY = savedY + height + 8;
|
|
49599
|
-
return `
|
|
49600
|
-
<g transform="translate(${x}, ${y})">
|
|
49601
|
-
<rect width="${width}" height="${height}" fill="${this.theme.colors.background}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49602
|
-
${children}
|
|
49603
|
-
</g>`;
|
|
49604
|
-
}
|
|
49605
|
-
// ===========================================
|
|
49606
|
-
// Container Renderers
|
|
49607
|
-
// ===========================================
|
|
49608
|
-
renderCard(node) {
|
|
49609
|
-
const width = Math.min(300, this.contentWidth);
|
|
49610
|
-
const x = this.currentX;
|
|
49611
|
-
const y = this.currentY;
|
|
49612
|
-
const savedY = this.currentY;
|
|
49613
|
-
this.currentY += 16;
|
|
49614
|
-
let titleSvg = "";
|
|
49615
|
-
if (node.title) {
|
|
49616
|
-
const titleFontSize = 16;
|
|
49617
|
-
titleSvg = `<text x="16" y="${titleFontSize + 12}" font-size="${titleFontSize}" font-weight="600" fill="${this.theme.colors.foreground}">${this.escapeXml(node.title)}</text>`;
|
|
49618
|
-
this.currentY += titleFontSize + 8;
|
|
49619
|
-
}
|
|
49620
|
-
const childStartY = this.currentY - savedY;
|
|
49621
|
-
const children = node.children.map((c) => this.renderNode(c)).join("\n");
|
|
49622
|
-
const contentHeight = Math.max(this.currentY - savedY, 100);
|
|
49623
|
-
this.currentY = savedY + contentHeight + 16;
|
|
49624
|
-
return `
|
|
49625
|
-
<g transform="translate(${x}, ${y})">
|
|
49626
|
-
<rect width="${width}" height="${contentHeight}" rx="8" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49627
|
-
${titleSvg}
|
|
49628
|
-
<g transform="translate(16, ${childStartY})">
|
|
49629
|
-
${children}
|
|
49630
|
-
</g>
|
|
49631
|
-
</g>`;
|
|
49632
|
-
}
|
|
49633
|
-
renderModal(node) {
|
|
49634
|
-
const width = 400;
|
|
49635
|
-
const height = 300;
|
|
49636
|
-
const x = (this.options.width - width) / 2;
|
|
49637
|
-
const y = (this.options.height - height) / 2;
|
|
49638
|
-
let titleSvg = "";
|
|
49639
|
-
if (node.title) {
|
|
49640
|
-
titleSvg = `<text x="20" y="30" font-size="18" font-weight="600" fill="${this.theme.colors.foreground}">${this.escapeXml(node.title)}</text>`;
|
|
49641
|
-
}
|
|
49642
|
-
const savedX = this.currentX;
|
|
49643
|
-
const savedY = this.currentY;
|
|
49644
|
-
this.currentX = 20;
|
|
49645
|
-
this.currentY = 50;
|
|
49646
|
-
const children = node.children.map((c) => this.renderNode(c)).join("\n");
|
|
49647
|
-
this.currentX = savedX;
|
|
49648
|
-
this.currentY = savedY;
|
|
49649
|
-
return `
|
|
49650
|
-
<g>
|
|
49651
|
-
<rect width="100%" height="100%" fill="rgba(0,0,0,0.5)" opacity="0.5"/>
|
|
49652
|
-
<g transform="translate(${x}, ${y})">
|
|
49653
|
-
<rect width="${width}" height="${height}" rx="8" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49654
|
-
${titleSvg}
|
|
49655
|
-
${children}
|
|
49656
|
-
</g>
|
|
49657
|
-
</g>`;
|
|
49658
|
-
}
|
|
49659
|
-
// ===========================================
|
|
49660
|
-
// Text Renderers
|
|
49661
|
-
// ===========================================
|
|
49662
|
-
renderText(node) {
|
|
49663
|
-
const fontSize = this.resolveFontSize(node.size);
|
|
49664
|
-
const fill = node.muted ? this.theme.colors.muted : this.theme.colors.foreground;
|
|
49665
|
-
const fontWeight = node.weight || "normal";
|
|
49666
|
-
const y = this.currentY + fontSize;
|
|
49667
|
-
this.currentY += fontSize + 8;
|
|
49668
|
-
return `<text x="${this.currentX}" y="${y}" font-size="${fontSize}" font-weight="${fontWeight}" fill="${fill}">${this.escapeXml(node.content)}</text>`;
|
|
49669
|
-
}
|
|
49670
|
-
renderTitle(node) {
|
|
49671
|
-
const level = node.level || 1;
|
|
49672
|
-
const fontSize = this.getTitleFontSize(level);
|
|
49673
|
-
const y = this.currentY + fontSize;
|
|
49674
|
-
this.currentY += fontSize + 12;
|
|
49675
|
-
return `<text x="${this.currentX}" y="${y}" font-size="${fontSize}" font-weight="600" fill="${this.theme.colors.foreground}">${this.escapeXml(node.content)}</text>`;
|
|
49676
|
-
}
|
|
49677
|
-
renderLink(node) {
|
|
49678
|
-
const fontSize = 14;
|
|
49679
|
-
const y = this.currentY + fontSize;
|
|
49680
|
-
this.currentY += fontSize + 8;
|
|
49681
|
-
return `<text x="${this.currentX}" y="${y}" font-size="${fontSize}" fill="${this.theme.colors.primary}" text-decoration="underline">${this.escapeXml(node.content)}</text>`;
|
|
49682
|
-
}
|
|
49683
|
-
// ===========================================
|
|
49684
|
-
// Input Renderers
|
|
49685
|
-
// ===========================================
|
|
49686
|
-
renderInput(node) {
|
|
49687
|
-
const width = 280;
|
|
49688
|
-
const height = 40;
|
|
49689
|
-
const x = this.currentX;
|
|
49690
|
-
let y = this.currentY;
|
|
49691
|
-
let result = "";
|
|
49692
|
-
if (node.label) {
|
|
49693
|
-
result += `<text x="${x}" y="${y + 14}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
49694
|
-
y += 24;
|
|
49695
|
-
}
|
|
49696
|
-
const placeholder = node.placeholder || "";
|
|
49697
|
-
result += `
|
|
49698
|
-
<g transform="translate(${x}, ${y})">
|
|
49699
|
-
<rect width="${width}" height="${height}" rx="4" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49700
|
-
<text x="12" y="${height / 2 + 5}" font-size="14" fill="${this.theme.colors.muted}">${this.escapeXml(placeholder)}</text>
|
|
49701
|
-
</g>`;
|
|
49702
|
-
this.currentY = y + height + 12;
|
|
49703
|
-
return result;
|
|
49704
|
-
}
|
|
49705
|
-
renderTextarea(node) {
|
|
49706
|
-
const width = 280;
|
|
49707
|
-
const height = 100;
|
|
49708
|
-
const x = this.currentX;
|
|
49709
|
-
let y = this.currentY;
|
|
49710
|
-
let result = "";
|
|
49711
|
-
if (node.label) {
|
|
49712
|
-
result += `<text x="${x}" y="${y + 14}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
49713
|
-
y += 24;
|
|
49714
|
-
}
|
|
49715
|
-
const placeholder = node.placeholder || "";
|
|
49716
|
-
result += `
|
|
49717
|
-
<g transform="translate(${x}, ${y})">
|
|
49718
|
-
<rect width="${width}" height="${height}" rx="4" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49719
|
-
<text x="12" y="24" font-size="14" fill="${this.theme.colors.muted}">${this.escapeXml(placeholder)}</text>
|
|
49720
|
-
</g>`;
|
|
49721
|
-
this.currentY = y + height + 12;
|
|
49722
|
-
return result;
|
|
49723
|
-
}
|
|
49724
|
-
renderSelect(node) {
|
|
49725
|
-
const width = 280;
|
|
49726
|
-
const height = 40;
|
|
49727
|
-
const x = this.currentX;
|
|
49728
|
-
let y = this.currentY;
|
|
49729
|
-
let result = "";
|
|
49730
|
-
if (node.label) {
|
|
49731
|
-
result += `<text x="${x}" y="${y + 14}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
49732
|
-
y += 24;
|
|
49733
|
-
}
|
|
49734
|
-
const placeholder = node.placeholder || "Select...";
|
|
49735
|
-
result += `
|
|
49736
|
-
<g transform="translate(${x}, ${y})">
|
|
49737
|
-
<rect width="${width}" height="${height}" rx="4" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49738
|
-
<text x="12" y="${height / 2 + 5}" font-size="14" fill="${this.theme.colors.muted}">${this.escapeXml(placeholder)}</text>
|
|
49739
|
-
<path d="M${width - 24} ${height / 2 - 3} l6 6 l6 -6" fill="none" stroke="${this.theme.colors.muted}" stroke-width="1.5"/>
|
|
49740
|
-
</g>`;
|
|
49741
|
-
this.currentY = y + height + 12;
|
|
49742
|
-
return result;
|
|
49743
|
-
}
|
|
49744
|
-
renderCheckbox(node) {
|
|
49745
|
-
const x = this.currentX;
|
|
49746
|
-
const y = this.currentY;
|
|
49747
|
-
const size = 18;
|
|
49748
|
-
let result = `
|
|
49749
|
-
<g transform="translate(${x}, ${y})">
|
|
49750
|
-
<rect width="${size}" height="${size}" rx="3" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
49751
|
-
if (node.checked) {
|
|
49752
|
-
result += `<path d="M4 9 L7 12 L14 5" fill="none" stroke="${this.theme.colors.foreground}" stroke-width="2"/>`;
|
|
49753
|
-
}
|
|
49754
|
-
if (node.label) {
|
|
49755
|
-
result += `<text x="${size + 8}" y="${size - 3}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
49756
|
-
}
|
|
49757
|
-
result += "</g>";
|
|
49758
|
-
this.currentY += size + 12;
|
|
49759
|
-
return result;
|
|
49760
|
-
}
|
|
49761
|
-
renderRadio(node) {
|
|
49762
|
-
const x = this.currentX;
|
|
49763
|
-
const y = this.currentY;
|
|
49764
|
-
const size = 18;
|
|
49765
|
-
const radius = size / 2;
|
|
49766
|
-
let result = `
|
|
49767
|
-
<g transform="translate(${x}, ${y})">
|
|
49768
|
-
<circle cx="${radius}" cy="${radius}" r="${radius - 1}" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
49769
|
-
if (node.checked) {
|
|
49770
|
-
result += `<circle cx="${radius}" cy="${radius}" r="${radius - 5}" fill="${this.theme.colors.foreground}"/>`;
|
|
49771
|
-
}
|
|
49772
|
-
if (node.label) {
|
|
49773
|
-
result += `<text x="${size + 8}" y="${size - 3}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
49774
|
-
}
|
|
49775
|
-
result += "</g>";
|
|
49776
|
-
this.currentY += size + 12;
|
|
49777
|
-
return result;
|
|
49778
|
-
}
|
|
49779
|
-
renderSwitch(node) {
|
|
49780
|
-
const x = this.currentX;
|
|
49781
|
-
const y = this.currentY;
|
|
49782
|
-
const width = 44;
|
|
49783
|
-
const height = 24;
|
|
49784
|
-
const radius = height / 2;
|
|
49785
|
-
const isOn = node.checked;
|
|
49786
|
-
const bgColor = isOn ? this.theme.colors.primary : this.theme.colors.border;
|
|
49787
|
-
const knobX = isOn ? width - radius : radius;
|
|
49788
|
-
let result = `
|
|
49789
|
-
<g transform="translate(${x}, ${y})">
|
|
49790
|
-
<rect width="${width}" height="${height}" rx="${radius}" fill="${bgColor}"/>
|
|
49791
|
-
<circle cx="${knobX}" cy="${radius}" r="${radius - 3}" fill="white"/>`;
|
|
49792
|
-
if (node.label) {
|
|
49793
|
-
result += `<text x="${width + 8}" y="${height - 6}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
49794
|
-
}
|
|
49795
|
-
result += "</g>";
|
|
49796
|
-
this.currentY += height + 12;
|
|
49797
|
-
return result;
|
|
49798
|
-
}
|
|
49799
|
-
// ===========================================
|
|
49800
|
-
// Button Renderer
|
|
49801
|
-
// ===========================================
|
|
49802
|
-
renderButton(node) {
|
|
49803
|
-
const content = node.content;
|
|
49804
|
-
const hasIcon = !!node.icon;
|
|
49805
|
-
const isIconOnly = hasIcon && !content.trim();
|
|
49806
|
-
const iconSize = 16;
|
|
49807
|
-
const padding = isIconOnly ? 8 : 16;
|
|
49808
|
-
let width;
|
|
49809
|
-
if (isIconOnly) {
|
|
49810
|
-
width = iconSize + padding * 2;
|
|
49811
|
-
} else if (hasIcon) {
|
|
49812
|
-
width = Math.max(80, content.length * 10 + iconSize + 40);
|
|
49813
|
-
} else {
|
|
49814
|
-
width = Math.max(80, content.length * 10 + 32);
|
|
49815
|
-
}
|
|
49816
|
-
const height = 36;
|
|
49817
|
-
const x = this.currentX;
|
|
49818
|
-
const y = this.currentY;
|
|
49819
|
-
let fill = this.theme.colors.primary;
|
|
49820
|
-
let textFill = "#ffffff";
|
|
49821
|
-
let isOutline = false;
|
|
49822
|
-
if (node.secondary) {
|
|
49823
|
-
fill = this.theme.colors.secondary;
|
|
49824
|
-
} else if (node.outline) {
|
|
49825
|
-
fill = "white";
|
|
49826
|
-
textFill = this.theme.colors.foreground;
|
|
49827
|
-
isOutline = true;
|
|
49828
|
-
} else if (node.ghost) {
|
|
49829
|
-
fill = "transparent";
|
|
49830
|
-
textFill = this.theme.colors.foreground;
|
|
49831
|
-
}
|
|
49832
|
-
this.currentY += height + 8;
|
|
49833
|
-
const strokeAttr = isOutline ? `stroke="${this.theme.colors.border}" stroke-width="1"` : "";
|
|
49834
|
-
let iconSvg = "";
|
|
49835
|
-
if (hasIcon) {
|
|
49836
|
-
const iconData = getIconData(node.icon);
|
|
49837
|
-
if (iconData) {
|
|
49838
|
-
const iconX = isIconOnly ? (width - iconSize) / 2 : padding;
|
|
49839
|
-
const iconY = (height - iconSize) / 2;
|
|
49840
|
-
iconSvg = this.renderIconPaths(iconData, iconX, iconY, iconSize, textFill);
|
|
49841
|
-
}
|
|
49842
|
-
}
|
|
49843
|
-
const textX = hasIcon && !isIconOnly ? padding + iconSize + 8 + (width - padding - iconSize - 8 - padding) / 2 : width / 2;
|
|
49844
|
-
const textContent = isIconOnly ? "" : `<text x="${textX}" y="${height / 2 + 5}" font-size="14" fill="${textFill}" text-anchor="middle">${this.escapeXml(content)}</text>`;
|
|
49845
|
-
return `
|
|
49846
|
-
<g transform="translate(${x}, ${y})">
|
|
49847
|
-
<rect width="${width}" height="${height}" rx="4" fill="${fill}" ${strokeAttr}/>
|
|
49848
|
-
${iconSvg}
|
|
49849
|
-
${textContent}
|
|
49850
|
-
</g>`;
|
|
49851
|
-
}
|
|
49852
|
-
/**
|
|
49853
|
-
* Render icon paths for SVG
|
|
49854
|
-
*/
|
|
49855
|
-
renderIconPaths(data, x, y, size, color) {
|
|
49856
|
-
const scale = size / 24;
|
|
49857
|
-
const paths = data.map(([tag, attrs]) => {
|
|
49858
|
-
const attrStr = Object.entries(attrs).map(([key, value]) => `${key}="${value}"`).join(" ");
|
|
49859
|
-
return `<${tag} ${attrStr} />`;
|
|
49860
|
-
}).join("");
|
|
49861
|
-
return `<g transform="translate(${x}, ${y}) scale(${scale})" fill="none" stroke="${color}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${paths}</g>`;
|
|
49862
|
-
}
|
|
49863
|
-
// ===========================================
|
|
49864
|
-
// Display Renderers
|
|
49865
|
-
// ===========================================
|
|
49866
|
-
renderImage(node) {
|
|
49867
|
-
const width = node.w && typeof node.w === "number" ? node.w : 200;
|
|
49868
|
-
const height = node.h && typeof node.h === "number" ? node.h : 150;
|
|
49869
|
-
const x = this.currentX;
|
|
49870
|
-
const y = this.currentY;
|
|
49871
|
-
this.currentY += height + 12;
|
|
49872
|
-
return `
|
|
49873
|
-
<g transform="translate(${x}, ${y})">
|
|
49874
|
-
<rect width="${width}" height="${height}" fill="${this.theme.colors.muted}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49875
|
-
<line x1="0" y1="0" x2="${width}" y2="${height}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49876
|
-
<line x1="${width}" y1="0" x2="0" y2="${height}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49877
|
-
<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>
|
|
49878
|
-
</g>`;
|
|
49879
|
-
}
|
|
49880
|
-
renderPlaceholder(node) {
|
|
49881
|
-
const width = node.w && typeof node.w === "number" ? node.w : 200;
|
|
49882
|
-
const height = node.h && typeof node.h === "number" ? node.h : 100;
|
|
49883
|
-
const x = this.currentX;
|
|
49884
|
-
const y = this.currentY;
|
|
49885
|
-
this.currentY += height + 12;
|
|
49886
|
-
return `
|
|
49887
|
-
<g transform="translate(${x}, ${y})">
|
|
49888
|
-
<rect width="${width}" height="${height}" fill="${this.theme.colors.muted}" stroke="${this.theme.colors.border}" stroke-width="1" stroke-dasharray="4,4"/>
|
|
49889
|
-
<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>
|
|
49890
|
-
</g>`;
|
|
49891
|
-
}
|
|
49892
|
-
renderAvatar(node) {
|
|
49893
|
-
const sizes = { xs: 24, sm: 32, md: 40, lg: 48, xl: 64 };
|
|
49894
|
-
const size = sizes[node.size || "md"] || 40;
|
|
49895
|
-
const radius = size / 2;
|
|
49896
|
-
const x = this.currentX;
|
|
49897
|
-
const y = this.currentY;
|
|
49898
|
-
const initial = node.name ? node.name.charAt(0).toUpperCase() : "?";
|
|
49899
|
-
this.currentY += size + 12;
|
|
49900
|
-
return `
|
|
49901
|
-
<g transform="translate(${x}, ${y})">
|
|
49902
|
-
<circle cx="${radius}" cy="${radius}" r="${radius}" fill="${this.theme.colors.muted}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49903
|
-
<text x="${radius}" y="${radius + 5}" font-size="${size / 2.5}" fill="${this.theme.colors.foreground}" text-anchor="middle">${initial}</text>
|
|
49904
|
-
</g>`;
|
|
49905
|
-
}
|
|
49906
|
-
renderBadge(node) {
|
|
49907
|
-
const content = node.content;
|
|
49908
|
-
const width = Math.max(24, content.length * 8 + 16);
|
|
49909
|
-
const height = 22;
|
|
49910
|
-
const x = this.currentX;
|
|
49911
|
-
const y = this.currentY;
|
|
49912
|
-
const fill = this.theme.colors.muted;
|
|
49913
|
-
const textFill = this.theme.colors.foreground;
|
|
49914
|
-
this.currentY += height + 8;
|
|
49915
|
-
return `
|
|
49916
|
-
<g transform="translate(${x}, ${y})">
|
|
49917
|
-
<rect width="${width}" height="${height}" rx="11" fill="${fill}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49918
|
-
<text x="${width / 2}" y="${height / 2 + 4}" font-size="12" fill="${textFill}" text-anchor="middle">${this.escapeXml(content)}</text>
|
|
49919
|
-
</g>`;
|
|
49920
|
-
}
|
|
49921
|
-
// ===========================================
|
|
49922
|
-
// Data Renderers
|
|
49923
|
-
// ===========================================
|
|
49924
|
-
renderTable(node) {
|
|
49925
|
-
const columns = node.columns || [];
|
|
49926
|
-
const rows = node.rows || [];
|
|
49927
|
-
const rowCount = rows.length || 3;
|
|
49928
|
-
const colWidth = 120;
|
|
49929
|
-
const rowHeight = 40;
|
|
49930
|
-
const x = this.currentX;
|
|
49931
|
-
const y = this.currentY;
|
|
49932
|
-
let svg = `<g transform="translate(${x}, ${y})">`;
|
|
49933
|
-
svg += `<rect width="${columns.length * colWidth}" height="${rowHeight}" fill="${this.theme.colors.muted}"/>`;
|
|
49934
|
-
columns.forEach((col, i) => {
|
|
49935
|
-
svg += `<text x="${i * colWidth + 12}" y="${rowHeight / 2 + 5}" font-size="14" font-weight="600">${this.escapeXml(col)}</text>`;
|
|
49936
|
-
});
|
|
49937
|
-
const displayRowCount = rows.length > 0 ? rows.length : Math.max(rowCount, 3);
|
|
49938
|
-
for (let rowIdx = 0; rowIdx < displayRowCount; rowIdx++) {
|
|
49939
|
-
const rowY = (rowIdx + 1) * rowHeight;
|
|
49940
|
-
svg += `<rect y="${rowY}" width="${columns.length * colWidth}" height="${rowHeight}" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
49941
|
-
columns.forEach((_, colIdx) => {
|
|
49942
|
-
const cellContent = rows[rowIdx] && rows[rowIdx][colIdx] ? String(typeof rows[rowIdx][colIdx] === "object" ? "..." : rows[rowIdx][colIdx]) : "\u2014";
|
|
49943
|
-
svg += `<text x="${colIdx * colWidth + 12}" y="${rowY + rowHeight / 2 + 5}" font-size="14" fill="${this.theme.colors.muted}">${this.escapeXml(cellContent)}</text>`;
|
|
49944
|
-
});
|
|
49945
|
-
}
|
|
49946
|
-
svg += "</g>";
|
|
49947
|
-
this.currentY += (displayRowCount + 1) * rowHeight + 16;
|
|
49948
|
-
return svg;
|
|
49949
|
-
}
|
|
49950
|
-
renderList(node) {
|
|
49951
|
-
const x = this.currentX;
|
|
49952
|
-
let y = this.currentY;
|
|
49953
|
-
const items = node.items || [];
|
|
49954
|
-
const ordered = node.ordered || false;
|
|
49955
|
-
let svg = `<g transform="translate(${x}, ${y})">`;
|
|
49956
|
-
items.forEach((item, idx) => {
|
|
49957
|
-
const marker = ordered ? `${idx + 1}.` : "\u2022";
|
|
49958
|
-
const content = typeof item === "string" ? item : item.content;
|
|
49959
|
-
svg += `<text x="0" y="${idx * 24 + 16}" font-size="14" fill="${this.theme.colors.foreground}">${marker} ${this.escapeXml(content)}</text>`;
|
|
49960
|
-
});
|
|
49961
|
-
svg += "</g>";
|
|
49962
|
-
this.currentY += items.length * 24 + 12;
|
|
49963
|
-
return svg;
|
|
49964
|
-
}
|
|
49965
|
-
// ===========================================
|
|
49966
|
-
// Feedback Renderers
|
|
49967
|
-
// ===========================================
|
|
49968
|
-
renderAlert(node) {
|
|
49969
|
-
const width = Math.min(400, this.contentWidth);
|
|
49970
|
-
const height = 48;
|
|
49971
|
-
const x = this.currentX;
|
|
49972
|
-
const y = this.currentY;
|
|
49973
|
-
this.currentY += height + 12;
|
|
49974
|
-
return `
|
|
49975
|
-
<g transform="translate(${x}, ${y})">
|
|
49976
|
-
<rect width="${width}" height="${height}" rx="4" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
49977
|
-
<text x="16" y="${height / 2 + 5}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.content)}</text>
|
|
49978
|
-
</g>`;
|
|
49979
|
-
}
|
|
49980
|
-
renderProgress(node) {
|
|
49981
|
-
const width = 200;
|
|
49982
|
-
const height = 8;
|
|
49983
|
-
const x = this.currentX;
|
|
49984
|
-
let y = this.currentY;
|
|
49985
|
-
let result = "";
|
|
49986
|
-
if (node.label) {
|
|
49987
|
-
result += `<text x="${x}" y="${y + 14}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
49988
|
-
y += 24;
|
|
49989
|
-
}
|
|
49990
|
-
const value = node.value || 0;
|
|
49991
|
-
const max = node.max || 100;
|
|
49992
|
-
const percent = Math.min(100, Math.max(0, value / max * 100));
|
|
49993
|
-
result += `
|
|
49994
|
-
<g transform="translate(${x}, ${y})">
|
|
49995
|
-
<rect width="${width}" height="${height}" rx="${height / 2}" fill="${this.theme.colors.muted}"/>
|
|
49996
|
-
<rect width="${width * percent / 100}" height="${height}" rx="${height / 2}" fill="${this.theme.colors.primary}"/>
|
|
49997
|
-
</g>`;
|
|
49998
|
-
this.currentY = y + height + 12;
|
|
49999
|
-
return result;
|
|
50000
|
-
}
|
|
50001
|
-
renderSpinner(node) {
|
|
50002
|
-
const sizes = { xs: 16, sm: 20, md: 24, lg: 32, xl: 40 };
|
|
50003
|
-
const size = sizes[node.size || "md"] || 24;
|
|
50004
|
-
const x = this.currentX + size / 2;
|
|
50005
|
-
const y = this.currentY + size / 2;
|
|
50006
|
-
const radius = size / 2 - 2;
|
|
50007
|
-
this.currentY += size + 12;
|
|
50008
|
-
return `
|
|
50009
|
-
<g transform="translate(${x}, ${y})">
|
|
50010
|
-
<circle r="${radius}" fill="none" stroke="${this.theme.colors.muted}" stroke-width="2"/>
|
|
50011
|
-
<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"/>
|
|
50012
|
-
</g>`;
|
|
50013
|
-
}
|
|
50014
|
-
// ===========================================
|
|
50015
|
-
// Navigation Renderers
|
|
50016
|
-
// ===========================================
|
|
50017
|
-
renderNav(node) {
|
|
50018
|
-
const items = node.items || [];
|
|
50019
|
-
const x = this.currentX;
|
|
50020
|
-
const y = this.currentY;
|
|
50021
|
-
const vertical = node.vertical || false;
|
|
50022
|
-
let svg = `<g transform="translate(${x}, ${y})">`;
|
|
50023
|
-
if (vertical) {
|
|
50024
|
-
items.forEach((item, idx) => {
|
|
50025
|
-
const label = typeof item === "string" ? item : item.label;
|
|
50026
|
-
const isActive = typeof item === "object" && item.active;
|
|
50027
|
-
const fill = isActive ? this.theme.colors.foreground : this.theme.colors.muted;
|
|
50028
|
-
svg += `<text x="0" y="${idx * 32 + 16}" font-size="14" fill="${fill}">${this.escapeXml(label)}</text>`;
|
|
50029
|
-
});
|
|
50030
|
-
this.currentY += items.length * 32 + 12;
|
|
50031
|
-
} else {
|
|
50032
|
-
let offsetX = 0;
|
|
50033
|
-
items.forEach((item) => {
|
|
50034
|
-
const label = typeof item === "string" ? item : item.label;
|
|
50035
|
-
const isActive = typeof item === "object" && item.active;
|
|
50036
|
-
const fill = isActive ? this.theme.colors.foreground : this.theme.colors.muted;
|
|
50037
|
-
svg += `<text x="${offsetX}" y="16" font-size="14" fill="${fill}">${this.escapeXml(label)}</text>`;
|
|
50038
|
-
offsetX += label.length * 8 + 24;
|
|
50039
|
-
});
|
|
50040
|
-
this.currentY += 32;
|
|
50041
|
-
}
|
|
50042
|
-
svg += "</g>";
|
|
50043
|
-
return svg;
|
|
50044
|
-
}
|
|
50045
|
-
renderTabs(node) {
|
|
50046
|
-
const items = node.items || [];
|
|
50047
|
-
const x = this.currentX;
|
|
50048
|
-
const y = this.currentY;
|
|
50049
|
-
const tabHeight = 40;
|
|
50050
|
-
let svg = `<g transform="translate(${x}, ${y})">`;
|
|
50051
|
-
let offsetX = 0;
|
|
50052
|
-
items.forEach((item) => {
|
|
50053
|
-
const label = typeof item === "string" ? item : item;
|
|
50054
|
-
const tabWidth = label.length * 10 + 24;
|
|
50055
|
-
svg += `<rect x="${offsetX}" width="${tabWidth}" height="${tabHeight}" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
50056
|
-
svg += `<text x="${offsetX + tabWidth / 2}" y="${tabHeight / 2 + 5}" font-size="14" text-anchor="middle">${this.escapeXml(label)}</text>`;
|
|
50057
|
-
offsetX += tabWidth;
|
|
50058
|
-
});
|
|
50059
|
-
svg += "</g>";
|
|
50060
|
-
this.currentY += tabHeight + 12;
|
|
50061
|
-
return svg;
|
|
50062
|
-
}
|
|
50063
|
-
renderBreadcrumb(node) {
|
|
50064
|
-
const items = node.items || [];
|
|
50065
|
-
const separator = "/";
|
|
50066
|
-
const x = this.currentX;
|
|
50067
|
-
const y = this.currentY;
|
|
50068
|
-
let svg = `<g transform="translate(${x}, ${y})">`;
|
|
50069
|
-
let offsetX = 0;
|
|
50070
|
-
items.forEach((item, idx) => {
|
|
50071
|
-
const label = typeof item === "string" ? item : item.label;
|
|
50072
|
-
const isLast = idx === items.length - 1;
|
|
50073
|
-
const fill = isLast ? this.theme.colors.foreground : this.theme.colors.muted;
|
|
50074
|
-
svg += `<text x="${offsetX}" y="16" font-size="14" fill="${fill}">${this.escapeXml(label)}</text>`;
|
|
50075
|
-
offsetX += label.length * 8 + 8;
|
|
50076
|
-
if (!isLast) {
|
|
50077
|
-
svg += `<text x="${offsetX}" y="16" font-size="14" fill="${this.theme.colors.muted}">${separator}</text>`;
|
|
50078
|
-
offsetX += 16;
|
|
50079
|
-
}
|
|
50080
|
-
});
|
|
50081
|
-
svg += "</g>";
|
|
50082
|
-
this.currentY += 28;
|
|
50083
|
-
return svg;
|
|
50084
|
-
}
|
|
50085
|
-
// ===========================================
|
|
50086
|
-
// Utility Methods
|
|
50087
|
-
// ===========================================
|
|
50088
|
-
getFontSize(size) {
|
|
50089
|
-
const sizes = {
|
|
50090
|
-
xs: 12,
|
|
50091
|
-
sm: 14,
|
|
50092
|
-
base: 16,
|
|
50093
|
-
md: 16,
|
|
50094
|
-
lg: 18,
|
|
50095
|
-
xl: 20,
|
|
50096
|
-
"2xl": 24,
|
|
50097
|
-
"3xl": 30
|
|
50098
|
-
};
|
|
50099
|
-
return sizes[size] || 16;
|
|
50100
|
-
}
|
|
50101
|
-
resolveFontSize(size) {
|
|
50102
|
-
if (!size) return 16;
|
|
50103
|
-
if (typeof size === "string") {
|
|
50104
|
-
return this.getFontSize(size);
|
|
50105
|
-
}
|
|
50106
|
-
if (typeof size === "object" && "value" in size) {
|
|
50107
|
-
if (size.unit === "px") return size.value;
|
|
50108
|
-
if (size.unit === "rem") return size.value * 16;
|
|
50109
|
-
if (size.unit === "em") return size.value * 16;
|
|
50110
|
-
return size.value;
|
|
50111
|
-
}
|
|
50112
|
-
return 16;
|
|
50113
|
-
}
|
|
50114
|
-
getTitleFontSize(level) {
|
|
50115
|
-
const sizes = {
|
|
50116
|
-
1: 32,
|
|
50117
|
-
2: 28,
|
|
50118
|
-
3: 24,
|
|
50119
|
-
4: 20,
|
|
50120
|
-
5: 18,
|
|
50121
|
-
6: 16
|
|
50122
|
-
};
|
|
50123
|
-
return sizes[level] || 24;
|
|
50124
|
-
}
|
|
50125
|
-
escapeXml(str) {
|
|
50126
|
-
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
50127
|
-
}
|
|
50128
|
-
};
|
|
50129
|
-
function createSvgRenderer(options) {
|
|
50130
|
-
return new SvgRenderer(options);
|
|
50131
|
-
}
|
|
50132
|
-
function renderToSvg(doc, options) {
|
|
50133
|
-
const renderer = new SvgRenderer(options);
|
|
50134
|
-
return renderer.render(doc);
|
|
50135
|
-
}
|
|
50136
|
-
|
|
50137
49707
|
// src/renderer/index.ts
|
|
50138
49708
|
function render(document, options = {}) {
|
|
50139
49709
|
const renderer = createHtmlRenderer(options);
|
|
@@ -50170,7 +49740,7 @@ ${html}
|
|
|
50170
49740
|
</body>
|
|
50171
49741
|
</html>`;
|
|
50172
49742
|
}
|
|
50173
|
-
function
|
|
49743
|
+
function renderToSvg(document, options = {}) {
|
|
50174
49744
|
const firstPage = document.children[0];
|
|
50175
49745
|
let width = options.width ?? 800;
|
|
50176
49746
|
let height = options.height ?? 600;
|
|
@@ -50181,15 +49751,22 @@ function renderToSvg2(document, options = {}) {
|
|
|
50181
49751
|
height = viewport.height;
|
|
50182
49752
|
}
|
|
50183
49753
|
}
|
|
50184
|
-
const padding = options.padding ?? 20;
|
|
50185
49754
|
const background = options.background ?? "#ffffff";
|
|
50186
49755
|
const { html, css } = render(document, { theme: "light" });
|
|
50187
49756
|
const svg = `<?xml version="1.0" encoding="UTF-8"?>
|
|
50188
49757
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
50189
49758
|
viewBox="0 0 ${width} ${height}" width="${width}" height="${height}">
|
|
50190
49759
|
<rect width="100%" height="100%" fill="${background}"/>
|
|
50191
|
-
<foreignObject x="
|
|
50192
|
-
<div xmlns="http://www.w3.org/1999/xhtml" style="
|
|
49760
|
+
<foreignObject x="0" y="0" width="${width}" height="${height}">
|
|
49761
|
+
<div xmlns="http://www.w3.org/1999/xhtml" style="
|
|
49762
|
+
width: ${width}px;
|
|
49763
|
+
height: ${height}px;
|
|
49764
|
+
overflow: hidden;
|
|
49765
|
+
display: flex;
|
|
49766
|
+
justify-content: center;
|
|
49767
|
+
align-items: center;
|
|
49768
|
+
box-sizing: border-box;
|
|
49769
|
+
">
|
|
50193
49770
|
<style type="text/css">
|
|
50194
49771
|
${css}
|
|
50195
49772
|
</style>
|
|
@@ -50199,15 +49776,10 @@ ${css}
|
|
|
50199
49776
|
</svg>`;
|
|
50200
49777
|
return { svg, width, height };
|
|
50201
49778
|
}
|
|
50202
|
-
function renderToPureSvg(document, options = {}) {
|
|
50203
|
-
return renderToSvg(document, options);
|
|
50204
|
-
}
|
|
50205
49779
|
// Annotate the CommonJS export names for ESM import in node:
|
|
50206
49780
|
0 && (module.exports = {
|
|
50207
49781
|
HtmlRenderer,
|
|
50208
|
-
SvgRenderer,
|
|
50209
49782
|
createHtmlRenderer,
|
|
50210
|
-
createSvgRenderer,
|
|
50211
49783
|
darkTheme,
|
|
50212
49784
|
defaultTheme,
|
|
50213
49785
|
generateComponentStyles,
|
|
@@ -50218,7 +49790,6 @@ function renderToPureSvg(document, options = {}) {
|
|
|
50218
49790
|
render,
|
|
50219
49791
|
renderIconSvg,
|
|
50220
49792
|
renderToHtml,
|
|
50221
|
-
renderToPureSvg,
|
|
50222
49793
|
renderToSvg
|
|
50223
49794
|
});
|
|
50224
49795
|
/**
|