@wireweave/core 1.1.0-beta.0 → 1.2.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +3966 -3278
- package/dist/index.d.cts +616 -2
- package/dist/index.d.ts +616 -2
- package/dist/index.js +3948 -3275
- package/dist/parser.cjs +675 -476
- package/dist/parser.js +675 -476
- package/dist/renderer.cjs +1099 -2759
- package/dist/renderer.d.cts +37 -175
- package/dist/renderer.d.ts +37 -175
- package/dist/renderer.js +1099 -2756
- package/package.json +1 -1
package/dist/renderer.js
CHANGED
|
@@ -51,23 +51,7 @@ function getTheme(name) {
|
|
|
51
51
|
return name === "dark" ? darkTheme : defaultTheme;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
// src/renderer/styles
|
|
55
|
-
function generateComponentStyles(_theme, prefix = "wf") {
|
|
56
|
-
const parts = [
|
|
57
|
-
generateContainerStyles(prefix),
|
|
58
|
-
generateTextStyles(prefix),
|
|
59
|
-
generateInputStyles(_theme, prefix),
|
|
60
|
-
generateButtonStyles(_theme, prefix),
|
|
61
|
-
generateDisplayStyles(_theme, prefix),
|
|
62
|
-
generateDataStyles(_theme, prefix),
|
|
63
|
-
generateFeedbackStyles(_theme, prefix),
|
|
64
|
-
generateOverlayStyles(_theme, prefix),
|
|
65
|
-
generateNavigationStyles(_theme, prefix),
|
|
66
|
-
generateSemanticMarkerStyles(_theme, prefix),
|
|
67
|
-
generateAccessibilityStyles(prefix)
|
|
68
|
-
];
|
|
69
|
-
return parts.join("\n\n");
|
|
70
|
-
}
|
|
54
|
+
// src/renderer/styles/container.ts
|
|
71
55
|
function generateContainerStyles(prefix) {
|
|
72
56
|
return `/* Container Components */
|
|
73
57
|
.${prefix}-card {
|
|
@@ -207,6 +191,8 @@ function generateContainerStyles(prefix) {
|
|
|
207
191
|
padding: 16px;
|
|
208
192
|
}`;
|
|
209
193
|
}
|
|
194
|
+
|
|
195
|
+
// src/renderer/styles/text.ts
|
|
210
196
|
function generateTextStyles(prefix) {
|
|
211
197
|
return `/* Text Components */
|
|
212
198
|
.${prefix}-text {
|
|
@@ -263,6 +249,8 @@ h6.${prefix}-title { font-size: 16px; }
|
|
|
263
249
|
opacity: 0.7;
|
|
264
250
|
}`;
|
|
265
251
|
}
|
|
252
|
+
|
|
253
|
+
// src/renderer/styles/input.ts
|
|
266
254
|
function generateInputStyles(_theme, prefix) {
|
|
267
255
|
return `/* Input Components */
|
|
268
256
|
.${prefix}-form-field {
|
|
@@ -462,6 +450,8 @@ function generateInputStyles(_theme, prefix) {
|
|
|
462
450
|
cursor: pointer;
|
|
463
451
|
}`;
|
|
464
452
|
}
|
|
453
|
+
|
|
454
|
+
// src/renderer/styles/button.ts
|
|
465
455
|
function generateButtonStyles(_theme, prefix) {
|
|
466
456
|
return `/* Button Components */
|
|
467
457
|
.${prefix}-button {
|
|
@@ -589,6 +579,8 @@ function generateButtonStyles(_theme, prefix) {
|
|
|
589
579
|
.${prefix}-button.${prefix}-justify-end { justify-content: flex-end; }
|
|
590
580
|
.${prefix}-button.${prefix}-justify-between { justify-content: space-between; }`;
|
|
591
581
|
}
|
|
582
|
+
|
|
583
|
+
// src/renderer/styles/display.ts
|
|
592
584
|
function generateDisplayStyles(_theme, prefix) {
|
|
593
585
|
return `/* Display Components */
|
|
594
586
|
.${prefix}-image {
|
|
@@ -796,6 +788,8 @@ svg.${prefix}-icon-xl { width: 32px; height: 32px; }
|
|
|
796
788
|
justify-content: center;
|
|
797
789
|
}`;
|
|
798
790
|
}
|
|
791
|
+
|
|
792
|
+
// src/renderer/styles/data.ts
|
|
799
793
|
function generateDataStyles(_theme, prefix) {
|
|
800
794
|
return `/* Data Components */
|
|
801
795
|
.${prefix}-table {
|
|
@@ -854,6 +848,8 @@ function generateDataStyles(_theme, prefix) {
|
|
|
854
848
|
border-bottom: none;
|
|
855
849
|
}`;
|
|
856
850
|
}
|
|
851
|
+
|
|
852
|
+
// src/renderer/styles/feedback.ts
|
|
857
853
|
function generateFeedbackStyles(_theme, prefix) {
|
|
858
854
|
return `/* Feedback Components */
|
|
859
855
|
.${prefix}-alert {
|
|
@@ -945,6 +941,8 @@ function generateFeedbackStyles(_theme, prefix) {
|
|
|
945
941
|
to { transform: rotate(360deg); }
|
|
946
942
|
}`;
|
|
947
943
|
}
|
|
944
|
+
|
|
945
|
+
// src/renderer/styles/overlay.ts
|
|
948
946
|
function generateOverlayStyles(_theme, prefix) {
|
|
949
947
|
return `/* Overlay Components */
|
|
950
948
|
.${prefix}-tooltip-wrapper {
|
|
@@ -1043,6 +1041,8 @@ function generateOverlayStyles(_theme, prefix) {
|
|
|
1043
1041
|
cursor: not-allowed;
|
|
1044
1042
|
}`;
|
|
1045
1043
|
}
|
|
1044
|
+
|
|
1045
|
+
// src/renderer/styles/navigation.ts
|
|
1046
1046
|
function generateNavigationStyles(_theme, prefix) {
|
|
1047
1047
|
return `/* Navigation Components */
|
|
1048
1048
|
.${prefix}-nav {
|
|
@@ -1155,6 +1155,8 @@ function generateNavigationStyles(_theme, prefix) {
|
|
|
1155
1155
|
color: var(--${prefix}-muted);
|
|
1156
1156
|
}`;
|
|
1157
1157
|
}
|
|
1158
|
+
|
|
1159
|
+
// src/renderer/styles/semantic.ts
|
|
1158
1160
|
function generateSemanticMarkerStyles(_theme, prefix) {
|
|
1159
1161
|
return `/* Semantic Markers */
|
|
1160
1162
|
|
|
@@ -1241,6 +1243,8 @@ function generateSemanticMarkerStyles(_theme, prefix) {
|
|
|
1241
1243
|
color: var(--${prefix}-muted);
|
|
1242
1244
|
}`;
|
|
1243
1245
|
}
|
|
1246
|
+
|
|
1247
|
+
// src/renderer/styles/accessibility.ts
|
|
1244
1248
|
function generateAccessibilityStyles(prefix) {
|
|
1245
1249
|
return `/* Accessibility Utilities */
|
|
1246
1250
|
.sr-only {
|
|
@@ -1278,6 +1282,24 @@ function generateAccessibilityStyles(prefix) {
|
|
|
1278
1282
|
}`;
|
|
1279
1283
|
}
|
|
1280
1284
|
|
|
1285
|
+
// src/renderer/styles-components.ts
|
|
1286
|
+
function generateComponentStyles(_theme, prefix = "wf") {
|
|
1287
|
+
const parts = [
|
|
1288
|
+
generateContainerStyles(prefix),
|
|
1289
|
+
generateTextStyles(prefix),
|
|
1290
|
+
generateInputStyles(_theme, prefix),
|
|
1291
|
+
generateButtonStyles(_theme, prefix),
|
|
1292
|
+
generateDisplayStyles(_theme, prefix),
|
|
1293
|
+
generateDataStyles(_theme, prefix),
|
|
1294
|
+
generateFeedbackStyles(_theme, prefix),
|
|
1295
|
+
generateOverlayStyles(_theme, prefix),
|
|
1296
|
+
generateNavigationStyles(_theme, prefix),
|
|
1297
|
+
generateSemanticMarkerStyles(_theme, prefix),
|
|
1298
|
+
generateAccessibilityStyles(prefix)
|
|
1299
|
+
];
|
|
1300
|
+
return parts.join("\n\n");
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1281
1303
|
// src/renderer/styles.ts
|
|
1282
1304
|
function generateStyles(theme, prefix = "wf") {
|
|
1283
1305
|
const parts = [
|
|
@@ -1561,6 +1583,7 @@ function generateLayoutClasses(prefix) {
|
|
|
1561
1583
|
padding: 16px;
|
|
1562
1584
|
display: flex;
|
|
1563
1585
|
flex-direction: column;
|
|
1586
|
+
min-height: 0;
|
|
1564
1587
|
}
|
|
1565
1588
|
|
|
1566
1589
|
/* Scrollable main content */
|
|
@@ -1569,6 +1592,11 @@ function generateLayoutClasses(prefix) {
|
|
|
1569
1592
|
overflow-x: hidden;
|
|
1570
1593
|
}
|
|
1571
1594
|
|
|
1595
|
+
/* Col containing scrollable main needs min-height: 0 for scroll to work */
|
|
1596
|
+
.${prefix}-col:has(> .${prefix}-main.${prefix}-scroll) {
|
|
1597
|
+
min-height: 0;
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1572
1600
|
/* Main content should align to top, not stretch to fill */
|
|
1573
1601
|
/* But allow explicit flex=1 to override */
|
|
1574
1602
|
.${prefix}-main > .${prefix}-col:not(.${prefix}-flex-1) {
|
|
@@ -1803,6 +1831,248 @@ function resolveViewport(viewport, device) {
|
|
|
1803
1831
|
return DEFAULT_VIEWPORT;
|
|
1804
1832
|
}
|
|
1805
1833
|
|
|
1834
|
+
// src/renderer/html/components.ts
|
|
1835
|
+
function buildClassString(classes) {
|
|
1836
|
+
return classes.filter(Boolean).join(" ");
|
|
1837
|
+
}
|
|
1838
|
+
var SIZE_TOKENS = {
|
|
1839
|
+
icon: { xs: 12, sm: 14, md: 16, lg: 20, xl: 24 },
|
|
1840
|
+
avatar: { xs: 24, sm: 32, md: 40, lg: 48, xl: 64 },
|
|
1841
|
+
spinner: { xs: 12, sm: 16, md: 24, lg: 32, xl: 48 }
|
|
1842
|
+
};
|
|
1843
|
+
function resolveSizeValue(size, componentType, prefix) {
|
|
1844
|
+
if (size === void 0) {
|
|
1845
|
+
return {};
|
|
1846
|
+
}
|
|
1847
|
+
if (typeof size === "string") {
|
|
1848
|
+
const tokens = SIZE_TOKENS[componentType];
|
|
1849
|
+
if (size in tokens) {
|
|
1850
|
+
return { className: `${prefix}-${componentType}-${size}` };
|
|
1851
|
+
}
|
|
1852
|
+
const parsed = parseInt(size, 10);
|
|
1853
|
+
if (!isNaN(parsed)) {
|
|
1854
|
+
return { style: `width: ${parsed}px; height: ${parsed}px;` };
|
|
1855
|
+
}
|
|
1856
|
+
return {};
|
|
1857
|
+
}
|
|
1858
|
+
if (typeof size === "number") {
|
|
1859
|
+
return { style: `width: ${size}px; height: ${size}px;` };
|
|
1860
|
+
}
|
|
1861
|
+
return {};
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
// src/renderer/html/renderers/layout.ts
|
|
1865
|
+
function renderHeader(node, ctx) {
|
|
1866
|
+
const classes = ctx.buildClassString([
|
|
1867
|
+
`${ctx.prefix}-header`,
|
|
1868
|
+
node.border === false ? `${ctx.prefix}-no-border` : void 0,
|
|
1869
|
+
...ctx.getCommonClasses(node)
|
|
1870
|
+
]);
|
|
1871
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1872
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1873
|
+
const children = ctx.renderChildren(node.children);
|
|
1874
|
+
return `<header class="${classes}"${styleAttr}>
|
|
1875
|
+
${children}
|
|
1876
|
+
</header>`;
|
|
1877
|
+
}
|
|
1878
|
+
function renderMain(node, ctx) {
|
|
1879
|
+
const classes = ctx.buildClassString([
|
|
1880
|
+
`${ctx.prefix}-main`,
|
|
1881
|
+
node.scroll ? `${ctx.prefix}-scroll` : void 0,
|
|
1882
|
+
...ctx.getCommonClasses(node)
|
|
1883
|
+
]);
|
|
1884
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1885
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1886
|
+
const children = ctx.renderChildren(node.children);
|
|
1887
|
+
return `<main class="${classes}"${styleAttr}>
|
|
1888
|
+
${children}
|
|
1889
|
+
</main>`;
|
|
1890
|
+
}
|
|
1891
|
+
function renderFooter(node, ctx) {
|
|
1892
|
+
const classes = ctx.buildClassString([
|
|
1893
|
+
`${ctx.prefix}-footer`,
|
|
1894
|
+
node.border === false ? `${ctx.prefix}-no-border` : void 0,
|
|
1895
|
+
...ctx.getCommonClasses(node)
|
|
1896
|
+
]);
|
|
1897
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1898
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1899
|
+
const children = ctx.renderChildren(node.children);
|
|
1900
|
+
return `<footer class="${classes}"${styleAttr}>
|
|
1901
|
+
${children}
|
|
1902
|
+
</footer>`;
|
|
1903
|
+
}
|
|
1904
|
+
function renderSidebar(node, ctx) {
|
|
1905
|
+
const classes = ctx.buildClassString([
|
|
1906
|
+
`${ctx.prefix}-sidebar`,
|
|
1907
|
+
node.position === "right" ? `${ctx.prefix}-sidebar-right` : void 0,
|
|
1908
|
+
...ctx.getCommonClasses(node)
|
|
1909
|
+
]);
|
|
1910
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1911
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1912
|
+
const children = ctx.renderChildren(node.children);
|
|
1913
|
+
return `<aside class="${classes}"${styleAttr}>
|
|
1914
|
+
${children}
|
|
1915
|
+
</aside>`;
|
|
1916
|
+
}
|
|
1917
|
+
function renderSection(node, ctx) {
|
|
1918
|
+
const classes = ctx.buildClassString([
|
|
1919
|
+
`${ctx.prefix}-section`,
|
|
1920
|
+
...ctx.getCommonClasses(node)
|
|
1921
|
+
]);
|
|
1922
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1923
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1924
|
+
const title = node.title ? `<h2 class="${ctx.prefix}-title">${ctx.escapeHtml(node.title)}</h2>
|
|
1925
|
+
` : "";
|
|
1926
|
+
const children = ctx.renderChildren(node.children);
|
|
1927
|
+
return `<section class="${classes}"${styleAttr}>
|
|
1928
|
+
${title}${children}
|
|
1929
|
+
</section>`;
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
// src/renderer/html/renderers/grid.ts
|
|
1933
|
+
function renderRow(node, ctx) {
|
|
1934
|
+
const classes = ctx.buildClassString([
|
|
1935
|
+
`${ctx.prefix}-row`,
|
|
1936
|
+
...ctx.getCommonClasses(node)
|
|
1937
|
+
]);
|
|
1938
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1939
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1940
|
+
const children = ctx.renderChildren(node.children);
|
|
1941
|
+
return `<div class="${classes}"${styleAttr}>
|
|
1942
|
+
${children}
|
|
1943
|
+
</div>`;
|
|
1944
|
+
}
|
|
1945
|
+
function renderCol(node, ctx) {
|
|
1946
|
+
const classes = ctx.buildClassString([
|
|
1947
|
+
`${ctx.prefix}-col`,
|
|
1948
|
+
node.span ? `${ctx.prefix}-col-${node.span}` : void 0,
|
|
1949
|
+
// Responsive breakpoint classes
|
|
1950
|
+
node.sm ? `${ctx.prefix}-col-sm-${node.sm}` : void 0,
|
|
1951
|
+
node.md ? `${ctx.prefix}-col-md-${node.md}` : void 0,
|
|
1952
|
+
node.lg ? `${ctx.prefix}-col-lg-${node.lg}` : void 0,
|
|
1953
|
+
node.xl ? `${ctx.prefix}-col-xl-${node.xl}` : void 0,
|
|
1954
|
+
...ctx.getCommonClasses(node)
|
|
1955
|
+
]);
|
|
1956
|
+
const styles = ctx.buildColStyles(node);
|
|
1957
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1958
|
+
const children = ctx.renderChildren(node.children);
|
|
1959
|
+
return `<div class="${classes}"${styleAttr}>
|
|
1960
|
+
${children}
|
|
1961
|
+
</div>`;
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
// src/renderer/html/renderers/container.ts
|
|
1965
|
+
function renderCard(node, ctx) {
|
|
1966
|
+
const hasExplicitWidth = node.w !== void 0;
|
|
1967
|
+
const classes = ctx.buildClassString([
|
|
1968
|
+
`${ctx.prefix}-card`,
|
|
1969
|
+
!hasExplicitWidth ? `${ctx.prefix}-card-flex` : void 0,
|
|
1970
|
+
node.shadow ? `${ctx.prefix}-card-shadow-${node.shadow}` : void 0,
|
|
1971
|
+
...ctx.getCommonClasses(node)
|
|
1972
|
+
]);
|
|
1973
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1974
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1975
|
+
const title = node.title ? `<h3 class="${ctx.prefix}-title">${ctx.escapeHtml(node.title)}</h3>
|
|
1976
|
+
` : "";
|
|
1977
|
+
const children = ctx.renderChildren(node.children);
|
|
1978
|
+
return `<div class="${classes}"${styleAttr}>
|
|
1979
|
+
${title}${children}
|
|
1980
|
+
</div>`;
|
|
1981
|
+
}
|
|
1982
|
+
function renderModal(node, ctx) {
|
|
1983
|
+
const classes = ctx.buildClassString([
|
|
1984
|
+
`${ctx.prefix}-modal`,
|
|
1985
|
+
...ctx.getCommonClasses(node)
|
|
1986
|
+
]);
|
|
1987
|
+
const styles = ctx.buildCommonStyles(node);
|
|
1988
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
1989
|
+
const title = node.title ? `<h2 class="${ctx.prefix}-title">${ctx.escapeHtml(node.title)}</h2>
|
|
1990
|
+
` : "";
|
|
1991
|
+
const children = ctx.renderChildren(node.children);
|
|
1992
|
+
return `<div class="${ctx.prefix}-modal-backdrop">
|
|
1993
|
+
<div class="${classes}"${styleAttr} role="dialog" aria-modal="true">
|
|
1994
|
+
${title}${children}
|
|
1995
|
+
</div>
|
|
1996
|
+
</div>`;
|
|
1997
|
+
}
|
|
1998
|
+
function renderDrawer(node, ctx) {
|
|
1999
|
+
const position = node.position || "left";
|
|
2000
|
+
const classes = ctx.buildClassString([
|
|
2001
|
+
`${ctx.prefix}-drawer`,
|
|
2002
|
+
`${ctx.prefix}-drawer-${position}`,
|
|
2003
|
+
...ctx.getCommonClasses(node)
|
|
2004
|
+
]);
|
|
2005
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2006
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2007
|
+
const title = node.title ? `<h2 class="${ctx.prefix}-title">${ctx.escapeHtml(node.title)}</h2>
|
|
2008
|
+
` : "";
|
|
2009
|
+
const children = ctx.renderChildren(node.children);
|
|
2010
|
+
return `<aside class="${classes}"${styleAttr}>
|
|
2011
|
+
${title}${children}
|
|
2012
|
+
</aside>`;
|
|
2013
|
+
}
|
|
2014
|
+
function renderAccordion(node, ctx) {
|
|
2015
|
+
const classes = ctx.buildClassString([
|
|
2016
|
+
`${ctx.prefix}-accordion`,
|
|
2017
|
+
...ctx.getCommonClasses(node)
|
|
2018
|
+
]);
|
|
2019
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2020
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2021
|
+
const title = node.title ? `<button class="${ctx.prefix}-accordion-header">${ctx.escapeHtml(node.title)}</button>
|
|
2022
|
+
` : "";
|
|
2023
|
+
const children = ctx.renderChildren(node.children);
|
|
2024
|
+
return `<div class="${classes}"${styleAttr}>
|
|
2025
|
+
${title}<div class="${ctx.prefix}-accordion-content">
|
|
2026
|
+
${children}
|
|
2027
|
+
</div>
|
|
2028
|
+
</div>`;
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
// src/renderer/html/renderers/text.ts
|
|
2032
|
+
function renderText(node, ctx) {
|
|
2033
|
+
const classes = ctx.buildClassString([
|
|
2034
|
+
`${ctx.prefix}-text`,
|
|
2035
|
+
node.size ? `${ctx.prefix}-text-${node.size}` : void 0,
|
|
2036
|
+
node.weight ? `${ctx.prefix}-text-${node.weight}` : void 0,
|
|
2037
|
+
node.align ? `${ctx.prefix}-text-${node.align}` : void 0,
|
|
2038
|
+
node.muted ? `${ctx.prefix}-text-muted` : void 0,
|
|
2039
|
+
...ctx.getCommonClasses(node)
|
|
2040
|
+
]);
|
|
2041
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2042
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2043
|
+
return `<p class="${classes}"${styleAttr}>${ctx.escapeHtml(node.content)}</p>`;
|
|
2044
|
+
}
|
|
2045
|
+
function renderTitle(node, ctx) {
|
|
2046
|
+
const level = node.level || 1;
|
|
2047
|
+
const tag = `h${level}`;
|
|
2048
|
+
const classes = ctx.buildClassString([
|
|
2049
|
+
`${ctx.prefix}-title`,
|
|
2050
|
+
node.size ? `${ctx.prefix}-text-${node.size}` : void 0,
|
|
2051
|
+
node.align ? `${ctx.prefix}-text-${node.align}` : void 0,
|
|
2052
|
+
...ctx.getCommonClasses(node)
|
|
2053
|
+
]);
|
|
2054
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2055
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2056
|
+
return `<${tag} class="${classes}"${styleAttr}>${ctx.escapeHtml(node.content)}</${tag}>`;
|
|
2057
|
+
}
|
|
2058
|
+
function renderLink(node, ctx) {
|
|
2059
|
+
const classes = ctx.buildClassString([
|
|
2060
|
+
`${ctx.prefix}-link`,
|
|
2061
|
+
...ctx.getCommonClasses(node)
|
|
2062
|
+
]);
|
|
2063
|
+
const styles = ctx.buildCommonStyles(node);
|
|
2064
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
2065
|
+
const attrs = {
|
|
2066
|
+
class: classes,
|
|
2067
|
+
href: node.href || "#"
|
|
2068
|
+
};
|
|
2069
|
+
if (node.external) {
|
|
2070
|
+
attrs.target = "_blank";
|
|
2071
|
+
attrs.rel = "noopener noreferrer";
|
|
2072
|
+
}
|
|
2073
|
+
return `<a${ctx.buildAttrsString(attrs)}${styleAttr}>${ctx.escapeHtml(node.content)}</a>`;
|
|
2074
|
+
}
|
|
2075
|
+
|
|
1806
2076
|
// src/icons/lucide-icons.ts
|
|
1807
2077
|
var lucideIcons = {
|
|
1808
2078
|
"a-arrow-down": [
|
|
@@ -48202,34 +48472,658 @@ function renderIconSvg(data, _size = 24, strokeWidth = 2, className = "", styleA
|
|
|
48202
48472
|
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="${strokeWidth}" stroke-linecap="round" stroke-linejoin="round" class="${className}"${styleAttr}>${elements}</svg>`;
|
|
48203
48473
|
}
|
|
48204
48474
|
|
|
48205
|
-
// src/renderer/html/
|
|
48206
|
-
function
|
|
48207
|
-
|
|
48475
|
+
// src/renderer/html/renderers/button.ts
|
|
48476
|
+
function renderButton(node, ctx) {
|
|
48477
|
+
const isIconOnly = node.icon && (!node.content.trim() || node.content === "Button");
|
|
48478
|
+
const classes = ctx.buildClassString([
|
|
48479
|
+
`${ctx.prefix}-button`,
|
|
48480
|
+
node.primary ? `${ctx.prefix}-button-primary` : void 0,
|
|
48481
|
+
node.secondary ? `${ctx.prefix}-button-secondary` : void 0,
|
|
48482
|
+
node.outline ? `${ctx.prefix}-button-outline` : void 0,
|
|
48483
|
+
node.ghost ? `${ctx.prefix}-button-ghost` : void 0,
|
|
48484
|
+
node.danger ? `${ctx.prefix}-button-danger` : void 0,
|
|
48485
|
+
node.size ? `${ctx.prefix}-button-${node.size}` : void 0,
|
|
48486
|
+
node.disabled ? `${ctx.prefix}-button-disabled` : void 0,
|
|
48487
|
+
node.loading ? `${ctx.prefix}-button-loading` : void 0,
|
|
48488
|
+
isIconOnly ? `${ctx.prefix}-button-icon-only` : void 0,
|
|
48489
|
+
...ctx.getCommonClasses(node)
|
|
48490
|
+
]);
|
|
48491
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48492
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48493
|
+
const attrs = {
|
|
48494
|
+
class: classes,
|
|
48495
|
+
disabled: node.disabled
|
|
48496
|
+
};
|
|
48497
|
+
let icon = "";
|
|
48498
|
+
if (node.icon) {
|
|
48499
|
+
const iconData = getIconData(node.icon);
|
|
48500
|
+
if (iconData) {
|
|
48501
|
+
icon = renderIconSvg(iconData, 16, 2, `${ctx.prefix}-icon`);
|
|
48502
|
+
} else {
|
|
48503
|
+
icon = `<span class="${ctx.prefix}-icon">[${ctx.escapeHtml(node.icon)}]</span>`;
|
|
48504
|
+
}
|
|
48505
|
+
}
|
|
48506
|
+
const loading = node.loading ? `<span class="${ctx.prefix}-spinner ${ctx.prefix}-spinner-sm"></span>` : "";
|
|
48507
|
+
const content = isIconOnly ? "" : ctx.escapeHtml(node.content);
|
|
48508
|
+
return `<button${ctx.buildAttrsString(attrs)}${styleAttr}>${loading}${icon}${content}</button>`;
|
|
48208
48509
|
}
|
|
48209
|
-
|
|
48210
|
-
|
|
48211
|
-
|
|
48212
|
-
|
|
48213
|
-
}
|
|
48214
|
-
|
|
48215
|
-
|
|
48216
|
-
|
|
48510
|
+
|
|
48511
|
+
// src/renderer/html/renderers/feedback.ts
|
|
48512
|
+
function renderAlert(node, ctx) {
|
|
48513
|
+
const classes = ctx.buildClassString([
|
|
48514
|
+
`${ctx.prefix}-alert`,
|
|
48515
|
+
node.variant ? `${ctx.prefix}-alert-${node.variant}` : void 0,
|
|
48516
|
+
...ctx.getCommonClasses(node)
|
|
48517
|
+
]);
|
|
48518
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48519
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48520
|
+
const dismissBtn = node.dismissible ? ` <button class="${ctx.prefix}-alert-close" aria-label="Close">×</button>` : "";
|
|
48521
|
+
return `<div class="${classes}"${styleAttr} role="alert">${ctx.escapeHtml(node.content)}${dismissBtn}</div>`;
|
|
48522
|
+
}
|
|
48523
|
+
function renderToast(node, ctx) {
|
|
48524
|
+
const classes = ctx.buildClassString([
|
|
48525
|
+
`${ctx.prefix}-toast`,
|
|
48526
|
+
node.position ? `${ctx.prefix}-toast-${node.position}` : void 0,
|
|
48527
|
+
node.variant ? `${ctx.prefix}-toast-${node.variant}` : void 0,
|
|
48528
|
+
...ctx.getCommonClasses(node)
|
|
48529
|
+
]);
|
|
48530
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48531
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48532
|
+
return `<div class="${classes}"${styleAttr} role="status">${ctx.escapeHtml(node.content)}</div>`;
|
|
48533
|
+
}
|
|
48534
|
+
function renderProgress(node, ctx) {
|
|
48535
|
+
const classes = ctx.buildClassString([
|
|
48536
|
+
`${ctx.prefix}-progress`,
|
|
48537
|
+
...ctx.getCommonClasses(node)
|
|
48538
|
+
]);
|
|
48539
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48540
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48541
|
+
const value = node.value || 0;
|
|
48542
|
+
const max = node.max || 100;
|
|
48543
|
+
const percentage = Math.round(value / max * 100);
|
|
48544
|
+
const label = node.label ? `<span class="${ctx.prefix}-progress-label">${ctx.escapeHtml(node.label)}</span>` : "";
|
|
48545
|
+
if (node.indeterminate) {
|
|
48546
|
+
return `<div class="${classes} ${ctx.prefix}-progress-indeterminate"${styleAttr} role="progressbar">${label}</div>`;
|
|
48217
48547
|
}
|
|
48218
|
-
|
|
48219
|
-
|
|
48220
|
-
|
|
48221
|
-
|
|
48548
|
+
return `<div class="${classes}"${styleAttr} role="progressbar" aria-valuenow="${value}" aria-valuemin="0" aria-valuemax="${max}">
|
|
48549
|
+
${label}
|
|
48550
|
+
<div class="${ctx.prefix}-progress-bar" style="width: ${percentage}%"></div>
|
|
48551
|
+
</div>`;
|
|
48552
|
+
}
|
|
48553
|
+
function renderSpinner(node, ctx) {
|
|
48554
|
+
const sizeResolved = resolveSizeValue(node.size, "spinner", ctx.prefix);
|
|
48555
|
+
const classes = ctx.buildClassString([
|
|
48556
|
+
`${ctx.prefix}-spinner`,
|
|
48557
|
+
sizeResolved.className,
|
|
48558
|
+
...ctx.getCommonClasses(node)
|
|
48559
|
+
]);
|
|
48560
|
+
const baseStyles = ctx.buildCommonStyles(node);
|
|
48561
|
+
const sizeStyle = sizeResolved.style || "";
|
|
48562
|
+
const combinedStyles = baseStyles && sizeStyle ? `${baseStyles}; ${sizeStyle}` : baseStyles || sizeStyle;
|
|
48563
|
+
const styleAttr = combinedStyles ? ` style="${combinedStyles}"` : "";
|
|
48564
|
+
const label = node.label || "Loading...";
|
|
48565
|
+
return `<span class="${classes}"${styleAttr} role="status" aria-label="${ctx.escapeHtml(label)}"></span>`;
|
|
48566
|
+
}
|
|
48567
|
+
|
|
48568
|
+
// src/renderer/html/renderers/input.ts
|
|
48569
|
+
function renderInput(node, ctx) {
|
|
48570
|
+
const inputClasses = ctx.buildClassString([
|
|
48571
|
+
`${ctx.prefix}-input`,
|
|
48572
|
+
node.icon ? `${ctx.prefix}-input-with-icon` : void 0,
|
|
48573
|
+
...ctx.getCommonClasses(node)
|
|
48574
|
+
]);
|
|
48575
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48576
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48577
|
+
const attrs = {
|
|
48578
|
+
class: inputClasses,
|
|
48579
|
+
type: node.inputType || "text",
|
|
48580
|
+
placeholder: node.placeholder,
|
|
48581
|
+
value: node.value,
|
|
48582
|
+
disabled: node.disabled,
|
|
48583
|
+
required: node.required,
|
|
48584
|
+
readonly: node.readonly
|
|
48585
|
+
};
|
|
48586
|
+
const inputElement = `<input${ctx.buildAttrsString(attrs)} />`;
|
|
48587
|
+
if (node.icon) {
|
|
48588
|
+
const iconData = getIconData(node.icon);
|
|
48589
|
+
let iconHtml;
|
|
48590
|
+
if (iconData) {
|
|
48591
|
+
iconHtml = renderIconSvg(iconData, 16, 2, `${ctx.prefix}-input-icon`);
|
|
48592
|
+
} else {
|
|
48593
|
+
iconHtml = `<span class="${ctx.prefix}-input-icon">[${ctx.escapeHtml(node.icon)}]</span>`;
|
|
48222
48594
|
}
|
|
48223
|
-
const
|
|
48224
|
-
|
|
48225
|
-
|
|
48595
|
+
const wrapperClasses = ctx.buildClassString([`${ctx.prefix}-input-wrapper`]);
|
|
48596
|
+
const wrapper = `<div class="${wrapperClasses}"${styleAttr}>${iconHtml}${inputElement}</div>`;
|
|
48597
|
+
const shouldShowLabel = node.label && !(node.label === "Label" && node.placeholder);
|
|
48598
|
+
if (shouldShowLabel) {
|
|
48599
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48600
|
+
${wrapper}`;
|
|
48226
48601
|
}
|
|
48227
|
-
return
|
|
48602
|
+
return wrapper;
|
|
48228
48603
|
}
|
|
48229
|
-
|
|
48230
|
-
|
|
48604
|
+
const input = `<input${ctx.buildAttrsString(attrs)}${styleAttr} />`;
|
|
48605
|
+
const shouldShowLabel2 = node.label && !(node.label === "Label" && node.placeholder);
|
|
48606
|
+
if (shouldShowLabel2) {
|
|
48607
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48608
|
+
${input}`;
|
|
48231
48609
|
}
|
|
48232
|
-
return
|
|
48610
|
+
return input;
|
|
48611
|
+
}
|
|
48612
|
+
function renderTextarea(node, ctx) {
|
|
48613
|
+
const classes = ctx.buildClassString([
|
|
48614
|
+
`${ctx.prefix}-input`,
|
|
48615
|
+
...ctx.getCommonClasses(node)
|
|
48616
|
+
]);
|
|
48617
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48618
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48619
|
+
const attrs = {
|
|
48620
|
+
class: classes,
|
|
48621
|
+
placeholder: node.placeholder,
|
|
48622
|
+
disabled: node.disabled,
|
|
48623
|
+
required: node.required,
|
|
48624
|
+
rows: node.rows?.toString()
|
|
48625
|
+
};
|
|
48626
|
+
const textarea = `<textarea${ctx.buildAttrsString(attrs)}${styleAttr}>${ctx.escapeHtml(node.value || "")}</textarea>`;
|
|
48627
|
+
if (node.label) {
|
|
48628
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48629
|
+
${textarea}`;
|
|
48630
|
+
}
|
|
48631
|
+
return textarea;
|
|
48632
|
+
}
|
|
48633
|
+
function renderSelect(node, ctx) {
|
|
48634
|
+
const classes = ctx.buildClassString([
|
|
48635
|
+
`${ctx.prefix}-input`,
|
|
48636
|
+
...ctx.getCommonClasses(node)
|
|
48637
|
+
]);
|
|
48638
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48639
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48640
|
+
const attrs = {
|
|
48641
|
+
class: classes,
|
|
48642
|
+
disabled: node.disabled,
|
|
48643
|
+
required: node.required
|
|
48644
|
+
};
|
|
48645
|
+
const options = node.options.map((opt) => {
|
|
48646
|
+
if (typeof opt === "string") {
|
|
48647
|
+
const selected2 = opt === node.value ? " selected" : "";
|
|
48648
|
+
return `<option value="${ctx.escapeHtml(opt)}"${selected2}>${ctx.escapeHtml(opt)}</option>`;
|
|
48649
|
+
}
|
|
48650
|
+
const selected = opt.value === node.value ? " selected" : "";
|
|
48651
|
+
return `<option value="${ctx.escapeHtml(opt.value)}"${selected}>${ctx.escapeHtml(opt.label)}</option>`;
|
|
48652
|
+
}).join("\n");
|
|
48653
|
+
const placeholder = node.placeholder ? `<option value="" disabled selected>${ctx.escapeHtml(node.placeholder)}</option>
|
|
48654
|
+
` : "";
|
|
48655
|
+
const select = `<select${ctx.buildAttrsString(attrs)}${styleAttr}>
|
|
48656
|
+
${placeholder}${options}
|
|
48657
|
+
</select>`;
|
|
48658
|
+
if (node.label) {
|
|
48659
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48660
|
+
${select}`;
|
|
48661
|
+
}
|
|
48662
|
+
return select;
|
|
48663
|
+
}
|
|
48664
|
+
function renderCheckbox(node, ctx) {
|
|
48665
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48666
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48667
|
+
const attrs = {
|
|
48668
|
+
type: "checkbox",
|
|
48669
|
+
checked: node.checked,
|
|
48670
|
+
disabled: node.disabled
|
|
48671
|
+
};
|
|
48672
|
+
const checkbox = `<input${ctx.buildAttrsString(attrs)} />`;
|
|
48673
|
+
if (node.label) {
|
|
48674
|
+
return `<label class="${ctx.prefix}-checkbox"${styleAttr}>${checkbox}<span>${ctx.escapeHtml(node.label)}</span></label>`;
|
|
48675
|
+
}
|
|
48676
|
+
return checkbox;
|
|
48677
|
+
}
|
|
48678
|
+
function renderRadio(node, ctx) {
|
|
48679
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48680
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48681
|
+
const attrs = {
|
|
48682
|
+
type: "radio",
|
|
48683
|
+
name: node.name,
|
|
48684
|
+
checked: node.checked,
|
|
48685
|
+
disabled: node.disabled
|
|
48686
|
+
};
|
|
48687
|
+
const radio = `<input${ctx.buildAttrsString(attrs)} />`;
|
|
48688
|
+
if (node.label) {
|
|
48689
|
+
return `<label class="${ctx.prefix}-radio"${styleAttr}>${radio}<span>${ctx.escapeHtml(node.label)}</span></label>`;
|
|
48690
|
+
}
|
|
48691
|
+
return radio;
|
|
48692
|
+
}
|
|
48693
|
+
function renderSwitch(node, ctx) {
|
|
48694
|
+
const classes = ctx.buildClassString([
|
|
48695
|
+
`${ctx.prefix}-switch`,
|
|
48696
|
+
...ctx.getCommonClasses(node)
|
|
48697
|
+
]);
|
|
48698
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48699
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48700
|
+
const attrs = {
|
|
48701
|
+
type: "checkbox",
|
|
48702
|
+
role: "switch",
|
|
48703
|
+
checked: node.checked,
|
|
48704
|
+
disabled: node.disabled
|
|
48705
|
+
};
|
|
48706
|
+
const switchEl = `<input${ctx.buildAttrsString(attrs)} />`;
|
|
48707
|
+
if (node.label) {
|
|
48708
|
+
return `<label class="${classes}"${styleAttr}>${switchEl} ${ctx.escapeHtml(node.label)}</label>`;
|
|
48709
|
+
}
|
|
48710
|
+
return `<label class="${classes}"${styleAttr}>${switchEl}</label>`;
|
|
48711
|
+
}
|
|
48712
|
+
function renderSlider(node, ctx) {
|
|
48713
|
+
const classes = ctx.buildClassString([
|
|
48714
|
+
`${ctx.prefix}-slider`,
|
|
48715
|
+
...ctx.getCommonClasses(node)
|
|
48716
|
+
]);
|
|
48717
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48718
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48719
|
+
const attrs = {
|
|
48720
|
+
class: classes,
|
|
48721
|
+
type: "range",
|
|
48722
|
+
min: node.min?.toString(),
|
|
48723
|
+
max: node.max?.toString(),
|
|
48724
|
+
step: node.step?.toString(),
|
|
48725
|
+
value: node.value?.toString(),
|
|
48726
|
+
disabled: node.disabled
|
|
48727
|
+
};
|
|
48728
|
+
const slider = `<input${ctx.buildAttrsString(attrs)}${styleAttr} />`;
|
|
48729
|
+
if (node.label) {
|
|
48730
|
+
return `<label class="${ctx.prefix}-input-label">${ctx.escapeHtml(node.label)}</label>
|
|
48731
|
+
${slider}`;
|
|
48732
|
+
}
|
|
48733
|
+
return slider;
|
|
48734
|
+
}
|
|
48735
|
+
|
|
48736
|
+
// src/renderer/html/renderers/display.ts
|
|
48737
|
+
function renderImage(node, ctx) {
|
|
48738
|
+
const classes = ctx.buildClassString([
|
|
48739
|
+
`${ctx.prefix}-image`,
|
|
48740
|
+
...ctx.getCommonClasses(node)
|
|
48741
|
+
]);
|
|
48742
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48743
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48744
|
+
if (node.src) {
|
|
48745
|
+
const attrs = {
|
|
48746
|
+
class: classes,
|
|
48747
|
+
src: node.src,
|
|
48748
|
+
alt: node.alt || "Image"
|
|
48749
|
+
};
|
|
48750
|
+
const imgStyleAttr = styles ? `; ${styles}` : "";
|
|
48751
|
+
return `<img${ctx.buildAttrsString(attrs)}${imgStyleAttr ? ` style="${imgStyleAttr.slice(2)}"` : ""} />`;
|
|
48752
|
+
}
|
|
48753
|
+
const label = node.alt || "Image";
|
|
48754
|
+
const icon = `<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>`;
|
|
48755
|
+
return `<div class="${classes}"${styleAttr} role="img" aria-label="${ctx.escapeHtml(label)}">${icon}<span>${ctx.escapeHtml(label)}</span></div>`;
|
|
48756
|
+
}
|
|
48757
|
+
function renderPlaceholder(node, ctx) {
|
|
48758
|
+
const classes = ctx.buildClassString([
|
|
48759
|
+
`${ctx.prefix}-placeholder`,
|
|
48760
|
+
node.children && node.children.length > 0 ? `${ctx.prefix}-placeholder-with-children` : void 0,
|
|
48761
|
+
...ctx.getCommonClasses(node)
|
|
48762
|
+
]);
|
|
48763
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48764
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48765
|
+
const label = node.label ? ctx.escapeHtml(node.label) : "Placeholder";
|
|
48766
|
+
if (node.children && node.children.length > 0) {
|
|
48767
|
+
const childrenHtml = ctx.renderChildren(node.children);
|
|
48768
|
+
return `<div class="${classes}"${styleAttr}>
|
|
48769
|
+
<span class="${ctx.prefix}-placeholder-label">${label}</span>
|
|
48770
|
+
<div class="${ctx.prefix}-placeholder-overlay">${childrenHtml}</div>
|
|
48771
|
+
</div>`;
|
|
48772
|
+
}
|
|
48773
|
+
return `<div class="${classes}"${styleAttr}>${label}</div>`;
|
|
48774
|
+
}
|
|
48775
|
+
function renderAvatar(node, ctx) {
|
|
48776
|
+
const sizeResolved = resolveSizeValue(node.size, "avatar", ctx.prefix);
|
|
48777
|
+
const classes = ctx.buildClassString([
|
|
48778
|
+
`${ctx.prefix}-avatar`,
|
|
48779
|
+
sizeResolved.className,
|
|
48780
|
+
...ctx.getCommonClasses(node)
|
|
48781
|
+
]);
|
|
48782
|
+
const baseStyles = ctx.buildCommonStyles(node);
|
|
48783
|
+
const sizeStyle = sizeResolved.style || "";
|
|
48784
|
+
const combinedStyles = baseStyles && sizeStyle ? `${baseStyles}; ${sizeStyle}` : baseStyles || sizeStyle;
|
|
48785
|
+
const styleAttr = combinedStyles ? ` style="${combinedStyles}"` : "";
|
|
48786
|
+
const initials = node.name ? node.name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) : "?";
|
|
48787
|
+
return `<div class="${classes}"${styleAttr} role="img" aria-label="${ctx.escapeHtml(node.name || "Avatar")}">${initials}</div>`;
|
|
48788
|
+
}
|
|
48789
|
+
function renderBadge(node, ctx) {
|
|
48790
|
+
if (node.icon) {
|
|
48791
|
+
const iconData = getIconData(node.icon);
|
|
48792
|
+
const classes2 = ctx.buildClassString([
|
|
48793
|
+
`${ctx.prefix}-badge-icon`,
|
|
48794
|
+
node.size ? `${ctx.prefix}-badge-icon-${node.size}` : void 0,
|
|
48795
|
+
node.variant ? `${ctx.prefix}-badge-icon-${node.variant}` : void 0,
|
|
48796
|
+
...ctx.getCommonClasses(node)
|
|
48797
|
+
]);
|
|
48798
|
+
const styles2 = ctx.buildCommonStyles(node);
|
|
48799
|
+
const styleAttr2 = styles2 ? ` style="${styles2}"` : "";
|
|
48800
|
+
if (iconData) {
|
|
48801
|
+
const svg = renderIconSvg(iconData, 24, 2, `${ctx.prefix}-icon`);
|
|
48802
|
+
return `<span class="${classes2}"${styleAttr2} aria-label="${ctx.escapeHtml(node.icon)}">${svg}</span>`;
|
|
48803
|
+
}
|
|
48804
|
+
return `<span class="${classes2}"${styleAttr2} aria-label="unknown icon">?</span>`;
|
|
48805
|
+
}
|
|
48806
|
+
const isDot = !node.content || node.content.trim() === "";
|
|
48807
|
+
const classes = ctx.buildClassString([
|
|
48808
|
+
`${ctx.prefix}-badge`,
|
|
48809
|
+
isDot ? `${ctx.prefix}-badge-dot` : void 0,
|
|
48810
|
+
node.variant ? `${ctx.prefix}-badge-${node.variant}` : void 0,
|
|
48811
|
+
node.pill ? `${ctx.prefix}-badge-pill` : void 0,
|
|
48812
|
+
...ctx.getCommonClasses(node)
|
|
48813
|
+
]);
|
|
48814
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48815
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48816
|
+
return `<span class="${classes}"${styleAttr}>${ctx.escapeHtml(node.content)}</span>`;
|
|
48817
|
+
}
|
|
48818
|
+
function renderIcon(node, ctx) {
|
|
48819
|
+
const iconData = getIconData(node.name);
|
|
48820
|
+
const sizeResolved = resolveSizeValue(node.size, "icon", ctx.prefix);
|
|
48821
|
+
const wrapperClasses = ctx.buildClassString([
|
|
48822
|
+
`${ctx.prefix}-icon-wrapper`,
|
|
48823
|
+
node.muted ? `${ctx.prefix}-text-muted` : void 0,
|
|
48824
|
+
...ctx.getCommonClasses(node)
|
|
48825
|
+
]);
|
|
48826
|
+
const baseStyles = ctx.buildCommonStyles(node);
|
|
48827
|
+
if (iconData) {
|
|
48828
|
+
const iconClasses = buildClassString([
|
|
48829
|
+
`${ctx.prefix}-icon`,
|
|
48830
|
+
sizeResolved.className
|
|
48831
|
+
]);
|
|
48832
|
+
const svgStyleAttr = sizeResolved.style ? ` style="${sizeResolved.style}"` : "";
|
|
48833
|
+
const svg = renderIconSvg(iconData, 24, 2, iconClasses, svgStyleAttr);
|
|
48834
|
+
const wrapperStyleAttr2 = baseStyles ? ` style="${baseStyles}"` : "";
|
|
48835
|
+
return `<span class="${wrapperClasses}"${wrapperStyleAttr2} aria-hidden="true">${svg}</span>`;
|
|
48836
|
+
}
|
|
48837
|
+
const size = sizeResolved.style?.match(/(\d+)px/)?.[1] || "24";
|
|
48838
|
+
const sizeNum = parseInt(size, 10);
|
|
48839
|
+
const placeholderSvg = `<svg class="${ctx.prefix}-icon ${sizeResolved.className || ""}" width="${sizeNum}" height="${sizeNum}" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
48840
|
+
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" stroke-dasharray="4 2" fill="none" opacity="0.5"/>
|
|
48841
|
+
<text x="12" y="16" text-anchor="middle" font-size="10" fill="currentColor" opacity="0.7">?</text>
|
|
48842
|
+
</svg>`;
|
|
48843
|
+
const wrapperStyleAttr = baseStyles ? ` style="${baseStyles}"` : "";
|
|
48844
|
+
return `<span class="${wrapperClasses}"${wrapperStyleAttr} aria-hidden="true" title="Unknown icon: ${ctx.escapeHtml(node.name)}">${placeholderSvg}</span>`;
|
|
48845
|
+
}
|
|
48846
|
+
|
|
48847
|
+
// src/renderer/html/renderers/overlay.ts
|
|
48848
|
+
function renderTooltip(node, ctx) {
|
|
48849
|
+
const classes = ctx.buildClassString([
|
|
48850
|
+
`${ctx.prefix}-tooltip-wrapper`,
|
|
48851
|
+
...ctx.getCommonClasses(node)
|
|
48852
|
+
]);
|
|
48853
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48854
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48855
|
+
const position = node.position || "top";
|
|
48856
|
+
const children = ctx.renderChildren(node.children);
|
|
48857
|
+
return `<div class="${classes}"${styleAttr}>
|
|
48858
|
+
${children}
|
|
48859
|
+
<div class="${ctx.prefix}-tooltip ${ctx.prefix}-tooltip-${position}" role="tooltip">${ctx.escapeHtml(node.content)}</div>
|
|
48860
|
+
</div>`;
|
|
48861
|
+
}
|
|
48862
|
+
function renderPopover(node, ctx) {
|
|
48863
|
+
const classes = ctx.buildClassString([
|
|
48864
|
+
`${ctx.prefix}-popover`,
|
|
48865
|
+
...ctx.getCommonClasses(node)
|
|
48866
|
+
]);
|
|
48867
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48868
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48869
|
+
const title = node.title ? `<div class="${ctx.prefix}-popover-header">${ctx.escapeHtml(node.title)}</div>
|
|
48870
|
+
` : "";
|
|
48871
|
+
const children = ctx.renderChildren(node.children);
|
|
48872
|
+
return `<div class="${classes}"${styleAttr}>
|
|
48873
|
+
${title}<div class="${ctx.prefix}-popover-body">
|
|
48874
|
+
${children}
|
|
48875
|
+
</div>
|
|
48876
|
+
</div>`;
|
|
48877
|
+
}
|
|
48878
|
+
function renderDropdown(node, ctx) {
|
|
48879
|
+
const classes = ctx.buildClassString([
|
|
48880
|
+
`${ctx.prefix}-dropdown`,
|
|
48881
|
+
...ctx.getCommonClasses(node)
|
|
48882
|
+
]);
|
|
48883
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48884
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48885
|
+
const items = node.items.map((item) => {
|
|
48886
|
+
if ("type" in item && item.type === "divider") {
|
|
48887
|
+
return `<hr class="${ctx.prefix}-divider" />`;
|
|
48888
|
+
}
|
|
48889
|
+
const dropdownItem = item;
|
|
48890
|
+
const itemClasses = ctx.buildClassString([
|
|
48891
|
+
`${ctx.prefix}-dropdown-item`,
|
|
48892
|
+
dropdownItem.danger ? `${ctx.prefix}-dropdown-item-danger` : void 0,
|
|
48893
|
+
dropdownItem.disabled ? `${ctx.prefix}-dropdown-item-disabled` : void 0
|
|
48894
|
+
]);
|
|
48895
|
+
return `<button class="${itemClasses}"${dropdownItem.disabled ? " disabled" : ""}>${ctx.escapeHtml(dropdownItem.label)}</button>`;
|
|
48896
|
+
}).join("\n");
|
|
48897
|
+
return `<div class="${classes}"${styleAttr}>
|
|
48898
|
+
${items}
|
|
48899
|
+
</div>`;
|
|
48900
|
+
}
|
|
48901
|
+
|
|
48902
|
+
// src/renderer/html/renderers/navigation.ts
|
|
48903
|
+
function renderIconHtml(iconName, prefix) {
|
|
48904
|
+
return `<span class="${prefix}-icon" data-icon="${iconName}"></span>`;
|
|
48905
|
+
}
|
|
48906
|
+
function renderNavItem(item, ctx) {
|
|
48907
|
+
const linkClasses = ctx.buildClassString([
|
|
48908
|
+
`${ctx.prefix}-nav-link`,
|
|
48909
|
+
item.active ? `${ctx.prefix}-nav-link-active` : void 0,
|
|
48910
|
+
item.disabled ? `${ctx.prefix}-nav-link-disabled` : void 0
|
|
48911
|
+
]);
|
|
48912
|
+
const iconHtml = item.icon ? renderIconHtml(item.icon, ctx.prefix) + " " : "";
|
|
48913
|
+
return `<a class="${linkClasses}" href="${item.href || "#"}">${iconHtml}${ctx.escapeHtml(item.label)}</a>`;
|
|
48914
|
+
}
|
|
48915
|
+
function renderNavChildren(children, ctx) {
|
|
48916
|
+
return children.map((child) => {
|
|
48917
|
+
if (child.type === "divider") {
|
|
48918
|
+
return `<hr class="${ctx.prefix}-nav-divider" />`;
|
|
48919
|
+
}
|
|
48920
|
+
if (child.type === "group") {
|
|
48921
|
+
const groupItems = child.items.map((item) => {
|
|
48922
|
+
if (item.type === "divider") {
|
|
48923
|
+
return `<hr class="${ctx.prefix}-nav-divider" />`;
|
|
48924
|
+
}
|
|
48925
|
+
return renderNavItem(item, ctx);
|
|
48926
|
+
}).join("\n");
|
|
48927
|
+
return `<div class="${ctx.prefix}-nav-group">
|
|
48928
|
+
<div class="${ctx.prefix}-nav-group-label">${ctx.escapeHtml(child.label)}</div>
|
|
48929
|
+
${groupItems}
|
|
48930
|
+
</div>`;
|
|
48931
|
+
}
|
|
48932
|
+
if (child.type === "item") {
|
|
48933
|
+
return renderNavItem(child, ctx);
|
|
48934
|
+
}
|
|
48935
|
+
return "";
|
|
48936
|
+
}).join("\n");
|
|
48937
|
+
}
|
|
48938
|
+
function renderNav(node, ctx) {
|
|
48939
|
+
const classes = ctx.buildClassString([
|
|
48940
|
+
`${ctx.prefix}-nav`,
|
|
48941
|
+
node.vertical ? `${ctx.prefix}-nav-vertical` : void 0,
|
|
48942
|
+
...ctx.getCommonClasses(node)
|
|
48943
|
+
]);
|
|
48944
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48945
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48946
|
+
if (node.children && node.children.length > 0) {
|
|
48947
|
+
const content = renderNavChildren(node.children, ctx);
|
|
48948
|
+
return `<nav class="${classes}"${styleAttr}>
|
|
48949
|
+
${content}
|
|
48950
|
+
</nav>`;
|
|
48951
|
+
}
|
|
48952
|
+
const items = node.items.map((item) => {
|
|
48953
|
+
if (typeof item === "string") {
|
|
48954
|
+
return `<a class="${ctx.prefix}-nav-link" href="#">${ctx.escapeHtml(item)}</a>`;
|
|
48955
|
+
}
|
|
48956
|
+
const linkClasses = ctx.buildClassString([
|
|
48957
|
+
`${ctx.prefix}-nav-link`,
|
|
48958
|
+
item.active ? `${ctx.prefix}-nav-link-active` : void 0,
|
|
48959
|
+
item.disabled ? `${ctx.prefix}-nav-link-disabled` : void 0
|
|
48960
|
+
]);
|
|
48961
|
+
const iconHtml = item.icon ? renderIconHtml(item.icon, ctx.prefix) + " " : "";
|
|
48962
|
+
return `<a class="${linkClasses}" href="${item.href || "#"}">${iconHtml}${ctx.escapeHtml(item.label)}</a>`;
|
|
48963
|
+
}).join("\n");
|
|
48964
|
+
return `<nav class="${classes}"${styleAttr}>
|
|
48965
|
+
${items}
|
|
48966
|
+
</nav>`;
|
|
48967
|
+
}
|
|
48968
|
+
function renderTabs(node, ctx) {
|
|
48969
|
+
const classes = ctx.buildClassString([
|
|
48970
|
+
`${ctx.prefix}-tabs`,
|
|
48971
|
+
...ctx.getCommonClasses(node)
|
|
48972
|
+
]);
|
|
48973
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48974
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48975
|
+
const tabList = node.items.map((label, idx) => {
|
|
48976
|
+
const isActive = idx === (node.active || 0);
|
|
48977
|
+
const tabClasses = `${ctx.prefix}-tab${isActive ? ` ${ctx.prefix}-tab-active` : ""}`;
|
|
48978
|
+
return `<button class="${tabClasses}" role="tab" aria-selected="${isActive}">${ctx.escapeHtml(label)}</button>`;
|
|
48979
|
+
}).join("\n");
|
|
48980
|
+
return `<div class="${classes}"${styleAttr}>
|
|
48981
|
+
<div class="${ctx.prefix}-tab-list" role="tablist">
|
|
48982
|
+
${tabList}
|
|
48983
|
+
</div>
|
|
48984
|
+
</div>`;
|
|
48985
|
+
}
|
|
48986
|
+
function renderBreadcrumb(node, ctx) {
|
|
48987
|
+
const classes = ctx.buildClassString([
|
|
48988
|
+
`${ctx.prefix}-breadcrumb`,
|
|
48989
|
+
...ctx.getCommonClasses(node)
|
|
48990
|
+
]);
|
|
48991
|
+
const styles = ctx.buildCommonStyles(node);
|
|
48992
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48993
|
+
const items = node.items.map((item, idx) => {
|
|
48994
|
+
const isLast = idx === node.items.length - 1;
|
|
48995
|
+
if (typeof item === "string") {
|
|
48996
|
+
return isLast ? `<span class="${ctx.prefix}-breadcrumb-item" aria-current="page">${ctx.escapeHtml(item)}</span>` : `<a class="${ctx.prefix}-breadcrumb-item" href="#">${ctx.escapeHtml(item)}</a>`;
|
|
48997
|
+
}
|
|
48998
|
+
return isLast ? `<span class="${ctx.prefix}-breadcrumb-item" aria-current="page">${ctx.escapeHtml(item.label)}</span>` : `<a class="${ctx.prefix}-breadcrumb-item" href="${item.href || "#"}">${ctx.escapeHtml(item.label)}</a>`;
|
|
48999
|
+
}).join(" / ");
|
|
49000
|
+
return `<nav class="${classes}"${styleAttr} aria-label="Breadcrumb">${items}</nav>`;
|
|
49001
|
+
}
|
|
49002
|
+
|
|
49003
|
+
// src/renderer/html/semantic.ts
|
|
49004
|
+
function renderSemanticMarker(component, variant, prefix) {
|
|
49005
|
+
switch (component) {
|
|
49006
|
+
case "avatar":
|
|
49007
|
+
const avatarSize = variant || "sm";
|
|
49008
|
+
return `<span class="${prefix}-semantic-avatar ${prefix}-semantic-avatar-${avatarSize}" data-semantic="avatar" data-variant="${avatarSize}" aria-hidden="true"></span>`;
|
|
49009
|
+
case "dot":
|
|
49010
|
+
const dotVariant = variant || "default";
|
|
49011
|
+
return `<span class="${prefix}-semantic-dot ${prefix}-semantic-dot-${dotVariant}" data-semantic="dot" data-variant="${dotVariant}" aria-hidden="true"></span>`;
|
|
49012
|
+
case "icon":
|
|
49013
|
+
const iconName = variant || "default";
|
|
49014
|
+
return `<span class="${prefix}-semantic-icon" data-semantic="icon" data-variant="${iconName}" aria-hidden="true">[${iconName}]</span>`;
|
|
49015
|
+
default:
|
|
49016
|
+
return `<span class="${prefix}-semantic-unknown" data-semantic="${component}" data-variant="${variant || ""}">[${component}${variant ? ":" + variant : ""}]</span>`;
|
|
49017
|
+
}
|
|
49018
|
+
}
|
|
49019
|
+
function renderSemanticMarkerWithContent(component, variant, content, prefix, escapeHtml) {
|
|
49020
|
+
switch (component) {
|
|
49021
|
+
case "badge":
|
|
49022
|
+
const badgeVariant = variant || "default";
|
|
49023
|
+
const escapedContent = escapeHtml(content);
|
|
49024
|
+
return `<span class="${prefix}-semantic-badge ${prefix}-semantic-badge-${badgeVariant}" data-semantic="badge" data-variant="${badgeVariant}">${escapedContent}</span>`;
|
|
49025
|
+
default:
|
|
49026
|
+
return renderSemanticMarker(component, variant, prefix) + escapeHtml(content);
|
|
49027
|
+
}
|
|
49028
|
+
}
|
|
49029
|
+
function renderSemanticMarkers(text, prefix, escapeHtml) {
|
|
49030
|
+
const markerPattern = /\[([a-z]+)(?::([a-z0-9-]+))?\](\s*)/gi;
|
|
49031
|
+
let result = "";
|
|
49032
|
+
let lastIndex = 0;
|
|
49033
|
+
let match;
|
|
49034
|
+
while ((match = markerPattern.exec(text)) !== null) {
|
|
49035
|
+
if (match.index > lastIndex) {
|
|
49036
|
+
result += escapeHtml(text.substring(lastIndex, match.index));
|
|
49037
|
+
}
|
|
49038
|
+
const [fullMatch, component, variant] = match;
|
|
49039
|
+
const comp = component.toLowerCase();
|
|
49040
|
+
const varnt = variant?.toLowerCase();
|
|
49041
|
+
if (comp === "badge") {
|
|
49042
|
+
const afterMarker = text.substring(match.index + fullMatch.length);
|
|
49043
|
+
const contentMatch = afterMarker.match(/^([^\n\[]+?)(?=\n|\[|$)/);
|
|
49044
|
+
const badgeContent = contentMatch ? contentMatch[1].trim() : "";
|
|
49045
|
+
result += renderSemanticMarkerWithContent(comp, varnt, badgeContent, prefix, escapeHtml);
|
|
49046
|
+
lastIndex = match.index + fullMatch.length + (contentMatch ? contentMatch[0].length : 0);
|
|
49047
|
+
markerPattern.lastIndex = lastIndex;
|
|
49048
|
+
} else {
|
|
49049
|
+
result += renderSemanticMarker(comp, varnt, prefix);
|
|
49050
|
+
lastIndex = match.index + fullMatch.length;
|
|
49051
|
+
}
|
|
49052
|
+
}
|
|
49053
|
+
if (lastIndex < text.length) {
|
|
49054
|
+
result += escapeHtml(text.substring(lastIndex));
|
|
49055
|
+
}
|
|
49056
|
+
if (lastIndex === 0) {
|
|
49057
|
+
return escapeHtml(text);
|
|
49058
|
+
}
|
|
49059
|
+
return result;
|
|
49060
|
+
}
|
|
49061
|
+
function renderTableCellContent(content, prefix, escapeHtml) {
|
|
49062
|
+
const avatarMatch = content.match(/^\[avatar(?::([a-z0-9-]+))?\]\s*/i);
|
|
49063
|
+
if (avatarMatch) {
|
|
49064
|
+
const avatarVariant = avatarMatch[1]?.toLowerCase();
|
|
49065
|
+
const avatarHtml = renderSemanticMarker("avatar", avatarVariant, prefix);
|
|
49066
|
+
const restContent = content.slice(avatarMatch[0].length);
|
|
49067
|
+
const restHtml = renderSemanticMarkers(restContent, prefix, escapeHtml);
|
|
49068
|
+
const lines = restHtml.split("\n");
|
|
49069
|
+
const textHtml = lines.length > 1 ? lines.map((line) => `<span>${line}</span>`).join("") : restHtml;
|
|
49070
|
+
return `<div class="${prefix}-cell-avatar-layout">${avatarHtml}<div class="${prefix}-cell-avatar-text">${textHtml}</div></div>`;
|
|
49071
|
+
}
|
|
49072
|
+
const withMarkers = renderSemanticMarkers(content, prefix, escapeHtml);
|
|
49073
|
+
return withMarkers.replace(/\n/g, "<br>");
|
|
49074
|
+
}
|
|
49075
|
+
|
|
49076
|
+
// src/renderer/html/renderers/data.ts
|
|
49077
|
+
function renderTable(node, ctx) {
|
|
49078
|
+
const classes = ctx.buildClassString([
|
|
49079
|
+
`${ctx.prefix}-table`,
|
|
49080
|
+
node.striped ? `${ctx.prefix}-table-striped` : void 0,
|
|
49081
|
+
node.bordered ? `${ctx.prefix}-table-bordered` : void 0,
|
|
49082
|
+
node.hover ? `${ctx.prefix}-table-hover` : void 0,
|
|
49083
|
+
...ctx.getCommonClasses(node)
|
|
49084
|
+
]);
|
|
49085
|
+
const styles = ctx.buildCommonStyles(node);
|
|
49086
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49087
|
+
const thead = `<thead><tr>${node.columns.map((col) => `<th>${ctx.escapeHtml(col)}</th>`).join("")}</tr></thead>`;
|
|
49088
|
+
const tbody = `<tbody>${node.rows.map(
|
|
49089
|
+
(row) => `<tr>${row.map((cell) => {
|
|
49090
|
+
if (typeof cell === "string") {
|
|
49091
|
+
return `<td>${renderTableCellContent(cell, ctx.prefix, ctx.escapeHtml)}</td>`;
|
|
49092
|
+
}
|
|
49093
|
+
return `<td>${ctx.renderNode(cell)}</td>`;
|
|
49094
|
+
}).join("")}</tr>`
|
|
49095
|
+
).join("")}</tbody>`;
|
|
49096
|
+
return `<table class="${classes}"${styleAttr}>
|
|
49097
|
+
${thead}
|
|
49098
|
+
${tbody}
|
|
49099
|
+
</table>`;
|
|
49100
|
+
}
|
|
49101
|
+
function renderList(node, ctx) {
|
|
49102
|
+
const tag = node.ordered ? "ol" : "ul";
|
|
49103
|
+
const classes = ctx.buildClassString([
|
|
49104
|
+
`${ctx.prefix}-list`,
|
|
49105
|
+
node.ordered ? `${ctx.prefix}-list-ordered` : void 0,
|
|
49106
|
+
node.none ? `${ctx.prefix}-list-none` : void 0,
|
|
49107
|
+
...ctx.getCommonClasses(node)
|
|
49108
|
+
]);
|
|
49109
|
+
const styles = ctx.buildCommonStyles(node);
|
|
49110
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49111
|
+
const items = node.items.map((item) => {
|
|
49112
|
+
if (typeof item === "string") {
|
|
49113
|
+
return `<li class="${ctx.prefix}-list-item">${ctx.escapeHtml(item)}</li>`;
|
|
49114
|
+
}
|
|
49115
|
+
return `<li class="${ctx.prefix}-list-item">${ctx.escapeHtml(item.content)}</li>`;
|
|
49116
|
+
}).join("\n");
|
|
49117
|
+
return `<${tag} class="${classes}"${styleAttr}>
|
|
49118
|
+
${items}
|
|
49119
|
+
</${tag}>`;
|
|
49120
|
+
}
|
|
49121
|
+
|
|
49122
|
+
// src/renderer/html/renderers/divider.ts
|
|
49123
|
+
function renderDivider(node, ctx) {
|
|
49124
|
+
const styles = ctx.buildCommonStyles(node);
|
|
49125
|
+
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49126
|
+
return `<hr class="${ctx.prefix}-divider"${styleAttr} />`;
|
|
48233
49127
|
}
|
|
48234
49128
|
|
|
48235
49129
|
// src/renderer/html/index.ts
|
|
@@ -48271,8 +49165,97 @@ function resolveSizeValueToCss(value) {
|
|
|
48271
49165
|
return void 0;
|
|
48272
49166
|
}
|
|
48273
49167
|
var HtmlRenderer = class extends BaseRenderer {
|
|
49168
|
+
/**
|
|
49169
|
+
* Node type to renderer method mapping
|
|
49170
|
+
*/
|
|
49171
|
+
nodeRenderers;
|
|
48274
49172
|
constructor(options = {}) {
|
|
48275
49173
|
super(options);
|
|
49174
|
+
this.nodeRenderers = this.createNodeRenderers();
|
|
49175
|
+
}
|
|
49176
|
+
/**
|
|
49177
|
+
* Get render context for external renderer functions
|
|
49178
|
+
*/
|
|
49179
|
+
getRenderContext() {
|
|
49180
|
+
return {
|
|
49181
|
+
prefix: this.prefix,
|
|
49182
|
+
escapeHtml: this.escapeHtml.bind(this),
|
|
49183
|
+
buildClassString: this.buildClassString.bind(this),
|
|
49184
|
+
buildAttrsString: this.buildAttrsString.bind(this),
|
|
49185
|
+
buildCommonStyles: this.buildCommonStyles.bind(this),
|
|
49186
|
+
getCommonClasses: this.getCommonClasses.bind(this),
|
|
49187
|
+
renderChildren: this.renderChildren.bind(this),
|
|
49188
|
+
renderNode: this.renderNode.bind(this)
|
|
49189
|
+
};
|
|
49190
|
+
}
|
|
49191
|
+
/**
|
|
49192
|
+
* Get grid render context (extends RenderContext with buildColStyles)
|
|
49193
|
+
*/
|
|
49194
|
+
getGridRenderContext() {
|
|
49195
|
+
return {
|
|
49196
|
+
...this.getRenderContext(),
|
|
49197
|
+
buildColStyles: this.buildColStyles.bind(this)
|
|
49198
|
+
};
|
|
49199
|
+
}
|
|
49200
|
+
/**
|
|
49201
|
+
* Create the node renderer mapping
|
|
49202
|
+
*/
|
|
49203
|
+
createNodeRenderers() {
|
|
49204
|
+
return {
|
|
49205
|
+
// Layout nodes
|
|
49206
|
+
Page: (node) => this.renderPage(node),
|
|
49207
|
+
Header: (node) => this.renderHeader(node),
|
|
49208
|
+
Main: (node) => this.renderMain(node),
|
|
49209
|
+
Footer: (node) => this.renderFooter(node),
|
|
49210
|
+
Sidebar: (node) => this.renderSidebar(node),
|
|
49211
|
+
Section: (node) => this.renderSection(node),
|
|
49212
|
+
// Grid nodes
|
|
49213
|
+
Row: (node) => this.renderRow(node),
|
|
49214
|
+
Col: (node) => this.renderCol(node),
|
|
49215
|
+
// Container nodes
|
|
49216
|
+
Card: (node) => this.renderCard(node),
|
|
49217
|
+
Modal: (node) => this.renderModal(node),
|
|
49218
|
+
Drawer: (node) => this.renderDrawer(node),
|
|
49219
|
+
Accordion: (node) => this.renderAccordion(node),
|
|
49220
|
+
// Text nodes
|
|
49221
|
+
Text: (node) => this.renderText(node),
|
|
49222
|
+
Title: (node) => this.renderTitle(node),
|
|
49223
|
+
Link: (node) => this.renderLink(node),
|
|
49224
|
+
// Input nodes
|
|
49225
|
+
Input: (node) => this.renderInput(node),
|
|
49226
|
+
Textarea: (node) => this.renderTextarea(node),
|
|
49227
|
+
Select: (node) => this.renderSelect(node),
|
|
49228
|
+
Checkbox: (node) => this.renderCheckbox(node),
|
|
49229
|
+
Radio: (node) => this.renderRadio(node),
|
|
49230
|
+
Switch: (node) => this.renderSwitch(node),
|
|
49231
|
+
Slider: (node) => this.renderSlider(node),
|
|
49232
|
+
// Button
|
|
49233
|
+
Button: (node) => this.renderButton(node),
|
|
49234
|
+
// Display nodes
|
|
49235
|
+
Image: (node) => this.renderImage(node),
|
|
49236
|
+
Placeholder: (node) => this.renderPlaceholder(node),
|
|
49237
|
+
Avatar: (node) => this.renderAvatar(node),
|
|
49238
|
+
Badge: (node) => this.renderBadge(node),
|
|
49239
|
+
Icon: (node) => this.renderIcon(node),
|
|
49240
|
+
// Data nodes
|
|
49241
|
+
Table: (node) => this.renderTable(node),
|
|
49242
|
+
List: (node) => this.renderList(node),
|
|
49243
|
+
// Feedback nodes
|
|
49244
|
+
Alert: (node) => this.renderAlert(node),
|
|
49245
|
+
Toast: (node) => this.renderToast(node),
|
|
49246
|
+
Progress: (node) => this.renderProgress(node),
|
|
49247
|
+
Spinner: (node) => this.renderSpinner(node),
|
|
49248
|
+
// Overlay nodes
|
|
49249
|
+
Tooltip: (node) => this.renderTooltip(node),
|
|
49250
|
+
Popover: (node) => this.renderPopover(node),
|
|
49251
|
+
Dropdown: (node) => this.renderDropdown(node),
|
|
49252
|
+
// Navigation nodes
|
|
49253
|
+
Nav: (node) => this.renderNav(node),
|
|
49254
|
+
Tabs: (node) => this.renderTabs(node),
|
|
49255
|
+
Breadcrumb: (node) => this.renderBreadcrumb(node),
|
|
49256
|
+
// Other
|
|
49257
|
+
Divider: (node) => this.renderDivider(node)
|
|
49258
|
+
};
|
|
48276
49259
|
}
|
|
48277
49260
|
/**
|
|
48278
49261
|
* Render a page node
|
|
@@ -48312,104 +49295,11 @@ ${title}${children}
|
|
|
48312
49295
|
* Render any AST node
|
|
48313
49296
|
*/
|
|
48314
49297
|
renderNode(node) {
|
|
48315
|
-
|
|
48316
|
-
|
|
48317
|
-
|
|
48318
|
-
return this.renderPage(node);
|
|
48319
|
-
case "Header":
|
|
48320
|
-
return this.renderHeader(node);
|
|
48321
|
-
case "Main":
|
|
48322
|
-
return this.renderMain(node);
|
|
48323
|
-
case "Footer":
|
|
48324
|
-
return this.renderFooter(node);
|
|
48325
|
-
case "Sidebar":
|
|
48326
|
-
return this.renderSidebar(node);
|
|
48327
|
-
case "Section":
|
|
48328
|
-
return this.renderSection(node);
|
|
48329
|
-
// Grid nodes
|
|
48330
|
-
case "Row":
|
|
48331
|
-
return this.renderRow(node);
|
|
48332
|
-
case "Col":
|
|
48333
|
-
return this.renderCol(node);
|
|
48334
|
-
// Container nodes
|
|
48335
|
-
case "Card":
|
|
48336
|
-
return this.renderCard(node);
|
|
48337
|
-
case "Modal":
|
|
48338
|
-
return this.renderModal(node);
|
|
48339
|
-
case "Drawer":
|
|
48340
|
-
return this.renderDrawer(node);
|
|
48341
|
-
case "Accordion":
|
|
48342
|
-
return this.renderAccordion(node);
|
|
48343
|
-
// Text nodes
|
|
48344
|
-
case "Text":
|
|
48345
|
-
return this.renderText(node);
|
|
48346
|
-
case "Title":
|
|
48347
|
-
return this.renderTitle(node);
|
|
48348
|
-
case "Link":
|
|
48349
|
-
return this.renderLink(node);
|
|
48350
|
-
// Input nodes
|
|
48351
|
-
case "Input":
|
|
48352
|
-
return this.renderInput(node);
|
|
48353
|
-
case "Textarea":
|
|
48354
|
-
return this.renderTextarea(node);
|
|
48355
|
-
case "Select":
|
|
48356
|
-
return this.renderSelect(node);
|
|
48357
|
-
case "Checkbox":
|
|
48358
|
-
return this.renderCheckbox(node);
|
|
48359
|
-
case "Radio":
|
|
48360
|
-
return this.renderRadio(node);
|
|
48361
|
-
case "Switch":
|
|
48362
|
-
return this.renderSwitch(node);
|
|
48363
|
-
case "Slider":
|
|
48364
|
-
return this.renderSlider(node);
|
|
48365
|
-
// Button
|
|
48366
|
-
case "Button":
|
|
48367
|
-
return this.renderButton(node);
|
|
48368
|
-
// Display nodes
|
|
48369
|
-
case "Image":
|
|
48370
|
-
return this.renderImage(node);
|
|
48371
|
-
case "Placeholder":
|
|
48372
|
-
return this.renderPlaceholder(node);
|
|
48373
|
-
case "Avatar":
|
|
48374
|
-
return this.renderAvatar(node);
|
|
48375
|
-
case "Badge":
|
|
48376
|
-
return this.renderBadge(node);
|
|
48377
|
-
case "Icon":
|
|
48378
|
-
return this.renderIcon(node);
|
|
48379
|
-
// Data nodes
|
|
48380
|
-
case "Table":
|
|
48381
|
-
return this.renderTable(node);
|
|
48382
|
-
case "List":
|
|
48383
|
-
return this.renderList(node);
|
|
48384
|
-
// Feedback nodes
|
|
48385
|
-
case "Alert":
|
|
48386
|
-
return this.renderAlert(node);
|
|
48387
|
-
case "Toast":
|
|
48388
|
-
return this.renderToast(node);
|
|
48389
|
-
case "Progress":
|
|
48390
|
-
return this.renderProgress(node);
|
|
48391
|
-
case "Spinner":
|
|
48392
|
-
return this.renderSpinner(node);
|
|
48393
|
-
// Overlay nodes
|
|
48394
|
-
case "Tooltip":
|
|
48395
|
-
return this.renderTooltip(node);
|
|
48396
|
-
case "Popover":
|
|
48397
|
-
return this.renderPopover(node);
|
|
48398
|
-
case "Dropdown":
|
|
48399
|
-
return this.renderDropdown(node);
|
|
48400
|
-
// Navigation nodes
|
|
48401
|
-
case "Nav":
|
|
48402
|
-
return this.renderNav(node);
|
|
48403
|
-
case "Tabs":
|
|
48404
|
-
return this.renderTabs(node);
|
|
48405
|
-
case "Breadcrumb":
|
|
48406
|
-
return this.renderBreadcrumb(node);
|
|
48407
|
-
// Other
|
|
48408
|
-
case "Divider":
|
|
48409
|
-
return this.renderDivider(node);
|
|
48410
|
-
default:
|
|
48411
|
-
return `<!-- Unknown node type: ${node.type} -->`;
|
|
49298
|
+
const renderer = this.nodeRenderers[node.type];
|
|
49299
|
+
if (renderer) {
|
|
49300
|
+
return renderer(node);
|
|
48412
49301
|
}
|
|
49302
|
+
return `<!-- Unknown node type: ${node.type} -->`;
|
|
48413
49303
|
}
|
|
48414
49304
|
/**
|
|
48415
49305
|
* Render children nodes
|
|
@@ -48452,103 +49342,28 @@ ${title}${children}
|
|
|
48452
49342
|
// Layout Node Renderers
|
|
48453
49343
|
// ===========================================
|
|
48454
49344
|
renderHeader(node) {
|
|
48455
|
-
|
|
48456
|
-
`${this.prefix}-header`,
|
|
48457
|
-
node.border === false ? `${this.prefix}-no-border` : void 0,
|
|
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 `<header class="${classes}"${styleAttr}>
|
|
48464
|
-
${children}
|
|
48465
|
-
</header>`;
|
|
49345
|
+
return renderHeader(node, this.getRenderContext());
|
|
48466
49346
|
}
|
|
48467
49347
|
renderMain(node) {
|
|
48468
|
-
|
|
48469
|
-
`${this.prefix}-main`,
|
|
48470
|
-
node.scroll ? `${this.prefix}-scroll` : void 0,
|
|
48471
|
-
...this.getCommonClasses(node)
|
|
48472
|
-
]);
|
|
48473
|
-
const styles = this.buildCommonStyles(node);
|
|
48474
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48475
|
-
const children = this.renderChildren(node.children);
|
|
48476
|
-
return `<main class="${classes}"${styleAttr}>
|
|
48477
|
-
${children}
|
|
48478
|
-
</main>`;
|
|
49348
|
+
return renderMain(node, this.getRenderContext());
|
|
48479
49349
|
}
|
|
48480
49350
|
renderFooter(node) {
|
|
48481
|
-
|
|
48482
|
-
`${this.prefix}-footer`,
|
|
48483
|
-
node.border === false ? `${this.prefix}-no-border` : void 0,
|
|
48484
|
-
...this.getCommonClasses(node)
|
|
48485
|
-
]);
|
|
48486
|
-
const styles = this.buildCommonStyles(node);
|
|
48487
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48488
|
-
const children = this.renderChildren(node.children);
|
|
48489
|
-
return `<footer class="${classes}"${styleAttr}>
|
|
48490
|
-
${children}
|
|
48491
|
-
</footer>`;
|
|
49351
|
+
return renderFooter(node, this.getRenderContext());
|
|
48492
49352
|
}
|
|
48493
49353
|
renderSidebar(node) {
|
|
48494
|
-
|
|
48495
|
-
`${this.prefix}-sidebar`,
|
|
48496
|
-
node.position === "right" ? `${this.prefix}-sidebar-right` : void 0,
|
|
48497
|
-
...this.getCommonClasses(node)
|
|
48498
|
-
]);
|
|
48499
|
-
const styles = this.buildCommonStyles(node);
|
|
48500
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48501
|
-
const children = this.renderChildren(node.children);
|
|
48502
|
-
return `<aside class="${classes}"${styleAttr}>
|
|
48503
|
-
${children}
|
|
48504
|
-
</aside>`;
|
|
49354
|
+
return renderSidebar(node, this.getRenderContext());
|
|
48505
49355
|
}
|
|
48506
49356
|
renderSection(node) {
|
|
48507
|
-
|
|
48508
|
-
`${this.prefix}-section`,
|
|
48509
|
-
...this.getCommonClasses(node)
|
|
48510
|
-
]);
|
|
48511
|
-
const styles = this.buildCommonStyles(node);
|
|
48512
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48513
|
-
const title = node.title ? `<h2 class="${this.prefix}-title">${this.escapeHtml(node.title)}</h2>
|
|
48514
|
-
` : "";
|
|
48515
|
-
const children = this.renderChildren(node.children);
|
|
48516
|
-
return `<section class="${classes}"${styleAttr}>
|
|
48517
|
-
${title}${children}
|
|
48518
|
-
</section>`;
|
|
49357
|
+
return renderSection(node, this.getRenderContext());
|
|
48519
49358
|
}
|
|
48520
49359
|
// ===========================================
|
|
48521
49360
|
// Grid Node Renderers
|
|
48522
49361
|
// ===========================================
|
|
48523
49362
|
renderRow(node) {
|
|
48524
|
-
|
|
48525
|
-
`${this.prefix}-row`,
|
|
48526
|
-
...this.getCommonClasses(node)
|
|
48527
|
-
]);
|
|
48528
|
-
const styles = this.buildCommonStyles(node);
|
|
48529
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48530
|
-
const children = this.renderChildren(node.children);
|
|
48531
|
-
return `<div class="${classes}"${styleAttr}>
|
|
48532
|
-
${children}
|
|
48533
|
-
</div>`;
|
|
49363
|
+
return renderRow(node, this.getRenderContext());
|
|
48534
49364
|
}
|
|
48535
49365
|
renderCol(node) {
|
|
48536
|
-
|
|
48537
|
-
`${this.prefix}-col`,
|
|
48538
|
-
node.span ? `${this.prefix}-col-${node.span}` : void 0,
|
|
48539
|
-
// Responsive breakpoint classes
|
|
48540
|
-
node.sm ? `${this.prefix}-col-sm-${node.sm}` : void 0,
|
|
48541
|
-
node.md ? `${this.prefix}-col-md-${node.md}` : void 0,
|
|
48542
|
-
node.lg ? `${this.prefix}-col-lg-${node.lg}` : void 0,
|
|
48543
|
-
node.xl ? `${this.prefix}-col-xl-${node.xl}` : void 0,
|
|
48544
|
-
...this.getCommonClasses(node)
|
|
48545
|
-
]);
|
|
48546
|
-
const styles = this.buildColStyles(node);
|
|
48547
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48548
|
-
const children = this.renderChildren(node.children);
|
|
48549
|
-
return `<div class="${classes}"${styleAttr}>
|
|
48550
|
-
${children}
|
|
48551
|
-
</div>`;
|
|
49366
|
+
return renderCol(node, this.getGridRenderContext());
|
|
48552
49367
|
}
|
|
48553
49368
|
/**
|
|
48554
49369
|
* Build common inline styles for all values
|
|
@@ -48571,6 +49386,17 @@ ${children}
|
|
|
48571
49386
|
*/
|
|
48572
49387
|
buildCommonStyles(props) {
|
|
48573
49388
|
const styles = [];
|
|
49389
|
+
this.buildPositionStyles(props, styles);
|
|
49390
|
+
this.buildSizeStyles(props, styles);
|
|
49391
|
+
this.buildPaddingStyles(props, styles);
|
|
49392
|
+
this.buildMarginStyles(props, styles);
|
|
49393
|
+
this.buildGapStyles(props, styles);
|
|
49394
|
+
return styles.join("; ");
|
|
49395
|
+
}
|
|
49396
|
+
/**
|
|
49397
|
+
* Build position styles (absolute positioning)
|
|
49398
|
+
*/
|
|
49399
|
+
buildPositionStyles(props, styles) {
|
|
48574
49400
|
if (props.x !== void 0 || props.y !== void 0) {
|
|
48575
49401
|
styles.push("position: absolute");
|
|
48576
49402
|
if (props.x !== void 0) {
|
|
@@ -48582,6 +49408,11 @@ ${children}
|
|
|
48582
49408
|
if (yValue) styles.push(`top: ${yValue}`);
|
|
48583
49409
|
}
|
|
48584
49410
|
}
|
|
49411
|
+
}
|
|
49412
|
+
/**
|
|
49413
|
+
* Build size styles (width, height, min/max)
|
|
49414
|
+
*/
|
|
49415
|
+
buildSizeStyles(props, styles) {
|
|
48585
49416
|
const wValue = resolveSizeValueToCss(props.w);
|
|
48586
49417
|
if (wValue) {
|
|
48587
49418
|
styles.push(`width: ${wValue}`);
|
|
@@ -48607,6 +49438,11 @@ ${children}
|
|
|
48607
49438
|
if (maxHValue) {
|
|
48608
49439
|
styles.push(`max-height: ${maxHValue}`);
|
|
48609
49440
|
}
|
|
49441
|
+
}
|
|
49442
|
+
/**
|
|
49443
|
+
* Build padding styles (p, px, py, pt, pr, pb, pl)
|
|
49444
|
+
*/
|
|
49445
|
+
buildPaddingStyles(props, styles) {
|
|
48610
49446
|
const pValue = resolveSpacingValue(props.p);
|
|
48611
49447
|
if (pValue) {
|
|
48612
49448
|
styles.push(`padding: ${pValue}`);
|
|
@@ -48637,6 +49473,11 @@ ${children}
|
|
|
48637
49473
|
if (plValue) {
|
|
48638
49474
|
styles.push(`padding-left: ${plValue}`);
|
|
48639
49475
|
}
|
|
49476
|
+
}
|
|
49477
|
+
/**
|
|
49478
|
+
* Build margin styles (m, mx, my, mt, mr, mb, ml)
|
|
49479
|
+
*/
|
|
49480
|
+
buildMarginStyles(props, styles) {
|
|
48640
49481
|
const mValue = resolveSpacingValue(props.m);
|
|
48641
49482
|
if (mValue) {
|
|
48642
49483
|
styles.push(`margin: ${mValue}`);
|
|
@@ -48667,11 +49508,15 @@ ${children}
|
|
|
48667
49508
|
if (mlValue) {
|
|
48668
49509
|
styles.push(`margin-left: ${mlValue}`);
|
|
48669
49510
|
}
|
|
49511
|
+
}
|
|
49512
|
+
/**
|
|
49513
|
+
* Build gap styles
|
|
49514
|
+
*/
|
|
49515
|
+
buildGapStyles(props, styles) {
|
|
48670
49516
|
const gapValue = resolveSpacingValue(props.gap);
|
|
48671
49517
|
if (gapValue) {
|
|
48672
49518
|
styles.push(`gap: ${gapValue}`);
|
|
48673
49519
|
}
|
|
48674
|
-
return styles.join("; ");
|
|
48675
49520
|
}
|
|
48676
49521
|
/**
|
|
48677
49522
|
* Build inline styles for Col node (extends common styles with order)
|
|
@@ -48691,2632 +49536,136 @@ ${children}
|
|
|
48691
49536
|
// Container Node Renderers
|
|
48692
49537
|
// ===========================================
|
|
48693
49538
|
renderCard(node) {
|
|
48694
|
-
|
|
48695
|
-
const classes = this.buildClassString([
|
|
48696
|
-
`${this.prefix}-card`,
|
|
48697
|
-
!hasExplicitWidth ? `${this.prefix}-card-flex` : void 0,
|
|
48698
|
-
node.shadow ? `${this.prefix}-card-shadow-${node.shadow}` : void 0,
|
|
48699
|
-
...this.getCommonClasses(node)
|
|
48700
|
-
]);
|
|
48701
|
-
const styles = this.buildCommonStyles(node);
|
|
48702
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48703
|
-
const title = node.title ? `<h3 class="${this.prefix}-title">${this.escapeHtml(node.title)}</h3>
|
|
48704
|
-
` : "";
|
|
48705
|
-
const children = this.renderChildren(node.children);
|
|
48706
|
-
return `<div class="${classes}"${styleAttr}>
|
|
48707
|
-
${title}${children}
|
|
48708
|
-
</div>`;
|
|
49539
|
+
return renderCard(node, this.getRenderContext());
|
|
48709
49540
|
}
|
|
48710
49541
|
renderModal(node) {
|
|
48711
|
-
|
|
48712
|
-
`${this.prefix}-modal`,
|
|
48713
|
-
...this.getCommonClasses(node)
|
|
48714
|
-
]);
|
|
48715
|
-
const styles = this.buildCommonStyles(node);
|
|
48716
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48717
|
-
const title = node.title ? `<h2 class="${this.prefix}-title">${this.escapeHtml(node.title)}</h2>
|
|
48718
|
-
` : "";
|
|
48719
|
-
const children = this.renderChildren(node.children);
|
|
48720
|
-
return `<div class="${this.prefix}-modal-backdrop">
|
|
48721
|
-
<div class="${classes}"${styleAttr} role="dialog" aria-modal="true">
|
|
48722
|
-
${title}${children}
|
|
48723
|
-
</div>
|
|
48724
|
-
</div>`;
|
|
49542
|
+
return renderModal(node, this.getRenderContext());
|
|
48725
49543
|
}
|
|
48726
49544
|
renderDrawer(node) {
|
|
48727
|
-
|
|
48728
|
-
const classes = this.buildClassString([
|
|
48729
|
-
`${this.prefix}-drawer`,
|
|
48730
|
-
`${this.prefix}-drawer-${position}`,
|
|
48731
|
-
...this.getCommonClasses(node)
|
|
48732
|
-
]);
|
|
48733
|
-
const styles = this.buildCommonStyles(node);
|
|
48734
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48735
|
-
const title = node.title ? `<h2 class="${this.prefix}-title">${this.escapeHtml(node.title)}</h2>
|
|
48736
|
-
` : "";
|
|
48737
|
-
const children = this.renderChildren(node.children);
|
|
48738
|
-
return `<aside class="${classes}"${styleAttr}>
|
|
48739
|
-
${title}${children}
|
|
48740
|
-
</aside>`;
|
|
49545
|
+
return renderDrawer(node, this.getRenderContext());
|
|
48741
49546
|
}
|
|
48742
49547
|
renderAccordion(node) {
|
|
48743
|
-
|
|
48744
|
-
`${this.prefix}-accordion`,
|
|
48745
|
-
...this.getCommonClasses(node)
|
|
48746
|
-
]);
|
|
48747
|
-
const styles = this.buildCommonStyles(node);
|
|
48748
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48749
|
-
const title = node.title ? `<button class="${this.prefix}-accordion-header">${this.escapeHtml(node.title)}</button>
|
|
48750
|
-
` : "";
|
|
48751
|
-
const children = this.renderChildren(node.children);
|
|
48752
|
-
return `<div class="${classes}"${styleAttr}>
|
|
48753
|
-
${title}<div class="${this.prefix}-accordion-content">
|
|
48754
|
-
${children}
|
|
48755
|
-
</div>
|
|
48756
|
-
</div>`;
|
|
49548
|
+
return renderAccordion(node, this.getRenderContext());
|
|
48757
49549
|
}
|
|
48758
49550
|
// ===========================================
|
|
48759
49551
|
// Text Node Renderers
|
|
48760
49552
|
// ===========================================
|
|
48761
49553
|
renderText(node) {
|
|
48762
|
-
|
|
48763
|
-
`${this.prefix}-text`,
|
|
48764
|
-
node.size ? `${this.prefix}-text-${node.size}` : void 0,
|
|
48765
|
-
node.weight ? `${this.prefix}-text-${node.weight}` : void 0,
|
|
48766
|
-
node.align ? `${this.prefix}-text-${node.align}` : void 0,
|
|
48767
|
-
node.muted ? `${this.prefix}-text-muted` : void 0,
|
|
48768
|
-
...this.getCommonClasses(node)
|
|
48769
|
-
]);
|
|
48770
|
-
const styles = this.buildCommonStyles(node);
|
|
48771
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48772
|
-
return `<p class="${classes}"${styleAttr}>${this.escapeHtml(node.content)}</p>`;
|
|
49554
|
+
return renderText(node, this.getRenderContext());
|
|
48773
49555
|
}
|
|
48774
49556
|
renderTitle(node) {
|
|
48775
|
-
|
|
48776
|
-
const tag = `h${level}`;
|
|
48777
|
-
const classes = this.buildClassString([
|
|
48778
|
-
`${this.prefix}-title`,
|
|
48779
|
-
node.size ? `${this.prefix}-text-${node.size}` : void 0,
|
|
48780
|
-
node.align ? `${this.prefix}-text-${node.align}` : void 0,
|
|
48781
|
-
...this.getCommonClasses(node)
|
|
48782
|
-
]);
|
|
48783
|
-
const styles = this.buildCommonStyles(node);
|
|
48784
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48785
|
-
return `<${tag} class="${classes}"${styleAttr}>${this.escapeHtml(node.content)}</${tag}>`;
|
|
49557
|
+
return renderTitle(node, this.getRenderContext());
|
|
48786
49558
|
}
|
|
48787
49559
|
renderLink(node) {
|
|
48788
|
-
|
|
48789
|
-
`${this.prefix}-link`,
|
|
48790
|
-
...this.getCommonClasses(node)
|
|
48791
|
-
]);
|
|
48792
|
-
const styles = this.buildCommonStyles(node);
|
|
48793
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48794
|
-
const attrs = {
|
|
48795
|
-
class: classes,
|
|
48796
|
-
href: node.href || "#"
|
|
48797
|
-
};
|
|
48798
|
-
if (node.external) {
|
|
48799
|
-
attrs.target = "_blank";
|
|
48800
|
-
attrs.rel = "noopener noreferrer";
|
|
48801
|
-
}
|
|
48802
|
-
return `<a${this.buildAttrsString(attrs)}${styleAttr}>${this.escapeHtml(node.content)}</a>`;
|
|
49560
|
+
return renderLink(node, this.getRenderContext());
|
|
48803
49561
|
}
|
|
48804
49562
|
// ===========================================
|
|
48805
49563
|
// Input Node Renderers
|
|
48806
49564
|
// ===========================================
|
|
48807
49565
|
renderInput(node) {
|
|
48808
|
-
|
|
48809
|
-
`${this.prefix}-input`,
|
|
48810
|
-
node.icon ? `${this.prefix}-input-with-icon` : void 0,
|
|
48811
|
-
...this.getCommonClasses(node)
|
|
48812
|
-
]);
|
|
48813
|
-
const styles = this.buildCommonStyles(node);
|
|
48814
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48815
|
-
const attrs = {
|
|
48816
|
-
class: inputClasses,
|
|
48817
|
-
type: node.inputType || "text",
|
|
48818
|
-
placeholder: node.placeholder,
|
|
48819
|
-
value: node.value,
|
|
48820
|
-
disabled: node.disabled,
|
|
48821
|
-
required: node.required,
|
|
48822
|
-
readonly: node.readonly
|
|
48823
|
-
};
|
|
48824
|
-
const inputElement = `<input${this.buildAttrsString(attrs)} />`;
|
|
48825
|
-
if (node.icon) {
|
|
48826
|
-
const iconData = getIconData(node.icon);
|
|
48827
|
-
let iconHtml;
|
|
48828
|
-
if (iconData) {
|
|
48829
|
-
iconHtml = renderIconSvg(iconData, 16, 2, `${this.prefix}-input-icon`);
|
|
48830
|
-
} else {
|
|
48831
|
-
iconHtml = `<span class="${this.prefix}-input-icon">[${this.escapeHtml(node.icon)}]</span>`;
|
|
48832
|
-
}
|
|
48833
|
-
const wrapperClasses = this.buildClassString([`${this.prefix}-input-wrapper`]);
|
|
48834
|
-
const wrapper = `<div class="${wrapperClasses}"${styleAttr}>${iconHtml}${inputElement}</div>`;
|
|
48835
|
-
if (node.label) {
|
|
48836
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48837
|
-
${wrapper}`;
|
|
48838
|
-
}
|
|
48839
|
-
return wrapper;
|
|
48840
|
-
}
|
|
48841
|
-
const input = `<input${this.buildAttrsString(attrs)}${styleAttr} />`;
|
|
48842
|
-
if (node.label) {
|
|
48843
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48844
|
-
${input}`;
|
|
48845
|
-
}
|
|
48846
|
-
return input;
|
|
49566
|
+
return renderInput(node, this.getRenderContext());
|
|
48847
49567
|
}
|
|
48848
49568
|
renderTextarea(node) {
|
|
48849
|
-
|
|
48850
|
-
`${this.prefix}-input`,
|
|
48851
|
-
...this.getCommonClasses(node)
|
|
48852
|
-
]);
|
|
48853
|
-
const styles = this.buildCommonStyles(node);
|
|
48854
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48855
|
-
const attrs = {
|
|
48856
|
-
class: classes,
|
|
48857
|
-
placeholder: node.placeholder,
|
|
48858
|
-
disabled: node.disabled,
|
|
48859
|
-
required: node.required,
|
|
48860
|
-
rows: node.rows?.toString()
|
|
48861
|
-
};
|
|
48862
|
-
const textarea = `<textarea${this.buildAttrsString(attrs)}${styleAttr}>${this.escapeHtml(node.value || "")}</textarea>`;
|
|
48863
|
-
if (node.label) {
|
|
48864
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48865
|
-
${textarea}`;
|
|
48866
|
-
}
|
|
48867
|
-
return textarea;
|
|
49569
|
+
return renderTextarea(node, this.getRenderContext());
|
|
48868
49570
|
}
|
|
48869
49571
|
renderSelect(node) {
|
|
48870
|
-
|
|
48871
|
-
`${this.prefix}-input`,
|
|
48872
|
-
...this.getCommonClasses(node)
|
|
48873
|
-
]);
|
|
48874
|
-
const styles = this.buildCommonStyles(node);
|
|
48875
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48876
|
-
const attrs = {
|
|
48877
|
-
class: classes,
|
|
48878
|
-
disabled: node.disabled,
|
|
48879
|
-
required: node.required
|
|
48880
|
-
};
|
|
48881
|
-
const options = node.options.map((opt) => {
|
|
48882
|
-
if (typeof opt === "string") {
|
|
48883
|
-
const selected2 = opt === node.value ? " selected" : "";
|
|
48884
|
-
return `<option value="${this.escapeHtml(opt)}"${selected2}>${this.escapeHtml(opt)}</option>`;
|
|
48885
|
-
}
|
|
48886
|
-
const selected = opt.value === node.value ? " selected" : "";
|
|
48887
|
-
return `<option value="${this.escapeHtml(opt.value)}"${selected}>${this.escapeHtml(opt.label)}</option>`;
|
|
48888
|
-
}).join("\n");
|
|
48889
|
-
const placeholder = node.placeholder ? `<option value="" disabled selected>${this.escapeHtml(node.placeholder)}</option>
|
|
48890
|
-
` : "";
|
|
48891
|
-
const select = `<select${this.buildAttrsString(attrs)}${styleAttr}>
|
|
48892
|
-
${placeholder}${options}
|
|
48893
|
-
</select>`;
|
|
48894
|
-
if (node.label) {
|
|
48895
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48896
|
-
${select}`;
|
|
48897
|
-
}
|
|
48898
|
-
return select;
|
|
49572
|
+
return renderSelect(node, this.getRenderContext());
|
|
48899
49573
|
}
|
|
48900
49574
|
renderCheckbox(node) {
|
|
48901
|
-
|
|
48902
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48903
|
-
const attrs = {
|
|
48904
|
-
type: "checkbox",
|
|
48905
|
-
checked: node.checked,
|
|
48906
|
-
disabled: node.disabled
|
|
48907
|
-
};
|
|
48908
|
-
const checkbox = `<input${this.buildAttrsString(attrs)} />`;
|
|
48909
|
-
if (node.label) {
|
|
48910
|
-
return `<label class="${this.prefix}-checkbox"${styleAttr}>${checkbox}<span>${this.escapeHtml(node.label)}</span></label>`;
|
|
48911
|
-
}
|
|
48912
|
-
return checkbox;
|
|
49575
|
+
return renderCheckbox(node, this.getRenderContext());
|
|
48913
49576
|
}
|
|
48914
49577
|
renderRadio(node) {
|
|
48915
|
-
|
|
48916
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48917
|
-
const attrs = {
|
|
48918
|
-
type: "radio",
|
|
48919
|
-
name: node.name,
|
|
48920
|
-
checked: node.checked,
|
|
48921
|
-
disabled: node.disabled
|
|
48922
|
-
};
|
|
48923
|
-
const radio = `<input${this.buildAttrsString(attrs)} />`;
|
|
48924
|
-
if (node.label) {
|
|
48925
|
-
return `<label class="${this.prefix}-radio"${styleAttr}>${radio}<span>${this.escapeHtml(node.label)}</span></label>`;
|
|
48926
|
-
}
|
|
48927
|
-
return radio;
|
|
49578
|
+
return renderRadio(node, this.getRenderContext());
|
|
48928
49579
|
}
|
|
48929
49580
|
renderSwitch(node) {
|
|
48930
|
-
|
|
48931
|
-
`${this.prefix}-switch`,
|
|
48932
|
-
...this.getCommonClasses(node)
|
|
48933
|
-
]);
|
|
48934
|
-
const styles = this.buildCommonStyles(node);
|
|
48935
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48936
|
-
const attrs = {
|
|
48937
|
-
type: "checkbox",
|
|
48938
|
-
role: "switch",
|
|
48939
|
-
checked: node.checked,
|
|
48940
|
-
disabled: node.disabled
|
|
48941
|
-
};
|
|
48942
|
-
const switchEl = `<input${this.buildAttrsString(attrs)} />`;
|
|
48943
|
-
if (node.label) {
|
|
48944
|
-
return `<label class="${classes}"${styleAttr}>${switchEl} ${this.escapeHtml(node.label)}</label>`;
|
|
48945
|
-
}
|
|
48946
|
-
return `<label class="${classes}"${styleAttr}>${switchEl}</label>`;
|
|
49581
|
+
return renderSwitch(node, this.getRenderContext());
|
|
48947
49582
|
}
|
|
48948
49583
|
renderSlider(node) {
|
|
48949
|
-
|
|
48950
|
-
`${this.prefix}-slider`,
|
|
48951
|
-
...this.getCommonClasses(node)
|
|
48952
|
-
]);
|
|
48953
|
-
const styles = this.buildCommonStyles(node);
|
|
48954
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48955
|
-
const attrs = {
|
|
48956
|
-
class: classes,
|
|
48957
|
-
type: "range",
|
|
48958
|
-
min: node.min?.toString(),
|
|
48959
|
-
max: node.max?.toString(),
|
|
48960
|
-
step: node.step?.toString(),
|
|
48961
|
-
value: node.value?.toString(),
|
|
48962
|
-
disabled: node.disabled
|
|
48963
|
-
};
|
|
48964
|
-
const slider = `<input${this.buildAttrsString(attrs)}${styleAttr} />`;
|
|
48965
|
-
if (node.label) {
|
|
48966
|
-
return `<label class="${this.prefix}-input-label">${this.escapeHtml(node.label)}</label>
|
|
48967
|
-
${slider}`;
|
|
48968
|
-
}
|
|
48969
|
-
return slider;
|
|
49584
|
+
return renderSlider(node, this.getRenderContext());
|
|
48970
49585
|
}
|
|
48971
49586
|
// ===========================================
|
|
48972
49587
|
// Button Renderer
|
|
48973
49588
|
// ===========================================
|
|
48974
49589
|
renderButton(node) {
|
|
48975
|
-
|
|
48976
|
-
const classes = this.buildClassString([
|
|
48977
|
-
`${this.prefix}-button`,
|
|
48978
|
-
node.primary ? `${this.prefix}-button-primary` : void 0,
|
|
48979
|
-
node.secondary ? `${this.prefix}-button-secondary` : void 0,
|
|
48980
|
-
node.outline ? `${this.prefix}-button-outline` : void 0,
|
|
48981
|
-
node.ghost ? `${this.prefix}-button-ghost` : void 0,
|
|
48982
|
-
node.danger ? `${this.prefix}-button-danger` : void 0,
|
|
48983
|
-
node.size ? `${this.prefix}-button-${node.size}` : void 0,
|
|
48984
|
-
node.disabled ? `${this.prefix}-button-disabled` : void 0,
|
|
48985
|
-
node.loading ? `${this.prefix}-button-loading` : void 0,
|
|
48986
|
-
isIconOnly ? `${this.prefix}-button-icon-only` : void 0,
|
|
48987
|
-
...this.getCommonClasses(node)
|
|
48988
|
-
]);
|
|
48989
|
-
const styles = this.buildCommonStyles(node);
|
|
48990
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
48991
|
-
const attrs = {
|
|
48992
|
-
class: classes,
|
|
48993
|
-
disabled: node.disabled
|
|
48994
|
-
};
|
|
48995
|
-
let icon = "";
|
|
48996
|
-
if (node.icon) {
|
|
48997
|
-
const iconData = getIconData(node.icon);
|
|
48998
|
-
if (iconData) {
|
|
48999
|
-
icon = renderIconSvg(iconData, 16, 2, `${this.prefix}-icon`);
|
|
49000
|
-
} else {
|
|
49001
|
-
icon = `<span class="${this.prefix}-icon">[${this.escapeHtml(node.icon)}]</span>`;
|
|
49002
|
-
}
|
|
49003
|
-
}
|
|
49004
|
-
const loading = node.loading ? `<span class="${this.prefix}-spinner ${this.prefix}-spinner-sm"></span>` : "";
|
|
49005
|
-
const content = this.escapeHtml(node.content);
|
|
49006
|
-
return `<button${this.buildAttrsString(attrs)}${styleAttr}>${loading}${icon}${content}</button>`;
|
|
49590
|
+
return renderButton(node, this.getRenderContext());
|
|
49007
49591
|
}
|
|
49008
49592
|
// ===========================================
|
|
49009
49593
|
// Display Node Renderers
|
|
49010
49594
|
// ===========================================
|
|
49011
49595
|
renderImage(node) {
|
|
49012
|
-
|
|
49013
|
-
`${this.prefix}-image`,
|
|
49014
|
-
...this.getCommonClasses(node)
|
|
49015
|
-
]);
|
|
49016
|
-
const styles = this.buildCommonStyles(node);
|
|
49017
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49018
|
-
if (node.src) {
|
|
49019
|
-
const attrs = {
|
|
49020
|
-
class: classes,
|
|
49021
|
-
src: node.src,
|
|
49022
|
-
alt: node.alt || "Image"
|
|
49023
|
-
};
|
|
49024
|
-
const imgStyleAttr = styles ? `; ${styles}` : "";
|
|
49025
|
-
return `<img${this.buildAttrsString(attrs)}${imgStyleAttr ? ` style="${imgStyleAttr.slice(2)}"` : ""} />`;
|
|
49026
|
-
}
|
|
49027
|
-
const label = node.alt || "Image";
|
|
49028
|
-
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>`;
|
|
49029
|
-
return `<div class="${classes}"${styleAttr} role="img" aria-label="${this.escapeHtml(label)}">${icon}<span>${this.escapeHtml(label)}</span></div>`;
|
|
49596
|
+
return renderImage(node, this.getRenderContext());
|
|
49030
49597
|
}
|
|
49031
49598
|
renderPlaceholder(node) {
|
|
49032
|
-
|
|
49033
|
-
`${this.prefix}-placeholder`,
|
|
49034
|
-
node.children && node.children.length > 0 ? `${this.prefix}-placeholder-with-children` : void 0,
|
|
49035
|
-
...this.getCommonClasses(node)
|
|
49036
|
-
]);
|
|
49037
|
-
const styles = this.buildCommonStyles(node);
|
|
49038
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49039
|
-
const label = node.label ? this.escapeHtml(node.label) : "Placeholder";
|
|
49040
|
-
if (node.children && node.children.length > 0) {
|
|
49041
|
-
const childrenHtml = this.renderChildren(node.children);
|
|
49042
|
-
return `<div class="${classes}"${styleAttr}>
|
|
49043
|
-
<span class="${this.prefix}-placeholder-label">${label}</span>
|
|
49044
|
-
<div class="${this.prefix}-placeholder-overlay">${childrenHtml}</div>
|
|
49045
|
-
</div>`;
|
|
49046
|
-
}
|
|
49047
|
-
return `<div class="${classes}"${styleAttr}>${label}</div>`;
|
|
49599
|
+
return renderPlaceholder(node, this.getRenderContext());
|
|
49048
49600
|
}
|
|
49049
49601
|
renderAvatar(node) {
|
|
49050
|
-
|
|
49051
|
-
const classes = this.buildClassString([
|
|
49052
|
-
`${this.prefix}-avatar`,
|
|
49053
|
-
sizeResolved.className,
|
|
49054
|
-
...this.getCommonClasses(node)
|
|
49055
|
-
]);
|
|
49056
|
-
const baseStyles = this.buildCommonStyles(node);
|
|
49057
|
-
const sizeStyle = sizeResolved.style || "";
|
|
49058
|
-
const combinedStyles = baseStyles && sizeStyle ? `${baseStyles}; ${sizeStyle}` : baseStyles || sizeStyle;
|
|
49059
|
-
const styleAttr = combinedStyles ? ` style="${combinedStyles}"` : "";
|
|
49060
|
-
const initials = node.name ? node.name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) : "?";
|
|
49061
|
-
return `<div class="${classes}"${styleAttr} role="img" aria-label="${this.escapeHtml(node.name || "Avatar")}">${initials}</div>`;
|
|
49602
|
+
return renderAvatar(node, this.getRenderContext());
|
|
49062
49603
|
}
|
|
49063
49604
|
renderBadge(node) {
|
|
49064
|
-
|
|
49065
|
-
const iconData = getIconData(node.icon);
|
|
49066
|
-
const classes2 = this.buildClassString([
|
|
49067
|
-
`${this.prefix}-badge-icon`,
|
|
49068
|
-
node.size ? `${this.prefix}-badge-icon-${node.size}` : void 0,
|
|
49069
|
-
node.variant ? `${this.prefix}-badge-icon-${node.variant}` : void 0,
|
|
49070
|
-
...this.getCommonClasses(node)
|
|
49071
|
-
]);
|
|
49072
|
-
const styles2 = this.buildCommonStyles(node);
|
|
49073
|
-
const styleAttr2 = styles2 ? ` style="${styles2}"` : "";
|
|
49074
|
-
if (iconData) {
|
|
49075
|
-
const svg = renderIconSvg(iconData, 24, 2, `${this.prefix}-icon`);
|
|
49076
|
-
return `<span class="${classes2}"${styleAttr2} aria-label="${this.escapeHtml(node.icon)}">${svg}</span>`;
|
|
49077
|
-
}
|
|
49078
|
-
return `<span class="${classes2}"${styleAttr2} aria-label="unknown icon">?</span>`;
|
|
49079
|
-
}
|
|
49080
|
-
const isDot = !node.content || node.content.trim() === "";
|
|
49081
|
-
const classes = this.buildClassString([
|
|
49082
|
-
`${this.prefix}-badge`,
|
|
49083
|
-
isDot ? `${this.prefix}-badge-dot` : void 0,
|
|
49084
|
-
node.variant ? `${this.prefix}-badge-${node.variant}` : void 0,
|
|
49085
|
-
node.pill ? `${this.prefix}-badge-pill` : void 0,
|
|
49086
|
-
...this.getCommonClasses(node)
|
|
49087
|
-
]);
|
|
49088
|
-
const styles = this.buildCommonStyles(node);
|
|
49089
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49090
|
-
return `<span class="${classes}"${styleAttr}>${this.escapeHtml(node.content)}</span>`;
|
|
49605
|
+
return renderBadge(node, this.getRenderContext());
|
|
49091
49606
|
}
|
|
49092
49607
|
renderIcon(node) {
|
|
49093
|
-
|
|
49094
|
-
const sizeResolved = resolveSizeValue(node.size, "icon", this.prefix);
|
|
49095
|
-
const wrapperClasses = this.buildClassString([
|
|
49096
|
-
`${this.prefix}-icon-wrapper`,
|
|
49097
|
-
node.muted ? `${this.prefix}-text-muted` : void 0,
|
|
49098
|
-
...this.getCommonClasses(node)
|
|
49099
|
-
]);
|
|
49100
|
-
const baseStyles = this.buildCommonStyles(node);
|
|
49101
|
-
if (iconData) {
|
|
49102
|
-
const iconClasses = buildClassString([
|
|
49103
|
-
`${this.prefix}-icon`,
|
|
49104
|
-
sizeResolved.className
|
|
49105
|
-
]);
|
|
49106
|
-
const svgStyleAttr = sizeResolved.style ? ` style="${sizeResolved.style}"` : "";
|
|
49107
|
-
const svg = renderIconSvg(iconData, 24, 2, iconClasses, svgStyleAttr);
|
|
49108
|
-
const wrapperStyleAttr2 = baseStyles ? ` style="${baseStyles}"` : "";
|
|
49109
|
-
return `<span class="${wrapperClasses}"${wrapperStyleAttr2} aria-hidden="true">${svg}</span>`;
|
|
49110
|
-
}
|
|
49111
|
-
const size = sizeResolved.style?.match(/(\d+)px/)?.[1] || "24";
|
|
49112
|
-
const sizeNum = parseInt(size, 10);
|
|
49113
|
-
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">
|
|
49114
|
-
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" stroke-dasharray="4 2" fill="none" opacity="0.5"/>
|
|
49115
|
-
<text x="12" y="16" text-anchor="middle" font-size="10" fill="currentColor" opacity="0.7">?</text>
|
|
49116
|
-
</svg>`;
|
|
49117
|
-
const wrapperStyleAttr = baseStyles ? ` style="${baseStyles}"` : "";
|
|
49118
|
-
return `<span class="${wrapperClasses}"${wrapperStyleAttr} aria-hidden="true" title="Unknown icon: ${this.escapeHtml(node.name)}">${placeholderSvg}</span>`;
|
|
49608
|
+
return renderIcon(node, this.getRenderContext());
|
|
49119
49609
|
}
|
|
49120
49610
|
// ===========================================
|
|
49121
49611
|
// Data Node Renderers
|
|
49122
49612
|
// ===========================================
|
|
49123
49613
|
renderTable(node) {
|
|
49124
|
-
|
|
49125
|
-
`${this.prefix}-table`,
|
|
49126
|
-
node.striped ? `${this.prefix}-table-striped` : void 0,
|
|
49127
|
-
node.bordered ? `${this.prefix}-table-bordered` : void 0,
|
|
49128
|
-
node.hover ? `${this.prefix}-table-hover` : void 0,
|
|
49129
|
-
...this.getCommonClasses(node)
|
|
49130
|
-
]);
|
|
49131
|
-
const styles = this.buildCommonStyles(node);
|
|
49132
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49133
|
-
const thead = `<thead><tr>${node.columns.map((col) => `<th>${this.escapeHtml(col)}</th>`).join("")}</tr></thead>`;
|
|
49134
|
-
const tbody = `<tbody>${node.rows.map(
|
|
49135
|
-
(row) => `<tr>${row.map((cell) => {
|
|
49136
|
-
if (typeof cell === "string") {
|
|
49137
|
-
return `<td>${this.renderTableCellContent(cell)}</td>`;
|
|
49138
|
-
}
|
|
49139
|
-
return `<td>${this.renderNode(cell)}</td>`;
|
|
49140
|
-
}).join("")}</tr>`
|
|
49141
|
-
).join("")}</tbody>`;
|
|
49142
|
-
return `<table class="${classes}"${styleAttr}>
|
|
49143
|
-
${thead}
|
|
49144
|
-
${tbody}
|
|
49145
|
-
</table>`;
|
|
49614
|
+
return renderTable(node, this.getRenderContext());
|
|
49146
49615
|
}
|
|
49147
49616
|
renderList(node) {
|
|
49148
|
-
|
|
49149
|
-
const classes = this.buildClassString([
|
|
49150
|
-
`${this.prefix}-list`,
|
|
49151
|
-
node.ordered ? `${this.prefix}-list-ordered` : void 0,
|
|
49152
|
-
node.none ? `${this.prefix}-list-none` : void 0,
|
|
49153
|
-
...this.getCommonClasses(node)
|
|
49154
|
-
]);
|
|
49155
|
-
const styles = this.buildCommonStyles(node);
|
|
49156
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49157
|
-
const items = node.items.map((item) => {
|
|
49158
|
-
if (typeof item === "string") {
|
|
49159
|
-
return `<li class="${this.prefix}-list-item">${this.escapeHtml(item)}</li>`;
|
|
49160
|
-
}
|
|
49161
|
-
return `<li class="${this.prefix}-list-item">${this.escapeHtml(item.content)}</li>`;
|
|
49162
|
-
}).join("\n");
|
|
49163
|
-
return `<${tag} class="${classes}"${styleAttr}>
|
|
49164
|
-
${items}
|
|
49165
|
-
</${tag}>`;
|
|
49617
|
+
return renderList(node, this.getRenderContext());
|
|
49166
49618
|
}
|
|
49167
49619
|
// ===========================================
|
|
49168
49620
|
// Feedback Node Renderers
|
|
49169
49621
|
// ===========================================
|
|
49170
49622
|
renderAlert(node) {
|
|
49171
|
-
|
|
49172
|
-
`${this.prefix}-alert`,
|
|
49173
|
-
node.variant ? `${this.prefix}-alert-${node.variant}` : void 0,
|
|
49174
|
-
...this.getCommonClasses(node)
|
|
49175
|
-
]);
|
|
49176
|
-
const styles = this.buildCommonStyles(node);
|
|
49177
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49178
|
-
const dismissBtn = node.dismissible ? ` <button class="${this.prefix}-alert-close" aria-label="Close">×</button>` : "";
|
|
49179
|
-
return `<div class="${classes}"${styleAttr} role="alert">${this.escapeHtml(node.content)}${dismissBtn}</div>`;
|
|
49623
|
+
return renderAlert(node, this.getRenderContext());
|
|
49180
49624
|
}
|
|
49181
49625
|
renderToast(node) {
|
|
49182
|
-
|
|
49183
|
-
`${this.prefix}-toast`,
|
|
49184
|
-
node.position ? `${this.prefix}-toast-${node.position}` : void 0,
|
|
49185
|
-
node.variant ? `${this.prefix}-toast-${node.variant}` : void 0,
|
|
49186
|
-
...this.getCommonClasses(node)
|
|
49187
|
-
]);
|
|
49188
|
-
const styles = this.buildCommonStyles(node);
|
|
49189
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49190
|
-
return `<div class="${classes}"${styleAttr} role="status">${this.escapeHtml(node.content)}</div>`;
|
|
49626
|
+
return renderToast(node, this.getRenderContext());
|
|
49191
49627
|
}
|
|
49192
49628
|
renderProgress(node) {
|
|
49193
|
-
|
|
49194
|
-
`${this.prefix}-progress`,
|
|
49195
|
-
...this.getCommonClasses(node)
|
|
49196
|
-
]);
|
|
49197
|
-
const styles = this.buildCommonStyles(node);
|
|
49198
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49199
|
-
const value = node.value || 0;
|
|
49200
|
-
const max = node.max || 100;
|
|
49201
|
-
const percentage = Math.round(value / max * 100);
|
|
49202
|
-
const label = node.label ? `<span class="${this.prefix}-progress-label">${this.escapeHtml(node.label)}</span>` : "";
|
|
49203
|
-
if (node.indeterminate) {
|
|
49204
|
-
return `<div class="${classes} ${this.prefix}-progress-indeterminate"${styleAttr} role="progressbar">${label}</div>`;
|
|
49205
|
-
}
|
|
49206
|
-
return `<div class="${classes}"${styleAttr} role="progressbar" aria-valuenow="${value}" aria-valuemin="0" aria-valuemax="${max}">
|
|
49207
|
-
${label}
|
|
49208
|
-
<div class="${this.prefix}-progress-bar" style="width: ${percentage}%"></div>
|
|
49209
|
-
</div>`;
|
|
49629
|
+
return renderProgress(node, this.getRenderContext());
|
|
49210
49630
|
}
|
|
49211
49631
|
renderSpinner(node) {
|
|
49212
|
-
|
|
49213
|
-
const classes = this.buildClassString([
|
|
49214
|
-
`${this.prefix}-spinner`,
|
|
49215
|
-
sizeResolved.className,
|
|
49216
|
-
...this.getCommonClasses(node)
|
|
49217
|
-
]);
|
|
49218
|
-
const baseStyles = this.buildCommonStyles(node);
|
|
49219
|
-
const sizeStyle = sizeResolved.style || "";
|
|
49220
|
-
const combinedStyles = baseStyles && sizeStyle ? `${baseStyles}; ${sizeStyle}` : baseStyles || sizeStyle;
|
|
49221
|
-
const styleAttr = combinedStyles ? ` style="${combinedStyles}"` : "";
|
|
49222
|
-
const label = node.label || "Loading...";
|
|
49223
|
-
return `<span class="${classes}"${styleAttr} role="status" aria-label="${this.escapeHtml(label)}"></span>`;
|
|
49632
|
+
return renderSpinner(node, this.getRenderContext());
|
|
49224
49633
|
}
|
|
49225
49634
|
// ===========================================
|
|
49226
49635
|
// Overlay Node Renderers
|
|
49227
49636
|
// ===========================================
|
|
49228
49637
|
renderTooltip(node) {
|
|
49229
|
-
|
|
49230
|
-
`${this.prefix}-tooltip-wrapper`,
|
|
49231
|
-
...this.getCommonClasses(node)
|
|
49232
|
-
]);
|
|
49233
|
-
const styles = this.buildCommonStyles(node);
|
|
49234
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49235
|
-
const position = node.position || "top";
|
|
49236
|
-
const children = this.renderChildren(node.children);
|
|
49237
|
-
return `<div class="${classes}"${styleAttr}>
|
|
49238
|
-
${children}
|
|
49239
|
-
<div class="${this.prefix}-tooltip ${this.prefix}-tooltip-${position}" role="tooltip">${this.escapeHtml(node.content)}</div>
|
|
49240
|
-
</div>`;
|
|
49638
|
+
return renderTooltip(node, this.getRenderContext());
|
|
49241
49639
|
}
|
|
49242
49640
|
renderPopover(node) {
|
|
49243
|
-
|
|
49244
|
-
`${this.prefix}-popover`,
|
|
49245
|
-
...this.getCommonClasses(node)
|
|
49246
|
-
]);
|
|
49247
|
-
const styles = this.buildCommonStyles(node);
|
|
49248
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49249
|
-
const title = node.title ? `<div class="${this.prefix}-popover-header">${this.escapeHtml(node.title)}</div>
|
|
49250
|
-
` : "";
|
|
49251
|
-
const children = this.renderChildren(node.children);
|
|
49252
|
-
return `<div class="${classes}"${styleAttr}>
|
|
49253
|
-
${title}<div class="${this.prefix}-popover-body">
|
|
49254
|
-
${children}
|
|
49255
|
-
</div>
|
|
49256
|
-
</div>`;
|
|
49641
|
+
return renderPopover(node, this.getRenderContext());
|
|
49257
49642
|
}
|
|
49258
49643
|
renderDropdown(node) {
|
|
49259
|
-
|
|
49260
|
-
`${this.prefix}-dropdown`,
|
|
49261
|
-
...this.getCommonClasses(node)
|
|
49262
|
-
]);
|
|
49263
|
-
const styles = this.buildCommonStyles(node);
|
|
49264
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49265
|
-
const items = node.items.map((item) => {
|
|
49266
|
-
if ("type" in item && item.type === "divider") {
|
|
49267
|
-
return `<hr class="${this.prefix}-divider" />`;
|
|
49268
|
-
}
|
|
49269
|
-
const dropdownItem = item;
|
|
49270
|
-
const itemClasses = this.buildClassString([
|
|
49271
|
-
`${this.prefix}-dropdown-item`,
|
|
49272
|
-
dropdownItem.danger ? `${this.prefix}-dropdown-item-danger` : void 0,
|
|
49273
|
-
dropdownItem.disabled ? `${this.prefix}-dropdown-item-disabled` : void 0
|
|
49274
|
-
]);
|
|
49275
|
-
return `<button class="${itemClasses}"${dropdownItem.disabled ? " disabled" : ""}>${this.escapeHtml(dropdownItem.label)}</button>`;
|
|
49276
|
-
}).join("\n");
|
|
49277
|
-
return `<div class="${classes}"${styleAttr}>
|
|
49278
|
-
${items}
|
|
49279
|
-
</div>`;
|
|
49644
|
+
return renderDropdown(node, this.getRenderContext());
|
|
49280
49645
|
}
|
|
49281
49646
|
// ===========================================
|
|
49282
49647
|
// Navigation Node Renderers
|
|
49283
49648
|
// ===========================================
|
|
49284
49649
|
renderNav(node) {
|
|
49285
|
-
|
|
49286
|
-
`${this.prefix}-nav`,
|
|
49287
|
-
node.vertical ? `${this.prefix}-nav-vertical` : void 0,
|
|
49288
|
-
...this.getCommonClasses(node)
|
|
49289
|
-
]);
|
|
49290
|
-
const styles = this.buildCommonStyles(node);
|
|
49291
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49292
|
-
if (node.children && node.children.length > 0) {
|
|
49293
|
-
const content = this.renderNavChildren(node.children);
|
|
49294
|
-
return `<nav class="${classes}"${styleAttr}>
|
|
49295
|
-
${content}
|
|
49296
|
-
</nav>`;
|
|
49297
|
-
}
|
|
49298
|
-
const items = node.items.map((item) => {
|
|
49299
|
-
if (typeof item === "string") {
|
|
49300
|
-
return `<a class="${this.prefix}-nav-link" href="#">${this.escapeHtml(item)}</a>`;
|
|
49301
|
-
}
|
|
49302
|
-
const linkClasses = this.buildClassString([
|
|
49303
|
-
`${this.prefix}-nav-link`,
|
|
49304
|
-
item.active ? `${this.prefix}-nav-link-active` : void 0,
|
|
49305
|
-
item.disabled ? `${this.prefix}-nav-link-disabled` : void 0
|
|
49306
|
-
]);
|
|
49307
|
-
const iconHtml = item.icon ? this.renderIconHtml(item.icon) + " " : "";
|
|
49308
|
-
return `<a class="${linkClasses}" href="${item.href || "#"}">${iconHtml}${this.escapeHtml(item.label)}</a>`;
|
|
49309
|
-
}).join("\n");
|
|
49310
|
-
return `<nav class="${classes}"${styleAttr}>
|
|
49311
|
-
${items}
|
|
49312
|
-
</nav>`;
|
|
49313
|
-
}
|
|
49314
|
-
renderNavChildren(children) {
|
|
49315
|
-
return children.map((child) => {
|
|
49316
|
-
if (child.type === "divider") {
|
|
49317
|
-
return `<hr class="${this.prefix}-nav-divider" />`;
|
|
49318
|
-
}
|
|
49319
|
-
if (child.type === "group") {
|
|
49320
|
-
const groupItems = child.items.map((item) => {
|
|
49321
|
-
if (item.type === "divider") {
|
|
49322
|
-
return `<hr class="${this.prefix}-nav-divider" />`;
|
|
49323
|
-
}
|
|
49324
|
-
return this.renderNavItem(item);
|
|
49325
|
-
}).join("\n");
|
|
49326
|
-
return `<div class="${this.prefix}-nav-group">
|
|
49327
|
-
<div class="${this.prefix}-nav-group-label">${this.escapeHtml(child.label)}</div>
|
|
49328
|
-
${groupItems}
|
|
49329
|
-
</div>`;
|
|
49330
|
-
}
|
|
49331
|
-
if (child.type === "item") {
|
|
49332
|
-
return this.renderNavItem(child);
|
|
49333
|
-
}
|
|
49334
|
-
return "";
|
|
49335
|
-
}).join("\n");
|
|
49336
|
-
}
|
|
49337
|
-
renderNavItem(item) {
|
|
49338
|
-
const linkClasses = this.buildClassString([
|
|
49339
|
-
`${this.prefix}-nav-link`,
|
|
49340
|
-
item.active ? `${this.prefix}-nav-link-active` : void 0,
|
|
49341
|
-
item.disabled ? `${this.prefix}-nav-link-disabled` : void 0
|
|
49342
|
-
]);
|
|
49343
|
-
const iconHtml = item.icon ? this.renderIconHtml(item.icon) + " " : "";
|
|
49344
|
-
return `<a class="${linkClasses}" href="${item.href || "#"}">${iconHtml}${this.escapeHtml(item.label)}</a>`;
|
|
49345
|
-
}
|
|
49346
|
-
renderIconHtml(iconName) {
|
|
49347
|
-
return `<span class="${this.prefix}-icon" data-icon="${iconName}"></span>`;
|
|
49650
|
+
return renderNav(node, this.getRenderContext());
|
|
49348
49651
|
}
|
|
49349
49652
|
renderTabs(node) {
|
|
49350
|
-
|
|
49351
|
-
`${this.prefix}-tabs`,
|
|
49352
|
-
...this.getCommonClasses(node)
|
|
49353
|
-
]);
|
|
49354
|
-
const styles = this.buildCommonStyles(node);
|
|
49355
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49356
|
-
const tabList = node.items.map((label, idx) => {
|
|
49357
|
-
const isActive = idx === (node.active || 0);
|
|
49358
|
-
const tabClasses = `${this.prefix}-tab${isActive ? ` ${this.prefix}-tab-active` : ""}`;
|
|
49359
|
-
return `<button class="${tabClasses}" role="tab" aria-selected="${isActive}">${this.escapeHtml(label)}</button>`;
|
|
49360
|
-
}).join("\n");
|
|
49361
|
-
return `<div class="${classes}"${styleAttr}>
|
|
49362
|
-
<div class="${this.prefix}-tab-list" role="tablist">
|
|
49363
|
-
${tabList}
|
|
49364
|
-
</div>
|
|
49365
|
-
</div>`;
|
|
49653
|
+
return renderTabs(node, this.getRenderContext());
|
|
49366
49654
|
}
|
|
49367
49655
|
renderBreadcrumb(node) {
|
|
49368
|
-
|
|
49369
|
-
`${this.prefix}-breadcrumb`,
|
|
49370
|
-
...this.getCommonClasses(node)
|
|
49371
|
-
]);
|
|
49372
|
-
const styles = this.buildCommonStyles(node);
|
|
49373
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49374
|
-
const items = node.items.map((item, idx) => {
|
|
49375
|
-
const isLast = idx === node.items.length - 1;
|
|
49376
|
-
if (typeof item === "string") {
|
|
49377
|
-
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>`;
|
|
49378
|
-
}
|
|
49379
|
-
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>`;
|
|
49380
|
-
}).join(" / ");
|
|
49381
|
-
return `<nav class="${classes}"${styleAttr} aria-label="Breadcrumb">${items}</nav>`;
|
|
49656
|
+
return renderBreadcrumb(node, this.getRenderContext());
|
|
49382
49657
|
}
|
|
49383
49658
|
// ===========================================
|
|
49384
49659
|
// Divider Renderer
|
|
49385
49660
|
// ===========================================
|
|
49386
49661
|
renderDivider(node) {
|
|
49387
|
-
|
|
49388
|
-
const styleAttr = styles ? ` style="${styles}"` : "";
|
|
49389
|
-
return `<hr class="${this.prefix}-divider"${styleAttr} />`;
|
|
49390
|
-
}
|
|
49391
|
-
// ===========================================
|
|
49392
|
-
// Semantic Marker Rendering
|
|
49393
|
-
// ===========================================
|
|
49394
|
-
/**
|
|
49395
|
-
* Parse and render semantic markers in text content
|
|
49396
|
-
*
|
|
49397
|
-
* Semantic markers use the syntax [component:variant] to indicate
|
|
49398
|
-
* what a visual element represents. This helps LLMs understand
|
|
49399
|
-
* the meaning of placeholder content.
|
|
49400
|
-
*
|
|
49401
|
-
* Supported markers:
|
|
49402
|
-
* - [avatar] or [avatar:size] - User avatar (renders as circle placeholder)
|
|
49403
|
-
* - [badge:variant] TEXT - Status badge (TEXT is displayed inside the badge)
|
|
49404
|
-
* - [dot:variant] - Status dot (renders as small circle before text)
|
|
49405
|
-
* - [icon:name] - Icon placeholder
|
|
49406
|
-
*
|
|
49407
|
-
* Examples:
|
|
49408
|
-
* - "[avatar] John Doe" → renders avatar circle + "John Doe"
|
|
49409
|
-
* - "[badge:primary] PRO" → renders badge containing "PRO"
|
|
49410
|
-
* - "[dot:success] Active" → renders green dot + "Active"
|
|
49411
|
-
*/
|
|
49412
|
-
renderSemanticMarkers(text) {
|
|
49413
|
-
const markerPattern = /\[([a-z]+)(?::([a-z0-9-]+))?\](\s*)/gi;
|
|
49414
|
-
let result = "";
|
|
49415
|
-
let lastIndex = 0;
|
|
49416
|
-
let match;
|
|
49417
|
-
while ((match = markerPattern.exec(text)) !== null) {
|
|
49418
|
-
if (match.index > lastIndex) {
|
|
49419
|
-
result += this.escapeHtml(text.substring(lastIndex, match.index));
|
|
49420
|
-
}
|
|
49421
|
-
const [fullMatch, component, variant] = match;
|
|
49422
|
-
const comp = component.toLowerCase();
|
|
49423
|
-
const varnt = variant?.toLowerCase();
|
|
49424
|
-
if (comp === "badge") {
|
|
49425
|
-
const afterMarker = text.substring(match.index + fullMatch.length);
|
|
49426
|
-
const contentMatch = afterMarker.match(/^([^\n\[]+?)(?=\n|\[|$)/);
|
|
49427
|
-
const badgeContent = contentMatch ? contentMatch[1].trim() : "";
|
|
49428
|
-
result += this.renderSemanticMarkerWithContent(comp, varnt, badgeContent);
|
|
49429
|
-
lastIndex = match.index + fullMatch.length + (contentMatch ? contentMatch[0].length : 0);
|
|
49430
|
-
markerPattern.lastIndex = lastIndex;
|
|
49431
|
-
} else {
|
|
49432
|
-
result += this.renderSemanticMarker(comp, varnt);
|
|
49433
|
-
lastIndex = match.index + fullMatch.length;
|
|
49434
|
-
}
|
|
49435
|
-
}
|
|
49436
|
-
if (lastIndex < text.length) {
|
|
49437
|
-
result += this.escapeHtml(text.substring(lastIndex));
|
|
49438
|
-
}
|
|
49439
|
-
if (lastIndex === 0) {
|
|
49440
|
-
return this.escapeHtml(text);
|
|
49441
|
-
}
|
|
49442
|
-
return result;
|
|
49443
|
-
}
|
|
49444
|
-
/**
|
|
49445
|
-
* Render a single semantic marker to HTML (without content)
|
|
49446
|
-
*/
|
|
49447
|
-
renderSemanticMarker(component, variant) {
|
|
49448
|
-
const prefix = this.prefix;
|
|
49449
|
-
switch (component) {
|
|
49450
|
-
case "avatar":
|
|
49451
|
-
const avatarSize = variant || "sm";
|
|
49452
|
-
return `<span class="${prefix}-semantic-avatar ${prefix}-semantic-avatar-${avatarSize}" data-semantic="avatar" data-variant="${avatarSize}" aria-hidden="true"></span>`;
|
|
49453
|
-
case "dot":
|
|
49454
|
-
const dotVariant = variant || "default";
|
|
49455
|
-
return `<span class="${prefix}-semantic-dot ${prefix}-semantic-dot-${dotVariant}" data-semantic="dot" data-variant="${dotVariant}" aria-hidden="true"></span>`;
|
|
49456
|
-
case "icon":
|
|
49457
|
-
const iconName = variant || "default";
|
|
49458
|
-
return `<span class="${prefix}-semantic-icon" data-semantic="icon" data-variant="${iconName}" aria-hidden="true">[${iconName}]</span>`;
|
|
49459
|
-
default:
|
|
49460
|
-
return `<span class="${prefix}-semantic-unknown" data-semantic="${component}" data-variant="${variant || ""}">[${component}${variant ? ":" + variant : ""}]</span>`;
|
|
49461
|
-
}
|
|
49462
|
-
}
|
|
49463
|
-
/**
|
|
49464
|
-
* Render a semantic marker with text content (for badge)
|
|
49465
|
-
*/
|
|
49466
|
-
renderSemanticMarkerWithContent(component, variant, content) {
|
|
49467
|
-
const prefix = this.prefix;
|
|
49468
|
-
switch (component) {
|
|
49469
|
-
case "badge":
|
|
49470
|
-
const badgeVariant = variant || "default";
|
|
49471
|
-
const escapedContent = this.escapeHtml(content);
|
|
49472
|
-
return `<span class="${prefix}-semantic-badge ${prefix}-semantic-badge-${badgeVariant}" data-semantic="badge" data-variant="${badgeVariant}">${escapedContent}</span>`;
|
|
49473
|
-
default:
|
|
49474
|
-
return this.renderSemanticMarker(component, variant) + this.escapeHtml(content);
|
|
49475
|
-
}
|
|
49476
|
-
}
|
|
49477
|
-
/**
|
|
49478
|
-
* Process table cell content with semantic markers and newlines
|
|
49479
|
-
*
|
|
49480
|
-
* Special handling for avatar + text layout:
|
|
49481
|
-
* When content starts with [avatar], wraps in flex container
|
|
49482
|
-
* so avatar and text align horizontally, with text stacking vertically
|
|
49483
|
-
*/
|
|
49484
|
-
renderTableCellContent(content) {
|
|
49485
|
-
const avatarMatch = content.match(/^\[avatar(?::([a-z0-9-]+))?\]\s*/i);
|
|
49486
|
-
if (avatarMatch) {
|
|
49487
|
-
const avatarVariant = avatarMatch[1]?.toLowerCase();
|
|
49488
|
-
const avatarHtml = this.renderSemanticMarker("avatar", avatarVariant);
|
|
49489
|
-
const restContent = content.slice(avatarMatch[0].length);
|
|
49490
|
-
const restHtml = this.renderSemanticMarkers(restContent);
|
|
49491
|
-
const lines = restHtml.split("\n");
|
|
49492
|
-
const textHtml = lines.length > 1 ? lines.map((line) => `<span>${line}</span>`).join("") : restHtml;
|
|
49493
|
-
return `<div class="${this.prefix}-cell-avatar-layout">${avatarHtml}<div class="${this.prefix}-cell-avatar-text">${textHtml}</div></div>`;
|
|
49494
|
-
}
|
|
49495
|
-
const withMarkers = this.renderSemanticMarkers(content);
|
|
49496
|
-
return withMarkers.replace(/\n/g, "<br>");
|
|
49662
|
+
return renderDivider(node, this.getRenderContext());
|
|
49497
49663
|
}
|
|
49498
49664
|
};
|
|
49499
49665
|
function createHtmlRenderer(options) {
|
|
49500
49666
|
return new HtmlRenderer(options);
|
|
49501
49667
|
}
|
|
49502
49668
|
|
|
49503
|
-
// src/renderer/svg/flex-layout.ts
|
|
49504
|
-
function computeFlexLayout(items, config) {
|
|
49505
|
-
const { mainSize, crossSize, justifyContent, alignItems, gap } = config;
|
|
49506
|
-
const computed = items.map((props, index) => {
|
|
49507
|
-
let flexBasis;
|
|
49508
|
-
if (props.basis === "auto" || props.basis === "content") {
|
|
49509
|
-
flexBasis = props.contentSize;
|
|
49510
|
-
} else {
|
|
49511
|
-
flexBasis = props.basis;
|
|
49512
|
-
}
|
|
49513
|
-
flexBasis = clamp(flexBasis, props.minSize, props.maxSize);
|
|
49514
|
-
return {
|
|
49515
|
-
index,
|
|
49516
|
-
props,
|
|
49517
|
-
flexBasis,
|
|
49518
|
-
mainSize: flexBasis,
|
|
49519
|
-
crossSize: 0,
|
|
49520
|
-
mainPosition: 0,
|
|
49521
|
-
crossPosition: 0,
|
|
49522
|
-
frozen: false,
|
|
49523
|
-
scaledShrinkFactor: props.shrink * flexBasis
|
|
49524
|
-
};
|
|
49525
|
-
});
|
|
49526
|
-
const totalGap = Math.max(0, (items.length - 1) * gap);
|
|
49527
|
-
const totalFlexBasis = computed.reduce((sum, item) => sum + item.flexBasis, 0);
|
|
49528
|
-
let freeSpace = mainSize - totalFlexBasis - totalGap;
|
|
49529
|
-
if (freeSpace !== 0) {
|
|
49530
|
-
resolveFlexibleLengths(computed, freeSpace);
|
|
49531
|
-
}
|
|
49532
|
-
distributeMainAxis(computed, mainSize, totalGap, gap, justifyContent);
|
|
49533
|
-
const crossSizeMax = crossSize ?? Math.max(...computed.map((item) => item.props.contentSize), 0);
|
|
49534
|
-
alignCrossAxis(computed, crossSizeMax, alignItems);
|
|
49535
|
-
const mainSizeUsed = computed.reduce((sum, item) => sum + item.mainSize, 0) + totalGap;
|
|
49536
|
-
return {
|
|
49537
|
-
items: computed,
|
|
49538
|
-
mainSizeUsed,
|
|
49539
|
-
crossSizeMax
|
|
49540
|
-
};
|
|
49541
|
-
}
|
|
49542
|
-
function resolveFlexibleLengths(items, initialFreeSpace) {
|
|
49543
|
-
items.forEach((item) => {
|
|
49544
|
-
item.frozen = false;
|
|
49545
|
-
item.mainSize = item.flexBasis;
|
|
49546
|
-
});
|
|
49547
|
-
let freeSpace = initialFreeSpace;
|
|
49548
|
-
const isGrowing = freeSpace > 0;
|
|
49549
|
-
let iteration = 0;
|
|
49550
|
-
const maxIterations = items.length + 1;
|
|
49551
|
-
while (iteration < maxIterations) {
|
|
49552
|
-
iteration++;
|
|
49553
|
-
const unfrozen = items.filter((item) => !item.frozen);
|
|
49554
|
-
if (unfrozen.length === 0) break;
|
|
49555
|
-
let flexFactorSum;
|
|
49556
|
-
if (isGrowing) {
|
|
49557
|
-
flexFactorSum = unfrozen.reduce((sum, item) => sum + item.props.grow, 0);
|
|
49558
|
-
} else {
|
|
49559
|
-
flexFactorSum = unfrozen.reduce((sum, item) => sum + item.scaledShrinkFactor, 0);
|
|
49560
|
-
}
|
|
49561
|
-
if (flexFactorSum === 0) {
|
|
49562
|
-
unfrozen.forEach((item) => item.frozen = true);
|
|
49563
|
-
break;
|
|
49564
|
-
}
|
|
49565
|
-
const usedSpace = items.reduce((sum, item) => sum + item.mainSize, 0);
|
|
49566
|
-
const containerMainSize = usedSpace + freeSpace;
|
|
49567
|
-
freeSpace = containerMainSize - usedSpace;
|
|
49568
|
-
let totalViolation = 0;
|
|
49569
|
-
for (const item of unfrozen) {
|
|
49570
|
-
let flexFraction;
|
|
49571
|
-
if (isGrowing) {
|
|
49572
|
-
flexFraction = item.props.grow / flexFactorSum;
|
|
49573
|
-
} else {
|
|
49574
|
-
flexFraction = item.scaledShrinkFactor / flexFactorSum;
|
|
49575
|
-
}
|
|
49576
|
-
const deltaSize = freeSpace * flexFraction;
|
|
49577
|
-
const targetSize = item.flexBasis + deltaSize;
|
|
49578
|
-
const clampedSize = clamp(targetSize, item.props.minSize, item.props.maxSize);
|
|
49579
|
-
const violation = clampedSize - targetSize;
|
|
49580
|
-
item.mainSize = clampedSize;
|
|
49581
|
-
totalViolation += violation;
|
|
49582
|
-
if (violation !== 0) {
|
|
49583
|
-
item.frozen = true;
|
|
49584
|
-
}
|
|
49585
|
-
}
|
|
49586
|
-
if (Math.abs(totalViolation) < 0.01) {
|
|
49587
|
-
unfrozen.forEach((item) => item.frozen = true);
|
|
49588
|
-
break;
|
|
49589
|
-
}
|
|
49590
|
-
freeSpace = containerMainSize - items.reduce((sum, item) => sum + item.mainSize, 0);
|
|
49591
|
-
}
|
|
49592
|
-
}
|
|
49593
|
-
function distributeMainAxis(items, containerSize, totalGap, gap, justifyContent) {
|
|
49594
|
-
if (items.length === 0) return;
|
|
49595
|
-
const totalItemSize = items.reduce((sum, item) => sum + item.mainSize, 0);
|
|
49596
|
-
const freeSpace = containerSize - totalItemSize - totalGap;
|
|
49597
|
-
let position = 0;
|
|
49598
|
-
let itemGap = gap;
|
|
49599
|
-
let leadingSpace = 0;
|
|
49600
|
-
switch (justifyContent) {
|
|
49601
|
-
case "flex-start":
|
|
49602
|
-
leadingSpace = 0;
|
|
49603
|
-
break;
|
|
49604
|
-
case "flex-end":
|
|
49605
|
-
leadingSpace = freeSpace;
|
|
49606
|
-
break;
|
|
49607
|
-
case "center":
|
|
49608
|
-
leadingSpace = freeSpace / 2;
|
|
49609
|
-
break;
|
|
49610
|
-
case "space-between":
|
|
49611
|
-
leadingSpace = 0;
|
|
49612
|
-
if (items.length > 1) {
|
|
49613
|
-
itemGap = gap + freeSpace / (items.length - 1);
|
|
49614
|
-
}
|
|
49615
|
-
break;
|
|
49616
|
-
case "space-around":
|
|
49617
|
-
if (items.length > 0) {
|
|
49618
|
-
const spacePerItem = freeSpace / items.length;
|
|
49619
|
-
leadingSpace = spacePerItem / 2;
|
|
49620
|
-
itemGap = gap + spacePerItem;
|
|
49621
|
-
}
|
|
49622
|
-
break;
|
|
49623
|
-
case "space-evenly":
|
|
49624
|
-
if (items.length > 0) {
|
|
49625
|
-
const totalSpaces = items.length + 1;
|
|
49626
|
-
const spaceSize = freeSpace / totalSpaces;
|
|
49627
|
-
leadingSpace = spaceSize;
|
|
49628
|
-
itemGap = gap + spaceSize;
|
|
49629
|
-
}
|
|
49630
|
-
break;
|
|
49631
|
-
}
|
|
49632
|
-
position = leadingSpace;
|
|
49633
|
-
for (let i = 0; i < items.length; i++) {
|
|
49634
|
-
items[i].mainPosition = position;
|
|
49635
|
-
position += items[i].mainSize;
|
|
49636
|
-
if (i < items.length - 1) {
|
|
49637
|
-
position += itemGap;
|
|
49638
|
-
}
|
|
49639
|
-
}
|
|
49640
|
-
}
|
|
49641
|
-
function alignCrossAxis(items, containerCrossSize, alignItems) {
|
|
49642
|
-
for (const item of items) {
|
|
49643
|
-
const align = item.props.alignSelf ?? alignItems;
|
|
49644
|
-
const itemCrossSize = item.props.contentSize;
|
|
49645
|
-
item.crossSize = align === "stretch" ? containerCrossSize : itemCrossSize;
|
|
49646
|
-
switch (align) {
|
|
49647
|
-
case "flex-start":
|
|
49648
|
-
item.crossPosition = 0;
|
|
49649
|
-
break;
|
|
49650
|
-
case "flex-end":
|
|
49651
|
-
item.crossPosition = containerCrossSize - item.crossSize;
|
|
49652
|
-
break;
|
|
49653
|
-
case "center":
|
|
49654
|
-
item.crossPosition = (containerCrossSize - item.crossSize) / 2;
|
|
49655
|
-
break;
|
|
49656
|
-
case "stretch":
|
|
49657
|
-
item.crossPosition = 0;
|
|
49658
|
-
item.crossSize = containerCrossSize;
|
|
49659
|
-
break;
|
|
49660
|
-
case "baseline":
|
|
49661
|
-
item.crossPosition = 0;
|
|
49662
|
-
break;
|
|
49663
|
-
}
|
|
49664
|
-
}
|
|
49665
|
-
}
|
|
49666
|
-
function clamp(value, min, max) {
|
|
49667
|
-
return Math.max(min, Math.min(max, value));
|
|
49668
|
-
}
|
|
49669
|
-
function toJustifyContent(justify) {
|
|
49670
|
-
switch (justify) {
|
|
49671
|
-
case "start":
|
|
49672
|
-
return "flex-start";
|
|
49673
|
-
case "end":
|
|
49674
|
-
return "flex-end";
|
|
49675
|
-
case "center":
|
|
49676
|
-
return "center";
|
|
49677
|
-
case "between":
|
|
49678
|
-
return "space-between";
|
|
49679
|
-
case "around":
|
|
49680
|
-
return "space-around";
|
|
49681
|
-
case "evenly":
|
|
49682
|
-
return "space-evenly";
|
|
49683
|
-
default:
|
|
49684
|
-
return "flex-start";
|
|
49685
|
-
}
|
|
49686
|
-
}
|
|
49687
|
-
function toAlignItems(align) {
|
|
49688
|
-
switch (align) {
|
|
49689
|
-
case "start":
|
|
49690
|
-
return "flex-start";
|
|
49691
|
-
case "end":
|
|
49692
|
-
return "flex-end";
|
|
49693
|
-
case "center":
|
|
49694
|
-
return "center";
|
|
49695
|
-
case "stretch":
|
|
49696
|
-
return "stretch";
|
|
49697
|
-
case "baseline":
|
|
49698
|
-
return "baseline";
|
|
49699
|
-
default:
|
|
49700
|
-
return "stretch";
|
|
49701
|
-
}
|
|
49702
|
-
}
|
|
49703
|
-
function createFlexItemProps(contentSize, options = {}) {
|
|
49704
|
-
return {
|
|
49705
|
-
basis: options.basis ?? "auto",
|
|
49706
|
-
grow: options.grow ?? 0,
|
|
49707
|
-
shrink: options.shrink ?? 1,
|
|
49708
|
-
minSize: options.minSize ?? 0,
|
|
49709
|
-
maxSize: options.maxSize ?? Infinity,
|
|
49710
|
-
contentSize,
|
|
49711
|
-
alignSelf: options.alignSelf
|
|
49712
|
-
};
|
|
49713
|
-
}
|
|
49714
|
-
function createFlexGrowItemProps(contentSize, options = {}) {
|
|
49715
|
-
return {
|
|
49716
|
-
basis: options.basis ?? 0,
|
|
49717
|
-
grow: options.grow ?? 1,
|
|
49718
|
-
shrink: options.shrink ?? 1,
|
|
49719
|
-
minSize: options.minSize ?? 0,
|
|
49720
|
-
maxSize: options.maxSize ?? Infinity,
|
|
49721
|
-
contentSize,
|
|
49722
|
-
alignSelf: options.alignSelf
|
|
49723
|
-
};
|
|
49724
|
-
}
|
|
49725
|
-
|
|
49726
|
-
// src/renderer/svg/index.ts
|
|
49727
|
-
var SvgRenderer = class {
|
|
49728
|
-
options;
|
|
49729
|
-
theme;
|
|
49730
|
-
pageWidth = 0;
|
|
49731
|
-
pageHeight = 0;
|
|
49732
|
-
clipPathDefs = [];
|
|
49733
|
-
clipPathCounter = 0;
|
|
49734
|
-
// Default spacing values
|
|
49735
|
-
DEFAULT_GAP = 16;
|
|
49736
|
-
constructor(options = {}) {
|
|
49737
|
-
this.options = {
|
|
49738
|
-
width: options.width ?? 800,
|
|
49739
|
-
height: options.height ?? 600,
|
|
49740
|
-
scale: options.scale ?? 1,
|
|
49741
|
-
background: options.background ?? "#ffffff",
|
|
49742
|
-
padding: options.padding ?? 20,
|
|
49743
|
-
fontFamily: options.fontFamily ?? "system-ui, -apple-system, sans-serif"
|
|
49744
|
-
};
|
|
49745
|
-
this.theme = defaultTheme;
|
|
49746
|
-
}
|
|
49747
|
-
/**
|
|
49748
|
-
* Render a wireframe document to SVG
|
|
49749
|
-
*/
|
|
49750
|
-
render(doc) {
|
|
49751
|
-
this.clipPathDefs = [];
|
|
49752
|
-
this.clipPathCounter = 0;
|
|
49753
|
-
const firstPage = doc.children[0];
|
|
49754
|
-
let width = this.options.width;
|
|
49755
|
-
let height = this.options.height;
|
|
49756
|
-
if (firstPage) {
|
|
49757
|
-
const pageAny = firstPage;
|
|
49758
|
-
const hasExplicitWidth = pageAny.width !== void 0;
|
|
49759
|
-
const hasExplicitHeight = pageAny.height !== void 0;
|
|
49760
|
-
if (hasExplicitWidth || hasExplicitHeight) {
|
|
49761
|
-
if (hasExplicitWidth) {
|
|
49762
|
-
width = pageAny.width;
|
|
49763
|
-
}
|
|
49764
|
-
if (hasExplicitHeight) {
|
|
49765
|
-
height = pageAny.height;
|
|
49766
|
-
}
|
|
49767
|
-
} else if (firstPage.viewport !== void 0 || firstPage.device !== void 0) {
|
|
49768
|
-
const viewport = resolveViewport(firstPage.viewport, firstPage.device);
|
|
49769
|
-
width = viewport.width;
|
|
49770
|
-
height = viewport.height;
|
|
49771
|
-
}
|
|
49772
|
-
}
|
|
49773
|
-
this.pageWidth = width;
|
|
49774
|
-
this.pageHeight = height;
|
|
49775
|
-
const content = doc.children.map((page) => this.renderPage(page)).join("\n");
|
|
49776
|
-
const allDefs = this.generateDefs() + "\n" + this.clipPathDefs.join("\n");
|
|
49777
|
-
const svg = `<?xml version="1.0" encoding="UTF-8"?>
|
|
49778
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" width="${width}" height="${height}">
|
|
49779
|
-
<defs>
|
|
49780
|
-
${allDefs}
|
|
49781
|
-
</defs>
|
|
49782
|
-
<rect width="100%" height="100%" fill="${this.options.background}"/>
|
|
49783
|
-
<g transform="scale(${this.options.scale})">
|
|
49784
|
-
${content}
|
|
49785
|
-
</g>
|
|
49786
|
-
</svg>`;
|
|
49787
|
-
return { svg, width, height };
|
|
49788
|
-
}
|
|
49789
|
-
/**
|
|
49790
|
-
* Generate SVG defs (styles)
|
|
49791
|
-
*/
|
|
49792
|
-
generateDefs() {
|
|
49793
|
-
return `
|
|
49794
|
-
<style>
|
|
49795
|
-
text { font-family: ${this.options.fontFamily}; }
|
|
49796
|
-
.wf-title { font-weight: 600; }
|
|
49797
|
-
.wf-muted { fill: ${this.theme.colors.muted}; }
|
|
49798
|
-
</style>
|
|
49799
|
-
`;
|
|
49800
|
-
}
|
|
49801
|
-
// ===========================================
|
|
49802
|
-
// Page Layout
|
|
49803
|
-
// ===========================================
|
|
49804
|
-
renderPage(page) {
|
|
49805
|
-
const padding = this.options.padding;
|
|
49806
|
-
const contentWidth = this.pageWidth - padding * 2;
|
|
49807
|
-
const contentHeight = this.pageHeight - padding * 2;
|
|
49808
|
-
const constraints = {
|
|
49809
|
-
maxWidth: contentWidth,
|
|
49810
|
-
maxHeight: contentHeight
|
|
49811
|
-
};
|
|
49812
|
-
const childBoxes = [];
|
|
49813
|
-
let currentY = padding;
|
|
49814
|
-
const isCentered = page.centered === true;
|
|
49815
|
-
const hasHeader = page.children.some((c) => c.type === "Header");
|
|
49816
|
-
const hasFooter = page.children.some((c) => c.type === "Footer");
|
|
49817
|
-
const hasMain = page.children.some((c) => c.type === "Main");
|
|
49818
|
-
if (hasHeader || hasFooter || hasMain) {
|
|
49819
|
-
return this.renderPageWithFixedLayout(page, padding, contentWidth, contentHeight);
|
|
49820
|
-
}
|
|
49821
|
-
const measurements = page.children.map((child) => this.measureNode(child, constraints));
|
|
49822
|
-
const gap = this.getGap(page) || this.DEFAULT_GAP;
|
|
49823
|
-
const totalChildrenHeight = measurements.reduce((sum, m, i) => {
|
|
49824
|
-
return sum + m.height + (i > 0 ? gap : 0);
|
|
49825
|
-
}, 0);
|
|
49826
|
-
if (isCentered) {
|
|
49827
|
-
const availableHeight = contentHeight;
|
|
49828
|
-
currentY = padding + Math.max(0, (availableHeight - totalChildrenHeight) / 2);
|
|
49829
|
-
}
|
|
49830
|
-
for (let i = 0; i < page.children.length; i++) {
|
|
49831
|
-
const child = page.children[i];
|
|
49832
|
-
const measurement = measurements[i];
|
|
49833
|
-
let childX = padding;
|
|
49834
|
-
if (isCentered || this.shouldCenterHorizontally(child)) {
|
|
49835
|
-
childX = padding + (contentWidth - measurement.width) / 2;
|
|
49836
|
-
}
|
|
49837
|
-
const box = this.layoutNode(child, childX, currentY, constraints);
|
|
49838
|
-
childBoxes.push(box);
|
|
49839
|
-
currentY += box.height + gap;
|
|
49840
|
-
}
|
|
49841
|
-
const elements = [];
|
|
49842
|
-
for (const box of childBoxes) {
|
|
49843
|
-
elements.push(this.renderBox(box));
|
|
49844
|
-
}
|
|
49845
|
-
return elements.join("\n");
|
|
49846
|
-
}
|
|
49847
|
-
/**
|
|
49848
|
-
* Render page with fixed header/footer layout
|
|
49849
|
-
* Header at top, Footer at bottom, Main fills remaining space
|
|
49850
|
-
*/
|
|
49851
|
-
renderPageWithFixedLayout(page, padding, contentWidth, contentHeight) {
|
|
49852
|
-
const constraints = {
|
|
49853
|
-
maxWidth: contentWidth,
|
|
49854
|
-
maxHeight: contentHeight
|
|
49855
|
-
};
|
|
49856
|
-
const header = page.children.find((c) => c.type === "Header");
|
|
49857
|
-
const footer = page.children.find((c) => c.type === "Footer");
|
|
49858
|
-
const otherChildren = page.children.filter((c) => c.type !== "Header" && c.type !== "Footer");
|
|
49859
|
-
const elements = [];
|
|
49860
|
-
let headerHeight = 0;
|
|
49861
|
-
let footerHeight = 0;
|
|
49862
|
-
let currentY = padding;
|
|
49863
|
-
if (header) {
|
|
49864
|
-
const headerMeasure = this.measureNode(header, constraints);
|
|
49865
|
-
headerHeight = headerMeasure.height;
|
|
49866
|
-
const headerBox = this.layoutNode(header, padding, currentY, constraints);
|
|
49867
|
-
elements.push(this.renderBox(headerBox));
|
|
49868
|
-
}
|
|
49869
|
-
if (footer) {
|
|
49870
|
-
const footerMeasure = this.measureNode(footer, constraints);
|
|
49871
|
-
footerHeight = footerMeasure.height;
|
|
49872
|
-
const footerY = this.pageHeight - padding - footerHeight;
|
|
49873
|
-
const footerBox = this.layoutNode(footer, padding, footerY, constraints);
|
|
49874
|
-
elements.push(this.renderBox(footerBox));
|
|
49875
|
-
}
|
|
49876
|
-
const mainStartY = currentY + headerHeight;
|
|
49877
|
-
const mainEndY = this.pageHeight - padding - footerHeight;
|
|
49878
|
-
const mainHeight = mainEndY - mainStartY;
|
|
49879
|
-
if (otherChildren.length > 0) {
|
|
49880
|
-
const mainConstraints = {
|
|
49881
|
-
maxWidth: contentWidth,
|
|
49882
|
-
maxHeight: mainHeight
|
|
49883
|
-
};
|
|
49884
|
-
const clipId = `main-clip-${this.clipPathCounter++}`;
|
|
49885
|
-
this.clipPathDefs.push(`<clipPath id="${clipId}"><rect x="${padding}" y="${mainStartY}" width="${contentWidth}" height="${mainHeight}"/></clipPath>`);
|
|
49886
|
-
const mainContent = [];
|
|
49887
|
-
mainContent.push(`<g clip-path="url(#${clipId})">`);
|
|
49888
|
-
let childY = mainStartY;
|
|
49889
|
-
const gap = this.getGap(page) || 0;
|
|
49890
|
-
for (const child of otherChildren) {
|
|
49891
|
-
const childBox = this.layoutNode(child, padding, childY, mainConstraints);
|
|
49892
|
-
mainContent.push(this.renderBox(childBox));
|
|
49893
|
-
childY += childBox.height + gap;
|
|
49894
|
-
}
|
|
49895
|
-
mainContent.push(`</g>`);
|
|
49896
|
-
elements.push(mainContent.join("\n"));
|
|
49897
|
-
}
|
|
49898
|
-
return elements.join("\n");
|
|
49899
|
-
}
|
|
49900
|
-
shouldCenterHorizontally(node) {
|
|
49901
|
-
return node.type === "Card" || node.type === "Modal";
|
|
49902
|
-
}
|
|
49903
|
-
// ===========================================
|
|
49904
|
-
// Measurement Phase
|
|
49905
|
-
// ===========================================
|
|
49906
|
-
measureNode(node, constraints) {
|
|
49907
|
-
switch (node.type) {
|
|
49908
|
-
case "Row":
|
|
49909
|
-
return this.measureRow(node, constraints);
|
|
49910
|
-
case "Col":
|
|
49911
|
-
return this.measureCol(node, constraints);
|
|
49912
|
-
case "Header":
|
|
49913
|
-
return this.measureHeader(node, constraints);
|
|
49914
|
-
case "Footer":
|
|
49915
|
-
return this.measureFooter(node, constraints);
|
|
49916
|
-
case "Main":
|
|
49917
|
-
return this.measureMain(node, constraints);
|
|
49918
|
-
case "Sidebar":
|
|
49919
|
-
return this.measureSidebar(node, constraints);
|
|
49920
|
-
case "Card":
|
|
49921
|
-
return this.measureCard(node, constraints);
|
|
49922
|
-
case "Modal":
|
|
49923
|
-
return this.measureModal(node, constraints);
|
|
49924
|
-
case "Title":
|
|
49925
|
-
return this.measureTitle(node);
|
|
49926
|
-
case "Text":
|
|
49927
|
-
return this.measureText(node);
|
|
49928
|
-
case "Button":
|
|
49929
|
-
return this.measureButton(node, constraints);
|
|
49930
|
-
case "Input":
|
|
49931
|
-
return this.measureInput(node, constraints);
|
|
49932
|
-
case "Textarea":
|
|
49933
|
-
return this.measureTextarea(node, constraints);
|
|
49934
|
-
case "Select":
|
|
49935
|
-
return this.measureSelect(node, constraints);
|
|
49936
|
-
case "Checkbox":
|
|
49937
|
-
return this.measureCheckbox(node);
|
|
49938
|
-
case "Radio":
|
|
49939
|
-
return this.measureRadio(node);
|
|
49940
|
-
case "Switch":
|
|
49941
|
-
return this.measureSwitch(node);
|
|
49942
|
-
case "Link":
|
|
49943
|
-
return this.measureLink(node);
|
|
49944
|
-
case "Image":
|
|
49945
|
-
return this.measureImage(node, constraints);
|
|
49946
|
-
case "Placeholder":
|
|
49947
|
-
return this.measurePlaceholder(node, constraints);
|
|
49948
|
-
case "Avatar":
|
|
49949
|
-
return this.measureAvatar(node, constraints);
|
|
49950
|
-
case "Badge":
|
|
49951
|
-
return this.measureBadge(node);
|
|
49952
|
-
case "Table":
|
|
49953
|
-
return this.measureTable(node);
|
|
49954
|
-
case "List":
|
|
49955
|
-
return this.measureList(node);
|
|
49956
|
-
case "Alert":
|
|
49957
|
-
return this.measureAlert(node, constraints);
|
|
49958
|
-
case "Progress":
|
|
49959
|
-
return this.measureProgress(node, constraints);
|
|
49960
|
-
case "Spinner":
|
|
49961
|
-
return this.measureSpinner(node);
|
|
49962
|
-
case "Nav":
|
|
49963
|
-
return this.measureNav(node);
|
|
49964
|
-
case "Tabs":
|
|
49965
|
-
return this.measureTabs(node);
|
|
49966
|
-
case "Breadcrumb":
|
|
49967
|
-
return this.measureBreadcrumb(node);
|
|
49968
|
-
case "Icon":
|
|
49969
|
-
return this.measureIcon(node);
|
|
49970
|
-
case "Divider":
|
|
49971
|
-
return this.measureDivider(node, constraints);
|
|
49972
|
-
default:
|
|
49973
|
-
return { width: 100, height: 40 };
|
|
49974
|
-
}
|
|
49975
|
-
}
|
|
49976
|
-
measureRow(node, constraints) {
|
|
49977
|
-
const padding = this.getPadding(node);
|
|
49978
|
-
const gap = this.getGap(node) ?? this.DEFAULT_GAP;
|
|
49979
|
-
const innerWidth = constraints.maxWidth - padding.left - padding.right;
|
|
49980
|
-
const childMeasurements = node.children.map(
|
|
49981
|
-
(child) => this.measureNode(child, { ...constraints, maxWidth: innerWidth })
|
|
49982
|
-
);
|
|
49983
|
-
const maxChildHeight = Math.max(...childMeasurements.map((m) => m.height), 0);
|
|
49984
|
-
const totalChildWidth = childMeasurements.reduce((sum, m) => sum + m.width, 0);
|
|
49985
|
-
const totalGapWidth = Math.max(0, (node.children.length - 1) * gap);
|
|
49986
|
-
const contentWidth = totalChildWidth + totalGapWidth + padding.left + padding.right;
|
|
49987
|
-
const hasExplicitWidth = "w" in node && node.w !== void 0;
|
|
49988
|
-
const width = hasExplicitWidth ? constraints.maxWidth : Math.min(contentWidth, constraints.maxWidth);
|
|
49989
|
-
return {
|
|
49990
|
-
width,
|
|
49991
|
-
height: maxChildHeight + padding.top + padding.bottom
|
|
49992
|
-
};
|
|
49993
|
-
}
|
|
49994
|
-
measureCol(node, constraints) {
|
|
49995
|
-
const gap = this.getGap(node) ?? this.DEFAULT_GAP;
|
|
49996
|
-
const padding = this.getPadding(node);
|
|
49997
|
-
const innerWidth = constraints.maxWidth - padding.left - padding.right;
|
|
49998
|
-
const childMeasurements = node.children.map(
|
|
49999
|
-
(child) => this.measureNode(child, { ...constraints, maxWidth: innerWidth })
|
|
50000
|
-
);
|
|
50001
|
-
const totalHeight = childMeasurements.reduce(
|
|
50002
|
-
(sum, m, i) => sum + m.height + (i > 0 ? gap : 0),
|
|
50003
|
-
0
|
|
50004
|
-
);
|
|
50005
|
-
const maxChildWidth = Math.max(...childMeasurements.map((m) => m.width), 0);
|
|
50006
|
-
return {
|
|
50007
|
-
width: Math.max(maxChildWidth + padding.left + padding.right, constraints.maxWidth),
|
|
50008
|
-
height: totalHeight + padding.top + padding.bottom
|
|
50009
|
-
};
|
|
50010
|
-
}
|
|
50011
|
-
measureHeader(node, constraints) {
|
|
50012
|
-
const padding = this.getPadding(node);
|
|
50013
|
-
const height = this.resolveSize(node.h) || 56;
|
|
50014
|
-
return {
|
|
50015
|
-
width: constraints.maxWidth,
|
|
50016
|
-
height: height + padding.top + padding.bottom
|
|
50017
|
-
};
|
|
50018
|
-
}
|
|
50019
|
-
measureFooter(node, constraints) {
|
|
50020
|
-
const padding = this.getPadding(node);
|
|
50021
|
-
const height = this.resolveSize(node.h) || 60;
|
|
50022
|
-
return {
|
|
50023
|
-
width: constraints.maxWidth,
|
|
50024
|
-
height: height + padding.top + padding.bottom
|
|
50025
|
-
};
|
|
50026
|
-
}
|
|
50027
|
-
measureMain(node, constraints) {
|
|
50028
|
-
const padding = this.getPadding(node);
|
|
50029
|
-
const gap = this.getGap(node) ?? this.DEFAULT_GAP;
|
|
50030
|
-
const innerWidth = constraints.maxWidth - padding.left - padding.right;
|
|
50031
|
-
const childMeasurements = node.children.map(
|
|
50032
|
-
(child) => this.measureNode(child, { ...constraints, maxWidth: innerWidth })
|
|
50033
|
-
);
|
|
50034
|
-
const totalHeight = childMeasurements.reduce(
|
|
50035
|
-
(sum, m, i) => sum + m.height + (i > 0 ? gap : 0),
|
|
50036
|
-
0
|
|
50037
|
-
);
|
|
50038
|
-
return {
|
|
50039
|
-
width: constraints.maxWidth,
|
|
50040
|
-
height: totalHeight + padding.top + padding.bottom
|
|
50041
|
-
};
|
|
50042
|
-
}
|
|
50043
|
-
measureSidebar(node, constraints) {
|
|
50044
|
-
const width = this.resolveSize(node.w) || 200;
|
|
50045
|
-
const padding = this.getPadding(node);
|
|
50046
|
-
const gap = this.getGap(node) ?? 8;
|
|
50047
|
-
const innerWidth = width - padding.left - padding.right;
|
|
50048
|
-
const childMeasurements = node.children.map(
|
|
50049
|
-
(child) => this.measureNode(child, { ...constraints, maxWidth: innerWidth })
|
|
50050
|
-
);
|
|
50051
|
-
const contentHeight = childMeasurements.reduce(
|
|
50052
|
-
(sum, m, i) => sum + m.height + (i > 0 ? gap : 0),
|
|
50053
|
-
0
|
|
50054
|
-
) + padding.top + padding.bottom;
|
|
50055
|
-
const explicitHeight = this.resolveSize(node.h);
|
|
50056
|
-
const height = explicitHeight || constraints.maxHeight || contentHeight;
|
|
50057
|
-
return { width, height };
|
|
50058
|
-
}
|
|
50059
|
-
measureCard(node, constraints) {
|
|
50060
|
-
let cardWidth = this.resolveSize(node.w);
|
|
50061
|
-
if (!cardWidth) {
|
|
50062
|
-
cardWidth = Math.min(360, constraints.maxWidth);
|
|
50063
|
-
} else {
|
|
50064
|
-
cardWidth = Math.min(cardWidth, constraints.maxWidth);
|
|
50065
|
-
}
|
|
50066
|
-
const explicitHeight = this.resolveSize(node.h);
|
|
50067
|
-
if (explicitHeight) {
|
|
50068
|
-
return { width: cardWidth, height: explicitHeight };
|
|
50069
|
-
}
|
|
50070
|
-
const padding = this.getPadding(node);
|
|
50071
|
-
const gap = this.getGap(node) ?? this.DEFAULT_GAP;
|
|
50072
|
-
const innerWidth = cardWidth - padding.left - padding.right;
|
|
50073
|
-
const childMeasurements = node.children.map(
|
|
50074
|
-
(child) => this.measureNode(child, { ...constraints, maxWidth: innerWidth })
|
|
50075
|
-
);
|
|
50076
|
-
let contentHeight = 0;
|
|
50077
|
-
if (node.title) {
|
|
50078
|
-
contentHeight += 28;
|
|
50079
|
-
}
|
|
50080
|
-
contentHeight += childMeasurements.reduce(
|
|
50081
|
-
(sum, m, i) => sum + m.height + (i > 0 ? gap : 0),
|
|
50082
|
-
0
|
|
50083
|
-
);
|
|
50084
|
-
return {
|
|
50085
|
-
width: cardWidth,
|
|
50086
|
-
height: contentHeight + padding.top + padding.bottom
|
|
50087
|
-
};
|
|
50088
|
-
}
|
|
50089
|
-
measureModal(node, constraints) {
|
|
50090
|
-
const width = this.resolveSize(node.w) || 400;
|
|
50091
|
-
const padding = this.getPadding(node);
|
|
50092
|
-
const gap = this.getGap(node) ?? this.DEFAULT_GAP;
|
|
50093
|
-
const innerWidth = width - padding.left - padding.right;
|
|
50094
|
-
const childMeasurements = node.children.map(
|
|
50095
|
-
(child) => this.measureNode(child, { ...constraints, maxWidth: innerWidth })
|
|
50096
|
-
);
|
|
50097
|
-
let contentHeight = node.title ? 40 : 0;
|
|
50098
|
-
contentHeight += childMeasurements.reduce(
|
|
50099
|
-
(sum, m, i) => sum + m.height + (i > 0 ? gap : 0),
|
|
50100
|
-
0
|
|
50101
|
-
);
|
|
50102
|
-
return {
|
|
50103
|
-
width,
|
|
50104
|
-
height: contentHeight + padding.top + padding.bottom
|
|
50105
|
-
};
|
|
50106
|
-
}
|
|
50107
|
-
measureTitle(node) {
|
|
50108
|
-
const level = node.level || 1;
|
|
50109
|
-
const fontSize = this.getTitleFontSize(level);
|
|
50110
|
-
const textWidth = this.estimateTextWidth(node.content, fontSize);
|
|
50111
|
-
return { width: textWidth, height: fontSize + 8 };
|
|
50112
|
-
}
|
|
50113
|
-
measureText(node) {
|
|
50114
|
-
const fontSize = this.resolveFontSize(node.size);
|
|
50115
|
-
const textWidth = this.estimateTextWidth(node.content, fontSize);
|
|
50116
|
-
return { width: textWidth, height: fontSize + 8 };
|
|
50117
|
-
}
|
|
50118
|
-
measureButton(node, constraints) {
|
|
50119
|
-
const hasIcon = !!node.icon;
|
|
50120
|
-
const isIconOnly = hasIcon && !node.content.trim();
|
|
50121
|
-
const iconSize = 16;
|
|
50122
|
-
const padding = 16;
|
|
50123
|
-
let width;
|
|
50124
|
-
if (this.isFullWidth(node)) {
|
|
50125
|
-
width = constraints.maxWidth;
|
|
50126
|
-
} else if (isIconOnly) {
|
|
50127
|
-
width = iconSize + padding * 2;
|
|
50128
|
-
} else if (hasIcon) {
|
|
50129
|
-
width = Math.max(80, this.estimateTextWidth(node.content, 14) + iconSize + 48);
|
|
50130
|
-
} else {
|
|
50131
|
-
width = Math.max(80, this.estimateTextWidth(node.content, 14) + 32);
|
|
50132
|
-
}
|
|
50133
|
-
return { width, height: 40 };
|
|
50134
|
-
}
|
|
50135
|
-
measureInput(node, constraints) {
|
|
50136
|
-
let width;
|
|
50137
|
-
if (this.resolveSize(node.w)) {
|
|
50138
|
-
width = this.resolveSize(node.w);
|
|
50139
|
-
} else if (constraints.inHeader) {
|
|
50140
|
-
const placeholderWidth = node.placeholder ? this.estimateTextWidth(node.placeholder, 14) : 60;
|
|
50141
|
-
width = Math.max(120, placeholderWidth + 24 + 100);
|
|
50142
|
-
} else {
|
|
50143
|
-
width = constraints.maxWidth;
|
|
50144
|
-
}
|
|
50145
|
-
let height = 36;
|
|
50146
|
-
if (node.label) height += 24;
|
|
50147
|
-
return { width, height };
|
|
50148
|
-
}
|
|
50149
|
-
measureTextarea(node, constraints) {
|
|
50150
|
-
const width = this.resolveSize(node.w) || constraints.maxWidth;
|
|
50151
|
-
let height = node.rows ? node.rows * 24 : 100;
|
|
50152
|
-
if (node.label) height += 24;
|
|
50153
|
-
return { width, height };
|
|
50154
|
-
}
|
|
50155
|
-
measureSelect(node, constraints) {
|
|
50156
|
-
const width = this.resolveSize(node.w) || constraints.maxWidth;
|
|
50157
|
-
let height = 40;
|
|
50158
|
-
if (node.label) height += 24;
|
|
50159
|
-
return { width, height };
|
|
50160
|
-
}
|
|
50161
|
-
measureCheckbox(node) {
|
|
50162
|
-
const labelWidth = node.label ? this.estimateTextWidth(node.label, 14) + 8 : 0;
|
|
50163
|
-
return { width: 18 + labelWidth, height: 24 };
|
|
50164
|
-
}
|
|
50165
|
-
measureRadio(node) {
|
|
50166
|
-
const labelWidth = node.label ? this.estimateTextWidth(node.label, 14) + 8 : 0;
|
|
50167
|
-
return { width: 18 + labelWidth, height: 24 };
|
|
50168
|
-
}
|
|
50169
|
-
measureSwitch(node) {
|
|
50170
|
-
const labelWidth = node.label ? this.estimateTextWidth(node.label, 14) + 8 : 0;
|
|
50171
|
-
return { width: 44 + labelWidth, height: 28 };
|
|
50172
|
-
}
|
|
50173
|
-
measureLink(node) {
|
|
50174
|
-
const fontSize = 14;
|
|
50175
|
-
const textWidth = this.estimateTextWidth(node.content, fontSize);
|
|
50176
|
-
return { width: textWidth, height: fontSize + 8 };
|
|
50177
|
-
}
|
|
50178
|
-
measureImage(node, constraints) {
|
|
50179
|
-
let width;
|
|
50180
|
-
if (this.isFullWidth(node)) {
|
|
50181
|
-
width = constraints.maxWidth;
|
|
50182
|
-
} else {
|
|
50183
|
-
width = this.resolveSize(node.w) || 200;
|
|
50184
|
-
}
|
|
50185
|
-
const height = this.resolveSize(node.h) || 150;
|
|
50186
|
-
return { width, height };
|
|
50187
|
-
}
|
|
50188
|
-
measurePlaceholder(node, constraints) {
|
|
50189
|
-
let width;
|
|
50190
|
-
if (node.w !== void 0) {
|
|
50191
|
-
width = this.isFullWidth(node) ? constraints.maxWidth : this.resolveSize(node.w) || 200;
|
|
50192
|
-
} else {
|
|
50193
|
-
width = constraints.maxWidth || 200;
|
|
50194
|
-
}
|
|
50195
|
-
const height = this.resolveSize(node.h) || 100;
|
|
50196
|
-
return { width, height };
|
|
50197
|
-
}
|
|
50198
|
-
measureAvatar(node, constraints) {
|
|
50199
|
-
const sizes = { xs: 24, sm: 32, md: 40, lg: 48, xl: 64 };
|
|
50200
|
-
const defaultSize = constraints?.inHeader ? "sm" : "md";
|
|
50201
|
-
const size = sizes[node.size || defaultSize] || 40;
|
|
50202
|
-
return { width: size, height: size };
|
|
50203
|
-
}
|
|
50204
|
-
measureBadge(node) {
|
|
50205
|
-
const width = Math.max(24, this.estimateTextWidth(node.content, 12) + 16);
|
|
50206
|
-
return { width, height: 22 };
|
|
50207
|
-
}
|
|
50208
|
-
measureTable(node) {
|
|
50209
|
-
const columns = node.columns || [];
|
|
50210
|
-
const rows = node.rows || [];
|
|
50211
|
-
const rowCount = rows.length || 3;
|
|
50212
|
-
const colWidth = 120;
|
|
50213
|
-
const rowHeight = 40;
|
|
50214
|
-
return {
|
|
50215
|
-
width: columns.length * colWidth,
|
|
50216
|
-
height: (rowCount + 1) * rowHeight
|
|
50217
|
-
};
|
|
50218
|
-
}
|
|
50219
|
-
measureList(node) {
|
|
50220
|
-
const items = node.items || [];
|
|
50221
|
-
const maxItemWidth = Math.max(...items.map((item) => {
|
|
50222
|
-
const content = typeof item === "string" ? item : item.content;
|
|
50223
|
-
return this.estimateTextWidth(content, 14);
|
|
50224
|
-
}), 100);
|
|
50225
|
-
return { width: maxItemWidth + 24, height: items.length * 28 };
|
|
50226
|
-
}
|
|
50227
|
-
measureAlert(_node, constraints) {
|
|
50228
|
-
const width = Math.min(400, constraints.maxWidth);
|
|
50229
|
-
return { width, height: 48 };
|
|
50230
|
-
}
|
|
50231
|
-
measureProgress(node, constraints) {
|
|
50232
|
-
const width = Math.min(200, constraints.maxWidth);
|
|
50233
|
-
let height = 8;
|
|
50234
|
-
if (node.label) height += 24;
|
|
50235
|
-
return { width, height };
|
|
50236
|
-
}
|
|
50237
|
-
measureSpinner(node) {
|
|
50238
|
-
const sizes = { xs: 16, sm: 20, md: 24, lg: 32, xl: 40 };
|
|
50239
|
-
const size = sizes[node.size || "md"] || 24;
|
|
50240
|
-
return { width: size, height: size };
|
|
50241
|
-
}
|
|
50242
|
-
measureNav(node) {
|
|
50243
|
-
const items = node.items || [];
|
|
50244
|
-
if (node.vertical) {
|
|
50245
|
-
const maxWidth = Math.max(...items.map((item) => {
|
|
50246
|
-
const label = typeof item === "string" ? item : item.label;
|
|
50247
|
-
return this.estimateTextWidth(label, 14);
|
|
50248
|
-
}), 100);
|
|
50249
|
-
return { width: maxWidth, height: items.length * 32 };
|
|
50250
|
-
} else {
|
|
50251
|
-
const totalWidth = items.reduce((sum, item) => {
|
|
50252
|
-
const label = typeof item === "string" ? item : item.label;
|
|
50253
|
-
return sum + this.estimateTextWidth(label, 14) + 24;
|
|
50254
|
-
}, 0);
|
|
50255
|
-
return { width: totalWidth, height: 32 };
|
|
50256
|
-
}
|
|
50257
|
-
}
|
|
50258
|
-
measureTabs(node) {
|
|
50259
|
-
const items = node.items || [];
|
|
50260
|
-
const totalWidth = items.reduce((sum, item) => {
|
|
50261
|
-
const label = typeof item === "string" ? item : item;
|
|
50262
|
-
return sum + this.estimateTextWidth(label, 14) + 32;
|
|
50263
|
-
}, 0);
|
|
50264
|
-
return { width: totalWidth, height: 44 };
|
|
50265
|
-
}
|
|
50266
|
-
measureBreadcrumb(node) {
|
|
50267
|
-
const items = node.items || [];
|
|
50268
|
-
const totalWidth = items.reduce((sum, item, idx) => {
|
|
50269
|
-
const label = typeof item === "string" ? item : item.label;
|
|
50270
|
-
return sum + this.estimateTextWidth(label, 14) + (idx < items.length - 1 ? 24 : 0);
|
|
50271
|
-
}, 0);
|
|
50272
|
-
return { width: totalWidth, height: 28 };
|
|
50273
|
-
}
|
|
50274
|
-
measureIcon(node) {
|
|
50275
|
-
const sizes = { xs: 12, sm: 16, md: 20, lg: 24, xl: 32 };
|
|
50276
|
-
const size = sizes[node.size || "md"] || 20;
|
|
50277
|
-
return { width: size, height: size };
|
|
50278
|
-
}
|
|
50279
|
-
measureDivider(_node, constraints) {
|
|
50280
|
-
return { width: constraints.maxWidth, height: 1 };
|
|
50281
|
-
}
|
|
50282
|
-
// ===========================================
|
|
50283
|
-
// Layout Phase
|
|
50284
|
-
// ===========================================
|
|
50285
|
-
layoutNode(node, x, y, constraints) {
|
|
50286
|
-
switch (node.type) {
|
|
50287
|
-
case "Row":
|
|
50288
|
-
return this.layoutRow(node, x, y, constraints);
|
|
50289
|
-
case "Col":
|
|
50290
|
-
return this.layoutCol(node, x, y, constraints);
|
|
50291
|
-
case "Header":
|
|
50292
|
-
return this.layoutHeader(node, x, y, constraints);
|
|
50293
|
-
case "Footer":
|
|
50294
|
-
return this.layoutFooter(node, x, y, constraints);
|
|
50295
|
-
case "Main":
|
|
50296
|
-
return this.layoutMain(node, x, y, constraints);
|
|
50297
|
-
case "Sidebar":
|
|
50298
|
-
return this.layoutSidebar(node, x, y, constraints);
|
|
50299
|
-
case "Card":
|
|
50300
|
-
return this.layoutCard(node, x, y, constraints);
|
|
50301
|
-
default:
|
|
50302
|
-
const size = this.measureNode(node, constraints);
|
|
50303
|
-
return {
|
|
50304
|
-
x,
|
|
50305
|
-
y,
|
|
50306
|
-
width: size.width,
|
|
50307
|
-
height: size.height,
|
|
50308
|
-
node,
|
|
50309
|
-
children: []
|
|
50310
|
-
};
|
|
50311
|
-
}
|
|
50312
|
-
}
|
|
50313
|
-
layoutRow(node, x, y, constraints) {
|
|
50314
|
-
const gap = this.getGap(node) ?? this.DEFAULT_GAP;
|
|
50315
|
-
const padding = this.getPadding(node);
|
|
50316
|
-
const innerWidth = constraints.maxWidth - padding.left - padding.right;
|
|
50317
|
-
const justify = node.justify || "start";
|
|
50318
|
-
const align = node.align || (constraints.inHeader ? "center" : "start");
|
|
50319
|
-
const childMeasurements = node.children.map(
|
|
50320
|
-
(child) => this.measureNode(child, { ...constraints, maxWidth: innerWidth })
|
|
50321
|
-
);
|
|
50322
|
-
const flexItems = node.children.map((child, i) => {
|
|
50323
|
-
const measurement = childMeasurements[i];
|
|
50324
|
-
if ("w" in child && child.w !== void 0 && child.w !== "full") {
|
|
50325
|
-
const resolved = this.resolveSize(child.w);
|
|
50326
|
-
if (resolved !== void 0) {
|
|
50327
|
-
return createFlexItemProps(measurement.height, {
|
|
50328
|
-
basis: resolved,
|
|
50329
|
-
grow: 0,
|
|
50330
|
-
shrink: 0,
|
|
50331
|
-
minSize: resolved,
|
|
50332
|
-
maxSize: resolved,
|
|
50333
|
-
contentSize: measurement.width
|
|
50334
|
-
});
|
|
50335
|
-
}
|
|
50336
|
-
}
|
|
50337
|
-
if (this.isFlexContainer(child)) {
|
|
50338
|
-
return createFlexGrowItemProps(measurement.height, {
|
|
50339
|
-
basis: 0,
|
|
50340
|
-
grow: 1,
|
|
50341
|
-
shrink: 1,
|
|
50342
|
-
minSize: 0,
|
|
50343
|
-
maxSize: Infinity,
|
|
50344
|
-
contentSize: measurement.width
|
|
50345
|
-
});
|
|
50346
|
-
}
|
|
50347
|
-
if (constraints.inHeader && child.type === "Input") {
|
|
50348
|
-
return createFlexGrowItemProps(measurement.height, {
|
|
50349
|
-
basis: measurement.width,
|
|
50350
|
-
// auto = content size
|
|
50351
|
-
grow: 1,
|
|
50352
|
-
shrink: 1,
|
|
50353
|
-
minSize: 120,
|
|
50354
|
-
// min-width: 120px
|
|
50355
|
-
maxSize: Infinity,
|
|
50356
|
-
contentSize: measurement.width
|
|
50357
|
-
});
|
|
50358
|
-
}
|
|
50359
|
-
return createFlexItemProps(measurement.height, {
|
|
50360
|
-
basis: measurement.width,
|
|
50361
|
-
// auto = content size
|
|
50362
|
-
grow: 0,
|
|
50363
|
-
shrink: 1,
|
|
50364
|
-
minSize: 0,
|
|
50365
|
-
maxSize: Infinity,
|
|
50366
|
-
contentSize: measurement.width
|
|
50367
|
-
});
|
|
50368
|
-
});
|
|
50369
|
-
const flexConfig = {
|
|
50370
|
-
mainSize: innerWidth,
|
|
50371
|
-
crossSize: void 0,
|
|
50372
|
-
// Will use max child height
|
|
50373
|
-
direction: "row",
|
|
50374
|
-
justifyContent: toJustifyContent(justify),
|
|
50375
|
-
alignItems: toAlignItems(align),
|
|
50376
|
-
gap
|
|
50377
|
-
};
|
|
50378
|
-
const flexResult = computeFlexLayout(flexItems, flexConfig);
|
|
50379
|
-
const maxChildHeight = Math.max(...childMeasurements.map((m) => m.height), 0);
|
|
50380
|
-
const innerMaxHeight = constraints.maxHeight ? constraints.maxHeight - padding.top - padding.bottom : void 0;
|
|
50381
|
-
const effectiveHeight = innerMaxHeight || maxChildHeight;
|
|
50382
|
-
const rowHeight = effectiveHeight + padding.top + padding.bottom;
|
|
50383
|
-
const children = [];
|
|
50384
|
-
for (let i = 0; i < node.children.length; i++) {
|
|
50385
|
-
const child = node.children[i];
|
|
50386
|
-
const flexItem = flexResult.items[i];
|
|
50387
|
-
const measurement = childMeasurements[i];
|
|
50388
|
-
const childX = x + padding.left + flexItem.mainPosition;
|
|
50389
|
-
let childY = y + padding.top;
|
|
50390
|
-
switch (align) {
|
|
50391
|
-
case "center":
|
|
50392
|
-
childY = y + padding.top + (maxChildHeight - measurement.height) / 2;
|
|
50393
|
-
break;
|
|
50394
|
-
case "end":
|
|
50395
|
-
childY = y + padding.top + (maxChildHeight - measurement.height);
|
|
50396
|
-
break;
|
|
50397
|
-
}
|
|
50398
|
-
const childBox = this.layoutNode(child, childX, childY, {
|
|
50399
|
-
...constraints,
|
|
50400
|
-
maxWidth: flexItem.mainSize,
|
|
50401
|
-
maxHeight: effectiveHeight
|
|
50402
|
-
});
|
|
50403
|
-
children.push(childBox);
|
|
50404
|
-
}
|
|
50405
|
-
return {
|
|
50406
|
-
x,
|
|
50407
|
-
y,
|
|
50408
|
-
width: constraints.maxWidth,
|
|
50409
|
-
height: rowHeight,
|
|
50410
|
-
node,
|
|
50411
|
-
children,
|
|
50412
|
-
padding
|
|
50413
|
-
};
|
|
50414
|
-
}
|
|
50415
|
-
layoutCol(node, x, y, constraints) {
|
|
50416
|
-
const gap = this.getGap(node) ?? this.DEFAULT_GAP;
|
|
50417
|
-
const padding = this.getPadding(node);
|
|
50418
|
-
const innerWidth = constraints.maxWidth - padding.left - padding.right;
|
|
50419
|
-
const innerHeight = constraints.maxHeight ? constraints.maxHeight - padding.top - padding.bottom : void 0;
|
|
50420
|
-
const align = node.align || "stretch";
|
|
50421
|
-
const childMeasurements = node.children.map(
|
|
50422
|
-
(child) => this.measureNode(child, { ...constraints, maxWidth: innerWidth })
|
|
50423
|
-
);
|
|
50424
|
-
const flexItems = node.children.map((child, i) => {
|
|
50425
|
-
const measurement = childMeasurements[i];
|
|
50426
|
-
if ("h" in child && child.h !== void 0) {
|
|
50427
|
-
const resolved = this.resolveSize(child.h);
|
|
50428
|
-
if (resolved !== void 0) {
|
|
50429
|
-
return createFlexItemProps(measurement.width, {
|
|
50430
|
-
basis: resolved,
|
|
50431
|
-
grow: 0,
|
|
50432
|
-
shrink: 0,
|
|
50433
|
-
minSize: resolved,
|
|
50434
|
-
maxSize: resolved,
|
|
50435
|
-
contentSize: measurement.height
|
|
50436
|
-
});
|
|
50437
|
-
}
|
|
50438
|
-
}
|
|
50439
|
-
if (child.type === "Row" && this.rowContainsSidebarOrMain(child)) {
|
|
50440
|
-
return createFlexGrowItemProps(measurement.width, {
|
|
50441
|
-
basis: 0,
|
|
50442
|
-
grow: 1,
|
|
50443
|
-
shrink: 1,
|
|
50444
|
-
minSize: 0,
|
|
50445
|
-
maxSize: Infinity,
|
|
50446
|
-
contentSize: measurement.height
|
|
50447
|
-
});
|
|
50448
|
-
}
|
|
50449
|
-
return createFlexItemProps(measurement.width, {
|
|
50450
|
-
basis: measurement.height,
|
|
50451
|
-
// auto = content size
|
|
50452
|
-
grow: 0,
|
|
50453
|
-
shrink: 1,
|
|
50454
|
-
minSize: 0,
|
|
50455
|
-
maxSize: Infinity,
|
|
50456
|
-
contentSize: measurement.height
|
|
50457
|
-
});
|
|
50458
|
-
});
|
|
50459
|
-
const flexConfig = {
|
|
50460
|
-
mainSize: innerHeight ?? childMeasurements.reduce(
|
|
50461
|
-
(sum, m, i) => sum + m.height + (i > 0 ? gap : 0),
|
|
50462
|
-
0
|
|
50463
|
-
),
|
|
50464
|
-
crossSize: innerWidth,
|
|
50465
|
-
direction: "column",
|
|
50466
|
-
justifyContent: "flex-start",
|
|
50467
|
-
alignItems: toAlignItems(align),
|
|
50468
|
-
gap
|
|
50469
|
-
};
|
|
50470
|
-
const flexResult = computeFlexLayout(flexItems, flexConfig);
|
|
50471
|
-
const children = [];
|
|
50472
|
-
for (let i = 0; i < node.children.length; i++) {
|
|
50473
|
-
const child = node.children[i];
|
|
50474
|
-
const flexItem = flexResult.items[i];
|
|
50475
|
-
const measurement = childMeasurements[i];
|
|
50476
|
-
let childX = x + padding.left;
|
|
50477
|
-
let childWidth = align === "stretch" ? innerWidth : measurement.width;
|
|
50478
|
-
switch (align) {
|
|
50479
|
-
case "center":
|
|
50480
|
-
childX = x + padding.left + (innerWidth - measurement.width) / 2;
|
|
50481
|
-
break;
|
|
50482
|
-
case "end":
|
|
50483
|
-
childX = x + padding.left + (innerWidth - measurement.width);
|
|
50484
|
-
break;
|
|
50485
|
-
}
|
|
50486
|
-
const childY = y + padding.top + flexItem.mainPosition;
|
|
50487
|
-
const childBox = this.layoutNode(child, childX, childY, {
|
|
50488
|
-
...constraints,
|
|
50489
|
-
maxWidth: childWidth,
|
|
50490
|
-
maxHeight: flexItem.mainSize
|
|
50491
|
-
});
|
|
50492
|
-
children.push(childBox);
|
|
50493
|
-
}
|
|
50494
|
-
const totalHeight = flexResult.mainSizeUsed;
|
|
50495
|
-
return {
|
|
50496
|
-
x,
|
|
50497
|
-
y,
|
|
50498
|
-
width: constraints.maxWidth,
|
|
50499
|
-
height: totalHeight + padding.top + padding.bottom,
|
|
50500
|
-
node,
|
|
50501
|
-
children,
|
|
50502
|
-
padding
|
|
50503
|
-
};
|
|
50504
|
-
}
|
|
50505
|
-
rowContainsSidebarOrMain(row) {
|
|
50506
|
-
return row.children.some(
|
|
50507
|
-
(child) => child.type === "Sidebar" || child.type === "Main"
|
|
50508
|
-
);
|
|
50509
|
-
}
|
|
50510
|
-
layoutHeader(node, x, y, constraints) {
|
|
50511
|
-
const padding = this.getPadding(node);
|
|
50512
|
-
const height = this.resolveSize(node.h) || 56;
|
|
50513
|
-
const innerWidth = constraints.maxWidth - padding.left - padding.right;
|
|
50514
|
-
const children = [];
|
|
50515
|
-
let currentY = y + padding.top;
|
|
50516
|
-
for (const child of node.children) {
|
|
50517
|
-
const childBox = this.layoutNode(child, x + padding.left, currentY, {
|
|
50518
|
-
...constraints,
|
|
50519
|
-
maxWidth: innerWidth,
|
|
50520
|
-
maxHeight: void 0,
|
|
50521
|
-
// Children use natural height
|
|
50522
|
-
inHeader: true
|
|
50523
|
-
// Pass header context for child sizing (e.g., smaller avatars)
|
|
50524
|
-
});
|
|
50525
|
-
const verticalOffset = (height - childBox.height) / 2;
|
|
50526
|
-
childBox.y = y + padding.top + verticalOffset;
|
|
50527
|
-
this.adjustChildrenY(childBox, verticalOffset);
|
|
50528
|
-
children.push(childBox);
|
|
50529
|
-
currentY += childBox.height;
|
|
50530
|
-
}
|
|
50531
|
-
return {
|
|
50532
|
-
x,
|
|
50533
|
-
y,
|
|
50534
|
-
width: constraints.maxWidth,
|
|
50535
|
-
height: height + padding.top + padding.bottom,
|
|
50536
|
-
node,
|
|
50537
|
-
children,
|
|
50538
|
-
padding
|
|
50539
|
-
};
|
|
50540
|
-
}
|
|
50541
|
-
adjustChildrenY(box, offset) {
|
|
50542
|
-
for (const child of box.children) {
|
|
50543
|
-
child.y += offset;
|
|
50544
|
-
this.adjustChildrenY(child, offset);
|
|
50545
|
-
}
|
|
50546
|
-
}
|
|
50547
|
-
/**
|
|
50548
|
-
* Check if a node should flex to fill available space in a Row
|
|
50549
|
-
* Only layout containers without explicit width should flex
|
|
50550
|
-
*/
|
|
50551
|
-
isFlexContainer(node) {
|
|
50552
|
-
if (node.type === "Main") return true;
|
|
50553
|
-
if (node.type === "Col" && !("w" in node && node.w !== void 0)) return true;
|
|
50554
|
-
return false;
|
|
50555
|
-
}
|
|
50556
|
-
layoutFooter(node, x, y, constraints) {
|
|
50557
|
-
const padding = this.getPadding(node);
|
|
50558
|
-
const height = this.resolveSize(node.h) || 60;
|
|
50559
|
-
const innerWidth = constraints.maxWidth - padding.left - padding.right;
|
|
50560
|
-
const children = [];
|
|
50561
|
-
let currentY = y + padding.top;
|
|
50562
|
-
for (const child of node.children) {
|
|
50563
|
-
const childBox = this.layoutNode(child, x + padding.left, currentY, {
|
|
50564
|
-
...constraints,
|
|
50565
|
-
maxWidth: innerWidth,
|
|
50566
|
-
maxHeight: void 0
|
|
50567
|
-
// Children use natural height
|
|
50568
|
-
});
|
|
50569
|
-
const verticalOffset = (height - childBox.height) / 2;
|
|
50570
|
-
childBox.y = y + padding.top + verticalOffset;
|
|
50571
|
-
this.adjustChildrenY(childBox, verticalOffset);
|
|
50572
|
-
children.push(childBox);
|
|
50573
|
-
currentY += childBox.height;
|
|
50574
|
-
}
|
|
50575
|
-
return {
|
|
50576
|
-
x,
|
|
50577
|
-
y,
|
|
50578
|
-
width: constraints.maxWidth,
|
|
50579
|
-
height: height + padding.top + padding.bottom,
|
|
50580
|
-
node,
|
|
50581
|
-
children,
|
|
50582
|
-
padding
|
|
50583
|
-
};
|
|
50584
|
-
}
|
|
50585
|
-
layoutMain(node, x, y, constraints) {
|
|
50586
|
-
const padding = this.getPadding(node);
|
|
50587
|
-
const gap = this.getGap(node) ?? this.DEFAULT_GAP;
|
|
50588
|
-
const innerWidth = constraints.maxWidth - padding.left - padding.right;
|
|
50589
|
-
const childMeasurements = node.children.map(
|
|
50590
|
-
(child) => this.measureNode(child, { ...constraints, maxWidth: innerWidth })
|
|
50591
|
-
);
|
|
50592
|
-
const children = [];
|
|
50593
|
-
let currentY = y + padding.top;
|
|
50594
|
-
for (let i = 0; i < node.children.length; i++) {
|
|
50595
|
-
const child = node.children[i];
|
|
50596
|
-
const childBox = this.layoutNode(child, x + padding.left, currentY, {
|
|
50597
|
-
...constraints,
|
|
50598
|
-
maxWidth: innerWidth
|
|
50599
|
-
});
|
|
50600
|
-
children.push(childBox);
|
|
50601
|
-
currentY += childBox.height + gap;
|
|
50602
|
-
}
|
|
50603
|
-
const totalHeight = childMeasurements.reduce(
|
|
50604
|
-
(sum, m, i) => sum + m.height + (i > 0 ? gap : 0),
|
|
50605
|
-
0
|
|
50606
|
-
);
|
|
50607
|
-
return {
|
|
50608
|
-
x,
|
|
50609
|
-
y,
|
|
50610
|
-
width: constraints.maxWidth,
|
|
50611
|
-
height: totalHeight + padding.top + padding.bottom,
|
|
50612
|
-
node,
|
|
50613
|
-
children,
|
|
50614
|
-
padding
|
|
50615
|
-
};
|
|
50616
|
-
}
|
|
50617
|
-
layoutSidebar(node, x, y, constraints) {
|
|
50618
|
-
const width = this.resolveSize(node.w) || 200;
|
|
50619
|
-
const padding = this.getPadding(node);
|
|
50620
|
-
const gap = this.getGap(node) ?? 8;
|
|
50621
|
-
const innerWidth = width - padding.left - padding.right;
|
|
50622
|
-
const children = [];
|
|
50623
|
-
let currentY = y + padding.top;
|
|
50624
|
-
for (const child of node.children) {
|
|
50625
|
-
const childBox = this.layoutNode(child, x + padding.left, currentY, {
|
|
50626
|
-
...constraints,
|
|
50627
|
-
maxWidth: innerWidth
|
|
50628
|
-
});
|
|
50629
|
-
children.push(childBox);
|
|
50630
|
-
currentY += childBox.height + gap;
|
|
50631
|
-
}
|
|
50632
|
-
const contentHeight = currentY - y - padding.top - gap + padding.bottom;
|
|
50633
|
-
const height = constraints.maxHeight || Math.max(contentHeight, 200);
|
|
50634
|
-
return {
|
|
50635
|
-
x,
|
|
50636
|
-
y,
|
|
50637
|
-
width,
|
|
50638
|
-
height,
|
|
50639
|
-
node,
|
|
50640
|
-
children,
|
|
50641
|
-
padding
|
|
50642
|
-
};
|
|
50643
|
-
}
|
|
50644
|
-
layoutCard(node, x, y, constraints) {
|
|
50645
|
-
let cardWidth = this.resolveSize(node.w);
|
|
50646
|
-
if (!cardWidth) {
|
|
50647
|
-
cardWidth = Math.min(360, constraints.maxWidth);
|
|
50648
|
-
}
|
|
50649
|
-
const padding = this.getPadding(node);
|
|
50650
|
-
const gap = this.getGap(node) ?? this.DEFAULT_GAP;
|
|
50651
|
-
const innerWidth = cardWidth - padding.left - padding.right;
|
|
50652
|
-
const children = [];
|
|
50653
|
-
let currentY = y + padding.top;
|
|
50654
|
-
if (node.title) {
|
|
50655
|
-
currentY += 28;
|
|
50656
|
-
}
|
|
50657
|
-
for (const child of node.children) {
|
|
50658
|
-
const childBox = this.layoutNode(child, x + padding.left, currentY, {
|
|
50659
|
-
...constraints,
|
|
50660
|
-
maxWidth: innerWidth
|
|
50661
|
-
});
|
|
50662
|
-
children.push(childBox);
|
|
50663
|
-
currentY += childBox.height + gap;
|
|
50664
|
-
}
|
|
50665
|
-
const totalHeight = currentY - y - gap + padding.bottom;
|
|
50666
|
-
return {
|
|
50667
|
-
x,
|
|
50668
|
-
y,
|
|
50669
|
-
width: cardWidth,
|
|
50670
|
-
height: totalHeight,
|
|
50671
|
-
node,
|
|
50672
|
-
children,
|
|
50673
|
-
padding
|
|
50674
|
-
};
|
|
50675
|
-
}
|
|
50676
|
-
// ===========================================
|
|
50677
|
-
// Render Phase
|
|
50678
|
-
// ===========================================
|
|
50679
|
-
renderBox(box) {
|
|
50680
|
-
if (!box.node) return "";
|
|
50681
|
-
switch (box.node.type) {
|
|
50682
|
-
case "Row":
|
|
50683
|
-
return this.renderRowBox(box);
|
|
50684
|
-
case "Col":
|
|
50685
|
-
return this.renderColBox(box);
|
|
50686
|
-
case "Header":
|
|
50687
|
-
return this.renderHeaderBox(box);
|
|
50688
|
-
case "Footer":
|
|
50689
|
-
return this.renderFooterBox(box);
|
|
50690
|
-
case "Main":
|
|
50691
|
-
return this.renderMainBox(box);
|
|
50692
|
-
case "Sidebar":
|
|
50693
|
-
return this.renderSidebarBox(box);
|
|
50694
|
-
case "Card":
|
|
50695
|
-
return this.renderCardBox(box);
|
|
50696
|
-
case "Modal":
|
|
50697
|
-
return this.renderModalBox(box);
|
|
50698
|
-
case "Title":
|
|
50699
|
-
return this.renderTitleBox(box);
|
|
50700
|
-
case "Text":
|
|
50701
|
-
return this.renderTextBox(box);
|
|
50702
|
-
case "Button":
|
|
50703
|
-
return this.renderButtonBox(box);
|
|
50704
|
-
case "Input":
|
|
50705
|
-
return this.renderInputBox(box);
|
|
50706
|
-
case "Textarea":
|
|
50707
|
-
return this.renderTextareaBox(box);
|
|
50708
|
-
case "Select":
|
|
50709
|
-
return this.renderSelectBox(box);
|
|
50710
|
-
case "Checkbox":
|
|
50711
|
-
return this.renderCheckboxBox(box);
|
|
50712
|
-
case "Radio":
|
|
50713
|
-
return this.renderRadioBox(box);
|
|
50714
|
-
case "Switch":
|
|
50715
|
-
return this.renderSwitchBox(box);
|
|
50716
|
-
case "Link":
|
|
50717
|
-
return this.renderLinkBox(box);
|
|
50718
|
-
case "Image":
|
|
50719
|
-
return this.renderImageBox(box);
|
|
50720
|
-
case "Placeholder":
|
|
50721
|
-
return this.renderPlaceholderBox(box);
|
|
50722
|
-
case "Avatar":
|
|
50723
|
-
return this.renderAvatarBox(box);
|
|
50724
|
-
case "Badge":
|
|
50725
|
-
return this.renderBadgeBox(box);
|
|
50726
|
-
case "Table":
|
|
50727
|
-
return this.renderTableBox(box);
|
|
50728
|
-
case "List":
|
|
50729
|
-
return this.renderListBox(box);
|
|
50730
|
-
case "Alert":
|
|
50731
|
-
return this.renderAlertBox(box);
|
|
50732
|
-
case "Progress":
|
|
50733
|
-
return this.renderProgressBox(box);
|
|
50734
|
-
case "Spinner":
|
|
50735
|
-
return this.renderSpinnerBox(box);
|
|
50736
|
-
case "Nav":
|
|
50737
|
-
return this.renderNavBox(box);
|
|
50738
|
-
case "Tabs":
|
|
50739
|
-
return this.renderTabsBox(box);
|
|
50740
|
-
case "Breadcrumb":
|
|
50741
|
-
return this.renderBreadcrumbBox(box);
|
|
50742
|
-
case "Icon":
|
|
50743
|
-
return this.renderIconBox(box);
|
|
50744
|
-
case "Divider":
|
|
50745
|
-
return this.renderDividerBox(box);
|
|
50746
|
-
default:
|
|
50747
|
-
return `<!-- Unsupported: ${box.node.type} -->`;
|
|
50748
|
-
}
|
|
50749
|
-
}
|
|
50750
|
-
renderRowBox(box) {
|
|
50751
|
-
const childrenSvg = box.children.map((child) => this.renderBox(child)).join("\n");
|
|
50752
|
-
return childrenSvg;
|
|
50753
|
-
}
|
|
50754
|
-
renderColBox(box) {
|
|
50755
|
-
const childrenSvg = box.children.map((child) => this.renderBox(child)).join("\n");
|
|
50756
|
-
return childrenSvg;
|
|
50757
|
-
}
|
|
50758
|
-
renderHeaderBox(box) {
|
|
50759
|
-
const node = box.node;
|
|
50760
|
-
const hasBorder = node.border !== false;
|
|
50761
|
-
let svg = `<g>
|
|
50762
|
-
<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" fill="${this.theme.colors.background}"/>`;
|
|
50763
|
-
if (hasBorder) {
|
|
50764
|
-
svg += `<line x1="${box.x}" y1="${box.y + box.height}" x2="${box.x + box.width}" y2="${box.y + box.height}" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
50765
|
-
}
|
|
50766
|
-
svg += box.children.map((child) => this.renderBox(child)).join("\n");
|
|
50767
|
-
svg += `</g>`;
|
|
50768
|
-
return svg;
|
|
50769
|
-
}
|
|
50770
|
-
renderFooterBox(box) {
|
|
50771
|
-
const node = box.node;
|
|
50772
|
-
const hasBorder = node.border !== false;
|
|
50773
|
-
let svg = `<g>
|
|
50774
|
-
<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" fill="${this.theme.colors.background}"`;
|
|
50775
|
-
if (hasBorder) {
|
|
50776
|
-
svg += ` stroke="${this.theme.colors.border}" stroke-width="1"`;
|
|
50777
|
-
}
|
|
50778
|
-
svg += `/>`;
|
|
50779
|
-
svg += box.children.map((child) => this.renderBox(child)).join("\n");
|
|
50780
|
-
svg += `</g>`;
|
|
50781
|
-
return svg;
|
|
50782
|
-
}
|
|
50783
|
-
renderMainBox(box) {
|
|
50784
|
-
const childrenSvg = box.children.map((child) => this.renderBox(child)).join("\n");
|
|
50785
|
-
return childrenSvg;
|
|
50786
|
-
}
|
|
50787
|
-
renderSidebarBox(box) {
|
|
50788
|
-
let svg = `<g>
|
|
50789
|
-
<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" fill="${this.theme.colors.background}" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
50790
|
-
svg += box.children.map((child) => this.renderBox(child)).join("\n");
|
|
50791
|
-
svg += `</g>`;
|
|
50792
|
-
return svg;
|
|
50793
|
-
}
|
|
50794
|
-
renderCardBox(box) {
|
|
50795
|
-
const node = box.node;
|
|
50796
|
-
const shadowAttr = node.shadow ? 'filter="url(#shadow)"' : "";
|
|
50797
|
-
let svg = `<g>
|
|
50798
|
-
<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" rx="8" fill="white" stroke="${this.theme.colors.border}" stroke-width="1" ${shadowAttr}/>`;
|
|
50799
|
-
if (node.title) {
|
|
50800
|
-
const padding = this.getPadding(node);
|
|
50801
|
-
svg += `<text x="${box.x + padding.left}" y="${box.y + padding.top + 18}" font-size="16" font-weight="600" fill="${this.theme.colors.foreground}">${this.escapeXml(node.title)}</text>`;
|
|
50802
|
-
}
|
|
50803
|
-
svg += box.children.map((child) => this.renderBox(child)).join("\n");
|
|
50804
|
-
svg += `</g>`;
|
|
50805
|
-
return svg;
|
|
50806
|
-
}
|
|
50807
|
-
renderModalBox(box) {
|
|
50808
|
-
const node = box.node;
|
|
50809
|
-
const modalX = (this.pageWidth - box.width) / 2;
|
|
50810
|
-
const modalY = (this.pageHeight - box.height) / 2;
|
|
50811
|
-
let svg = `<g>
|
|
50812
|
-
<rect width="${this.pageWidth}" height="${this.pageHeight}" fill="rgba(0,0,0,0.5)"/>
|
|
50813
|
-
<rect x="${modalX}" y="${modalY}" width="${box.width}" height="${box.height}" rx="8" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
50814
|
-
if (node.title) {
|
|
50815
|
-
svg += `<text x="${modalX + 20}" y="${modalY + 30}" font-size="18" font-weight="600" fill="${this.theme.colors.foreground}">${this.escapeXml(node.title)}</text>`;
|
|
50816
|
-
}
|
|
50817
|
-
for (const child of box.children) {
|
|
50818
|
-
const adjustedChild = { ...child, x: modalX + (child.x - box.x), y: modalY + (child.y - box.y) };
|
|
50819
|
-
svg += this.renderBox(adjustedChild);
|
|
50820
|
-
}
|
|
50821
|
-
svg += `</g>`;
|
|
50822
|
-
return svg;
|
|
50823
|
-
}
|
|
50824
|
-
renderTitleBox(box) {
|
|
50825
|
-
const node = box.node;
|
|
50826
|
-
const level = node.level || 1;
|
|
50827
|
-
const fontSize = this.getTitleFontSize(level);
|
|
50828
|
-
const textY = box.y + fontSize;
|
|
50829
|
-
let textX = box.x;
|
|
50830
|
-
let anchor = "start";
|
|
50831
|
-
if (node.align === "center") {
|
|
50832
|
-
textX = box.x + box.width / 2;
|
|
50833
|
-
anchor = "middle";
|
|
50834
|
-
} else if (node.align === "right") {
|
|
50835
|
-
textX = box.x + box.width;
|
|
50836
|
-
anchor = "end";
|
|
50837
|
-
}
|
|
50838
|
-
return `<text x="${textX}" y="${textY}" font-size="${fontSize}" font-weight="600" fill="${this.theme.colors.foreground}" text-anchor="${anchor}">${this.escapeXml(node.content)}</text>`;
|
|
50839
|
-
}
|
|
50840
|
-
renderTextBox(box) {
|
|
50841
|
-
const node = box.node;
|
|
50842
|
-
const fontSize = this.resolveFontSize(node.size);
|
|
50843
|
-
const fill = node.muted ? this.theme.colors.muted : this.theme.colors.foreground;
|
|
50844
|
-
const fontWeight = node.weight || "normal";
|
|
50845
|
-
const textY = box.y + fontSize;
|
|
50846
|
-
let textX = box.x;
|
|
50847
|
-
let anchor = "start";
|
|
50848
|
-
if (node.align === "center") {
|
|
50849
|
-
textX = box.x + box.width / 2;
|
|
50850
|
-
anchor = "middle";
|
|
50851
|
-
} else if (node.align === "right") {
|
|
50852
|
-
textX = box.x + box.width;
|
|
50853
|
-
anchor = "end";
|
|
50854
|
-
}
|
|
50855
|
-
return `<text x="${textX}" y="${textY}" font-size="${fontSize}" font-weight="${fontWeight}" fill="${fill}" text-anchor="${anchor}">${this.escapeXml(node.content)}</text>`;
|
|
50856
|
-
}
|
|
50857
|
-
renderButtonBox(box) {
|
|
50858
|
-
const node = box.node;
|
|
50859
|
-
const hasIcon = !!node.icon;
|
|
50860
|
-
const isIconOnly = hasIcon && !node.content.trim();
|
|
50861
|
-
let fill = this.theme.colors.primary;
|
|
50862
|
-
let textFill = "#ffffff";
|
|
50863
|
-
let strokeAttr = "";
|
|
50864
|
-
if (node.secondary) {
|
|
50865
|
-
fill = this.theme.colors.secondary;
|
|
50866
|
-
} else if (node.outline) {
|
|
50867
|
-
fill = "white";
|
|
50868
|
-
textFill = this.theme.colors.foreground;
|
|
50869
|
-
strokeAttr = `stroke="${this.theme.colors.border}" stroke-width="1"`;
|
|
50870
|
-
} else if (node.ghost) {
|
|
50871
|
-
fill = "transparent";
|
|
50872
|
-
textFill = this.theme.colors.foreground;
|
|
50873
|
-
}
|
|
50874
|
-
let svg = `<g>
|
|
50875
|
-
<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" rx="4" fill="${fill}" ${strokeAttr}/>`;
|
|
50876
|
-
if (hasIcon) {
|
|
50877
|
-
const iconData = getIconData(node.icon);
|
|
50878
|
-
if (iconData) {
|
|
50879
|
-
const iconSize = 16;
|
|
50880
|
-
const iconX = isIconOnly ? box.x + (box.width - iconSize) / 2 : box.x + 16;
|
|
50881
|
-
const iconY = box.y + (box.height - iconSize) / 2;
|
|
50882
|
-
svg += this.renderIconPaths(iconData, iconX, iconY, iconSize, textFill);
|
|
50883
|
-
}
|
|
50884
|
-
}
|
|
50885
|
-
if (!isIconOnly) {
|
|
50886
|
-
const textX = hasIcon ? box.x + 36 + (box.width - 52) / 2 : box.x + box.width / 2;
|
|
50887
|
-
svg += `<text x="${textX}" y="${box.y + box.height / 2 + 5}" font-size="14" fill="${textFill}" text-anchor="middle">${this.escapeXml(node.content)}</text>`;
|
|
50888
|
-
}
|
|
50889
|
-
svg += `</g>`;
|
|
50890
|
-
return svg;
|
|
50891
|
-
}
|
|
50892
|
-
renderInputBox(box) {
|
|
50893
|
-
const node = box.node;
|
|
50894
|
-
let y = box.y;
|
|
50895
|
-
let svg = "<g>";
|
|
50896
|
-
if (node.label) {
|
|
50897
|
-
svg += `<text x="${box.x}" y="${y + 14}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
50898
|
-
y += 24;
|
|
50899
|
-
}
|
|
50900
|
-
const inputHeight = 36;
|
|
50901
|
-
const placeholder = node.placeholder || "";
|
|
50902
|
-
svg += `<rect x="${box.x}" y="${y}" width="${box.width}" height="${inputHeight}" rx="4" fill="#f4f4f5"/>`;
|
|
50903
|
-
svg += `<text x="${box.x + 12}" y="${y + inputHeight / 2 + 5}" font-size="14" fill="${this.theme.colors.muted}">${this.escapeXml(placeholder)}</text>`;
|
|
50904
|
-
svg += "</g>";
|
|
50905
|
-
return svg;
|
|
50906
|
-
}
|
|
50907
|
-
renderTextareaBox(box) {
|
|
50908
|
-
const node = box.node;
|
|
50909
|
-
let y = box.y;
|
|
50910
|
-
let svg = "<g>";
|
|
50911
|
-
if (node.label) {
|
|
50912
|
-
svg += `<text x="${box.x}" y="${y + 14}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
50913
|
-
y += 24;
|
|
50914
|
-
}
|
|
50915
|
-
const textareaHeight = box.height - (node.label ? 24 : 0);
|
|
50916
|
-
const placeholder = node.placeholder || "";
|
|
50917
|
-
svg += `<rect x="${box.x}" y="${y}" width="${box.width}" height="${textareaHeight}" rx="4" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
50918
|
-
svg += `<text x="${box.x + 12}" y="${y + 24}" font-size="14" fill="${this.theme.colors.muted}">${this.escapeXml(placeholder)}</text>`;
|
|
50919
|
-
svg += "</g>";
|
|
50920
|
-
return svg;
|
|
50921
|
-
}
|
|
50922
|
-
renderSelectBox(box) {
|
|
50923
|
-
const node = box.node;
|
|
50924
|
-
let y = box.y;
|
|
50925
|
-
let svg = "<g>";
|
|
50926
|
-
if (node.label) {
|
|
50927
|
-
svg += `<text x="${box.x}" y="${y + 14}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
50928
|
-
y += 24;
|
|
50929
|
-
}
|
|
50930
|
-
const selectHeight = 40;
|
|
50931
|
-
const placeholder = node.placeholder || "Select...";
|
|
50932
|
-
svg += `<rect x="${box.x}" y="${y}" width="${box.width}" height="${selectHeight}" rx="4" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
50933
|
-
svg += `<text x="${box.x + 12}" y="${y + selectHeight / 2 + 5}" font-size="14" fill="${this.theme.colors.muted}">${this.escapeXml(placeholder)}</text>`;
|
|
50934
|
-
svg += `<path d="M${box.x + box.width - 24} ${y + selectHeight / 2 - 3} l6 6 l6 -6" fill="none" stroke="${this.theme.colors.muted}" stroke-width="1.5"/>`;
|
|
50935
|
-
svg += "</g>";
|
|
50936
|
-
return svg;
|
|
50937
|
-
}
|
|
50938
|
-
renderCheckboxBox(box) {
|
|
50939
|
-
const node = box.node;
|
|
50940
|
-
const size = 18;
|
|
50941
|
-
let svg = `<g>
|
|
50942
|
-
<rect x="${box.x}" y="${box.y}" width="${size}" height="${size}" rx="3" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
50943
|
-
if (node.checked) {
|
|
50944
|
-
svg += `<path d="M${box.x + 4} ${box.y + 9} L${box.x + 7} ${box.y + 12} L${box.x + 14} ${box.y + 5}" fill="none" stroke="${this.theme.colors.foreground}" stroke-width="2"/>`;
|
|
50945
|
-
}
|
|
50946
|
-
if (node.label) {
|
|
50947
|
-
svg += `<text x="${box.x + size + 8}" y="${box.y + size - 3}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
50948
|
-
}
|
|
50949
|
-
svg += "</g>";
|
|
50950
|
-
return svg;
|
|
50951
|
-
}
|
|
50952
|
-
renderRadioBox(box) {
|
|
50953
|
-
const node = box.node;
|
|
50954
|
-
const size = 18;
|
|
50955
|
-
const radius = size / 2;
|
|
50956
|
-
const cx = box.x + radius;
|
|
50957
|
-
const cy = box.y + radius;
|
|
50958
|
-
let svg = `<g>
|
|
50959
|
-
<circle cx="${cx}" cy="${cy}" r="${radius - 1}" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
50960
|
-
if (node.checked) {
|
|
50961
|
-
svg += `<circle cx="${cx}" cy="${cy}" r="${radius - 5}" fill="${this.theme.colors.foreground}"/>`;
|
|
50962
|
-
}
|
|
50963
|
-
if (node.label) {
|
|
50964
|
-
svg += `<text x="${box.x + size + 8}" y="${box.y + size - 3}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
50965
|
-
}
|
|
50966
|
-
svg += "</g>";
|
|
50967
|
-
return svg;
|
|
50968
|
-
}
|
|
50969
|
-
renderSwitchBox(box) {
|
|
50970
|
-
const node = box.node;
|
|
50971
|
-
const width = 44;
|
|
50972
|
-
const height = 24;
|
|
50973
|
-
const radius = height / 2;
|
|
50974
|
-
const isOn = node.checked;
|
|
50975
|
-
const bgColor = isOn ? this.theme.colors.primary : this.theme.colors.border;
|
|
50976
|
-
const knobX = isOn ? box.x + width - radius : box.x + radius;
|
|
50977
|
-
let svg = `<g>
|
|
50978
|
-
<rect x="${box.x}" y="${box.y}" width="${width}" height="${height}" rx="${radius}" fill="${bgColor}"/>
|
|
50979
|
-
<circle cx="${knobX}" cy="${box.y + radius}" r="${radius - 3}" fill="white"/>`;
|
|
50980
|
-
if (node.label) {
|
|
50981
|
-
svg += `<text x="${box.x + width + 8}" y="${box.y + height - 6}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
50982
|
-
}
|
|
50983
|
-
svg += "</g>";
|
|
50984
|
-
return svg;
|
|
50985
|
-
}
|
|
50986
|
-
renderLinkBox(box) {
|
|
50987
|
-
const node = box.node;
|
|
50988
|
-
const fontSize = 14;
|
|
50989
|
-
const textY = box.y + fontSize;
|
|
50990
|
-
return `<text x="${box.x}" y="${textY}" font-size="${fontSize}" fill="${this.theme.colors.primary}" text-decoration="underline">${this.escapeXml(node.content)}</text>`;
|
|
50991
|
-
}
|
|
50992
|
-
renderImageBox(box) {
|
|
50993
|
-
const node = box.node;
|
|
50994
|
-
return `<g>
|
|
50995
|
-
<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" fill="${this.theme.colors.muted}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
50996
|
-
<line x1="${box.x}" y1="${box.y}" x2="${box.x + box.width}" y2="${box.y + box.height}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
50997
|
-
<line x1="${box.x + box.width}" y1="${box.y}" x2="${box.x}" y2="${box.y + box.height}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
50998
|
-
<text x="${box.x + box.width / 2}" y="${box.y + box.height / 2 + 5}" font-size="14" fill="${this.theme.colors.foreground}" text-anchor="middle">${this.escapeXml(node.alt || "Image")}</text>
|
|
50999
|
-
</g>`;
|
|
51000
|
-
}
|
|
51001
|
-
renderPlaceholderBox(box) {
|
|
51002
|
-
const node = box.node;
|
|
51003
|
-
const patternId = `placeholder-pattern-${this.clipPathCounter++}`;
|
|
51004
|
-
const patternDef = `<pattern id="${patternId}" width="14" height="14" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
|
|
51005
|
-
<rect width="14" height="14" fill="#f9f9f9"/>
|
|
51006
|
-
<rect width="7" height="14" fill="rgba(0,0,0,0.03)"/>
|
|
51007
|
-
</pattern>`;
|
|
51008
|
-
this.clipPathDefs.push(patternDef);
|
|
51009
|
-
return `<g>
|
|
51010
|
-
<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" rx="4" fill="url(#${patternId})" stroke="${this.theme.colors.muted}" stroke-width="1" stroke-dasharray="4,2"/>
|
|
51011
|
-
<text x="${box.x + box.width / 2}" y="${box.y + box.height / 2 + 5}" font-size="14" fill="${this.theme.colors.muted}" text-anchor="middle">${this.escapeXml(node.label || "Placeholder")}</text>
|
|
51012
|
-
</g>`;
|
|
51013
|
-
}
|
|
51014
|
-
renderAvatarBox(box) {
|
|
51015
|
-
const node = box.node;
|
|
51016
|
-
const radius = box.width / 2;
|
|
51017
|
-
const cx = box.x + radius;
|
|
51018
|
-
const cy = box.y + radius;
|
|
51019
|
-
const initial = node.name ? node.name.charAt(0).toUpperCase() : "?";
|
|
51020
|
-
return `<g>
|
|
51021
|
-
<circle cx="${cx}" cy="${cy}" r="${radius}" fill="${this.theme.colors.foreground}"/>
|
|
51022
|
-
<text x="${cx}" y="${cy + 5}" font-size="${box.width / 2.5}" fill="${this.theme.colors.background}" text-anchor="middle">${initial}</text>
|
|
51023
|
-
</g>`;
|
|
51024
|
-
}
|
|
51025
|
-
renderBadgeBox(box) {
|
|
51026
|
-
const node = box.node;
|
|
51027
|
-
return `<g>
|
|
51028
|
-
<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" rx="11" fill="${this.theme.colors.muted}" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
51029
|
-
<text x="${box.x + box.width / 2}" y="${box.y + box.height / 2 + 4}" font-size="12" fill="${this.theme.colors.foreground}" text-anchor="middle">${this.escapeXml(node.content)}</text>
|
|
51030
|
-
</g>`;
|
|
51031
|
-
}
|
|
51032
|
-
renderTableBox(box) {
|
|
51033
|
-
const node = box.node;
|
|
51034
|
-
const columns = node.columns || [];
|
|
51035
|
-
const rows = node.rows || [];
|
|
51036
|
-
const rowCount = rows.length || 3;
|
|
51037
|
-
const colWidth = 120;
|
|
51038
|
-
const rowHeight = 40;
|
|
51039
|
-
let svg = `<g>`;
|
|
51040
|
-
svg += `<rect x="${box.x}" y="${box.y}" width="${columns.length * colWidth}" height="${rowHeight}" fill="${this.theme.colors.muted}"/>`;
|
|
51041
|
-
columns.forEach((col, i) => {
|
|
51042
|
-
svg += `<text x="${box.x + i * colWidth + 12}" y="${box.y + rowHeight / 2 + 5}" font-size="14" font-weight="600">${this.escapeXml(col)}</text>`;
|
|
51043
|
-
});
|
|
51044
|
-
const displayRowCount = rows.length > 0 ? rows.length : rowCount;
|
|
51045
|
-
for (let rowIdx = 0; rowIdx < displayRowCount; rowIdx++) {
|
|
51046
|
-
const rowY = box.y + (rowIdx + 1) * rowHeight;
|
|
51047
|
-
svg += `<rect x="${box.x}" y="${rowY}" width="${columns.length * colWidth}" height="${rowHeight}" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
51048
|
-
columns.forEach((_, colIdx) => {
|
|
51049
|
-
const cellContent = rows[rowIdx] && rows[rowIdx][colIdx] ? String(typeof rows[rowIdx][colIdx] === "object" ? "..." : rows[rowIdx][colIdx]) : "\u2014";
|
|
51050
|
-
svg += `<text x="${box.x + colIdx * colWidth + 12}" y="${rowY + rowHeight / 2 + 5}" font-size="14" fill="${this.theme.colors.muted}">${this.escapeXml(cellContent)}</text>`;
|
|
51051
|
-
});
|
|
51052
|
-
}
|
|
51053
|
-
svg += "</g>";
|
|
51054
|
-
return svg;
|
|
51055
|
-
}
|
|
51056
|
-
renderListBox(box) {
|
|
51057
|
-
const node = box.node;
|
|
51058
|
-
const items = node.items || [];
|
|
51059
|
-
const ordered = node.ordered || false;
|
|
51060
|
-
let svg = "<g>";
|
|
51061
|
-
items.forEach((item, idx) => {
|
|
51062
|
-
const marker = ordered ? `${idx + 1}.` : "\u2022";
|
|
51063
|
-
const content = typeof item === "string" ? item : item.content;
|
|
51064
|
-
svg += `<text x="${box.x}" y="${box.y + idx * 28 + 16}" font-size="14" fill="${this.theme.colors.foreground}">${marker} ${this.escapeXml(content)}</text>`;
|
|
51065
|
-
});
|
|
51066
|
-
svg += "</g>";
|
|
51067
|
-
return svg;
|
|
51068
|
-
}
|
|
51069
|
-
renderAlertBox(box) {
|
|
51070
|
-
const node = box.node;
|
|
51071
|
-
return `<g>
|
|
51072
|
-
<rect x="${box.x}" y="${box.y}" width="${box.width}" height="${box.height}" rx="4" fill="white" stroke="${this.theme.colors.border}" stroke-width="1"/>
|
|
51073
|
-
<text x="${box.x + 16}" y="${box.y + box.height / 2 + 5}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.content)}</text>
|
|
51074
|
-
</g>`;
|
|
51075
|
-
}
|
|
51076
|
-
renderProgressBox(box) {
|
|
51077
|
-
const node = box.node;
|
|
51078
|
-
let y = box.y;
|
|
51079
|
-
let svg = "<g>";
|
|
51080
|
-
if (node.label) {
|
|
51081
|
-
svg += `<text x="${box.x}" y="${y + 14}" font-size="14" fill="${this.theme.colors.foreground}">${this.escapeXml(node.label)}</text>`;
|
|
51082
|
-
y += 24;
|
|
51083
|
-
}
|
|
51084
|
-
const barHeight = 8;
|
|
51085
|
-
const value = node.value || 0;
|
|
51086
|
-
const max = node.max || 100;
|
|
51087
|
-
const percent = Math.min(100, Math.max(0, value / max * 100));
|
|
51088
|
-
svg += `<rect x="${box.x}" y="${y}" width="${box.width}" height="${barHeight}" rx="${barHeight / 2}" fill="${this.theme.colors.muted}"/>`;
|
|
51089
|
-
svg += `<rect x="${box.x}" y="${y}" width="${box.width * percent / 100}" height="${barHeight}" rx="${barHeight / 2}" fill="${this.theme.colors.primary}"/>`;
|
|
51090
|
-
svg += "</g>";
|
|
51091
|
-
return svg;
|
|
51092
|
-
}
|
|
51093
|
-
renderSpinnerBox(box) {
|
|
51094
|
-
const cx = box.x + box.width / 2;
|
|
51095
|
-
const cy = box.y + box.height / 2;
|
|
51096
|
-
const radius = box.width / 2 - 2;
|
|
51097
|
-
return `<g>
|
|
51098
|
-
<circle cx="${cx}" cy="${cy}" r="${radius}" fill="none" stroke="${this.theme.colors.muted}" stroke-width="2"/>
|
|
51099
|
-
<path d="M${cx},${cy - radius} A${radius},${radius} 0 0,1 ${cx + radius},${cy}" fill="none" stroke="${this.theme.colors.primary}" stroke-width="2" stroke-linecap="round"/>
|
|
51100
|
-
</g>`;
|
|
51101
|
-
}
|
|
51102
|
-
renderNavBox(box) {
|
|
51103
|
-
const node = box.node;
|
|
51104
|
-
const vertical = node.vertical || false;
|
|
51105
|
-
let svg = "<g>";
|
|
51106
|
-
if (node.children && node.children.length > 0) {
|
|
51107
|
-
let offsetY = 0;
|
|
51108
|
-
node.children.forEach((child) => {
|
|
51109
|
-
if (child.type === "divider") {
|
|
51110
|
-
offsetY += 16;
|
|
51111
|
-
svg += `<line x1="${box.x}" y1="${box.y + offsetY}" x2="${box.x + box.width - 32}" y2="${box.y + offsetY}" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
51112
|
-
offsetY += 8;
|
|
51113
|
-
} else if (child.type === "group") {
|
|
51114
|
-
svg += `<text x="${box.x}" y="${box.y + offsetY + 16}" font-size="11" font-weight="500" fill="${this.theme.colors.muted}" text-transform="uppercase">${this.escapeXml(child.label)}</text>`;
|
|
51115
|
-
offsetY += 28;
|
|
51116
|
-
child.items.forEach((item) => {
|
|
51117
|
-
if (item.type === "divider") {
|
|
51118
|
-
offsetY += 8;
|
|
51119
|
-
svg += `<line x1="${box.x}" y1="${box.y + offsetY}" x2="${box.x + box.width - 32}" y2="${box.y + offsetY}" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
51120
|
-
offsetY += 8;
|
|
51121
|
-
} else {
|
|
51122
|
-
const fill = item.active ? this.theme.colors.foreground : this.theme.colors.muted;
|
|
51123
|
-
const fontWeight = item.active ? 'font-weight="500"' : "";
|
|
51124
|
-
svg += `<text x="${box.x}" y="${box.y + offsetY + 16}" font-size="14" ${fontWeight} fill="${fill}">${this.escapeXml(item.label)}</text>`;
|
|
51125
|
-
offsetY += 32;
|
|
51126
|
-
}
|
|
51127
|
-
});
|
|
51128
|
-
} else if (child.type === "item") {
|
|
51129
|
-
const fill = child.active ? this.theme.colors.foreground : this.theme.colors.muted;
|
|
51130
|
-
const fontWeight = child.active ? 'font-weight="500"' : "";
|
|
51131
|
-
svg += `<text x="${box.x}" y="${box.y + offsetY + 16}" font-size="14" ${fontWeight} fill="${fill}">${this.escapeXml(child.label)}</text>`;
|
|
51132
|
-
offsetY += 32;
|
|
51133
|
-
}
|
|
51134
|
-
});
|
|
51135
|
-
svg += "</g>";
|
|
51136
|
-
return svg;
|
|
51137
|
-
}
|
|
51138
|
-
const items = node.items || [];
|
|
51139
|
-
if (vertical) {
|
|
51140
|
-
items.forEach((item, idx) => {
|
|
51141
|
-
const label = typeof item === "string" ? item : item.label;
|
|
51142
|
-
const isActive = typeof item === "object" && item.active;
|
|
51143
|
-
const fill = isActive ? this.theme.colors.foreground : this.theme.colors.muted;
|
|
51144
|
-
svg += `<text x="${box.x}" y="${box.y + idx * 32 + 16}" font-size="14" fill="${fill}">${this.escapeXml(label)}</text>`;
|
|
51145
|
-
});
|
|
51146
|
-
} else {
|
|
51147
|
-
let offsetX = 0;
|
|
51148
|
-
items.forEach((item) => {
|
|
51149
|
-
const label = typeof item === "string" ? item : item.label;
|
|
51150
|
-
const isActive = typeof item === "object" && item.active;
|
|
51151
|
-
const fill = isActive ? this.theme.colors.foreground : this.theme.colors.muted;
|
|
51152
|
-
svg += `<text x="${box.x + offsetX}" y="${box.y + 16}" font-size="14" fill="${fill}">${this.escapeXml(label)}</text>`;
|
|
51153
|
-
offsetX += this.estimateTextWidth(label, 14) + 24;
|
|
51154
|
-
});
|
|
51155
|
-
}
|
|
51156
|
-
svg += "</g>";
|
|
51157
|
-
return svg;
|
|
51158
|
-
}
|
|
51159
|
-
renderTabsBox(box) {
|
|
51160
|
-
const node = box.node;
|
|
51161
|
-
const items = node.items || [];
|
|
51162
|
-
const tabHeight = 40;
|
|
51163
|
-
let svg = "<g>";
|
|
51164
|
-
let offsetX = 0;
|
|
51165
|
-
items.forEach((item, idx) => {
|
|
51166
|
-
const label = typeof item === "string" ? item : item;
|
|
51167
|
-
const tabWidth = this.estimateTextWidth(label, 14) + 32;
|
|
51168
|
-
const isFirst = idx === 0;
|
|
51169
|
-
svg += `<rect x="${box.x + offsetX}" y="${box.y}" width="${tabWidth}" height="${tabHeight}" fill="${isFirst ? "white" : this.theme.colors.muted}" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
51170
|
-
svg += `<text x="${box.x + offsetX + tabWidth / 2}" y="${box.y + tabHeight / 2 + 5}" font-size="14" text-anchor="middle" fill="${this.theme.colors.foreground}">${this.escapeXml(label)}</text>`;
|
|
51171
|
-
offsetX += tabWidth;
|
|
51172
|
-
});
|
|
51173
|
-
svg += "</g>";
|
|
51174
|
-
return svg;
|
|
51175
|
-
}
|
|
51176
|
-
renderBreadcrumbBox(box) {
|
|
51177
|
-
const node = box.node;
|
|
51178
|
-
const items = node.items || [];
|
|
51179
|
-
const separator = "/";
|
|
51180
|
-
let svg = "<g>";
|
|
51181
|
-
let offsetX = 0;
|
|
51182
|
-
items.forEach((item, idx) => {
|
|
51183
|
-
const label = typeof item === "string" ? item : item.label;
|
|
51184
|
-
const isLast = idx === items.length - 1;
|
|
51185
|
-
const fill = isLast ? this.theme.colors.foreground : this.theme.colors.muted;
|
|
51186
|
-
svg += `<text x="${box.x + offsetX}" y="${box.y + 16}" font-size="14" fill="${fill}">${this.escapeXml(label)}</text>`;
|
|
51187
|
-
offsetX += this.estimateTextWidth(label, 14) + 8;
|
|
51188
|
-
if (!isLast) {
|
|
51189
|
-
svg += `<text x="${box.x + offsetX}" y="${box.y + 16}" font-size="14" fill="${this.theme.colors.muted}">${separator}</text>`;
|
|
51190
|
-
offsetX += 16;
|
|
51191
|
-
}
|
|
51192
|
-
});
|
|
51193
|
-
svg += "</g>";
|
|
51194
|
-
return svg;
|
|
51195
|
-
}
|
|
51196
|
-
renderIconBox(box) {
|
|
51197
|
-
const node = box.node;
|
|
51198
|
-
const iconData = getIconData(node.name);
|
|
51199
|
-
if (!iconData) {
|
|
51200
|
-
return `<!-- Icon not found: ${node.name} -->`;
|
|
51201
|
-
}
|
|
51202
|
-
const color = this.theme.colors.foreground;
|
|
51203
|
-
return this.renderIconPaths(iconData, box.x, box.y, box.width, color);
|
|
51204
|
-
}
|
|
51205
|
-
renderDividerBox(box) {
|
|
51206
|
-
return `<line x1="${box.x}" y1="${box.y}" x2="${box.x + box.width}" y2="${box.y}" stroke="${this.theme.colors.border}" stroke-width="1"/>`;
|
|
51207
|
-
}
|
|
51208
|
-
// ===========================================
|
|
51209
|
-
// Utility Methods
|
|
51210
|
-
// ===========================================
|
|
51211
|
-
renderIconPaths(data, x, y, size, color) {
|
|
51212
|
-
const scale = size / 24;
|
|
51213
|
-
const paths = data.map(([tag, attrs]) => {
|
|
51214
|
-
const attrStr = Object.entries(attrs).map(([key, value]) => `${key}="${value}"`).join(" ");
|
|
51215
|
-
return `<${tag} ${attrStr} />`;
|
|
51216
|
-
}).join("");
|
|
51217
|
-
return `<g transform="translate(${x}, ${y}) scale(${scale})" fill="none" stroke="${color}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${paths}</g>`;
|
|
51218
|
-
}
|
|
51219
|
-
getPadding(node) {
|
|
51220
|
-
const defaultPadding = { top: 0, right: 0, bottom: 0, left: 0 };
|
|
51221
|
-
if (!("p" in node) && !("px" in node) && !("py" in node)) {
|
|
51222
|
-
if (node.type === "Card" || node.type === "Header" || node.type === "Footer" || node.type === "Sidebar") {
|
|
51223
|
-
return { top: 16, right: 16, bottom: 16, left: 16 };
|
|
51224
|
-
}
|
|
51225
|
-
return defaultPadding;
|
|
51226
|
-
}
|
|
51227
|
-
let p = 0;
|
|
51228
|
-
if ("p" in node && node.p !== void 0) {
|
|
51229
|
-
p = this.resolveSpacing(node.p);
|
|
51230
|
-
}
|
|
51231
|
-
let px = p;
|
|
51232
|
-
let py = p;
|
|
51233
|
-
if ("px" in node && node.px !== void 0) {
|
|
51234
|
-
px = this.resolveSpacing(node.px);
|
|
51235
|
-
}
|
|
51236
|
-
if ("py" in node && node.py !== void 0) {
|
|
51237
|
-
py = this.resolveSpacing(node.py);
|
|
51238
|
-
}
|
|
51239
|
-
if (node.type === "Header") {
|
|
51240
|
-
return { top: 0, right: px, bottom: 0, left: px };
|
|
51241
|
-
}
|
|
51242
|
-
return { top: py, right: px, bottom: py, left: px };
|
|
51243
|
-
}
|
|
51244
|
-
getGap(node) {
|
|
51245
|
-
if ("gap" in node && node.gap !== void 0) {
|
|
51246
|
-
return this.resolveSpacing(node.gap);
|
|
51247
|
-
}
|
|
51248
|
-
return void 0;
|
|
51249
|
-
}
|
|
51250
|
-
resolveSpacing(value) {
|
|
51251
|
-
if (typeof value === "number") {
|
|
51252
|
-
return value * 4;
|
|
51253
|
-
}
|
|
51254
|
-
if (typeof value === "object" && value && "value" in value) {
|
|
51255
|
-
return value.value;
|
|
51256
|
-
}
|
|
51257
|
-
return 0;
|
|
51258
|
-
}
|
|
51259
|
-
resolveSize(value) {
|
|
51260
|
-
if (value === void 0 || value === null) return void 0;
|
|
51261
|
-
if (typeof value === "number") return value;
|
|
51262
|
-
if (typeof value === "string") {
|
|
51263
|
-
if (value === "full") return void 0;
|
|
51264
|
-
const num = parseFloat(value);
|
|
51265
|
-
if (!isNaN(num)) return num;
|
|
51266
|
-
}
|
|
51267
|
-
if (typeof value === "object" && value && "value" in value) {
|
|
51268
|
-
return value.value;
|
|
51269
|
-
}
|
|
51270
|
-
return void 0;
|
|
51271
|
-
}
|
|
51272
|
-
isFullWidth(node) {
|
|
51273
|
-
if ("w" in node) {
|
|
51274
|
-
return node.w === "full";
|
|
51275
|
-
}
|
|
51276
|
-
return false;
|
|
51277
|
-
}
|
|
51278
|
-
estimateTextWidth(text, fontSize) {
|
|
51279
|
-
return text.length * fontSize * 0.6;
|
|
51280
|
-
}
|
|
51281
|
-
resolveFontSize(size) {
|
|
51282
|
-
if (!size) return 16;
|
|
51283
|
-
if (typeof size === "string") {
|
|
51284
|
-
const sizes = {
|
|
51285
|
-
xs: 12,
|
|
51286
|
-
sm: 14,
|
|
51287
|
-
base: 16,
|
|
51288
|
-
md: 16,
|
|
51289
|
-
lg: 18,
|
|
51290
|
-
xl: 20,
|
|
51291
|
-
"2xl": 24,
|
|
51292
|
-
"3xl": 30
|
|
51293
|
-
};
|
|
51294
|
-
return sizes[size] || 16;
|
|
51295
|
-
}
|
|
51296
|
-
if (typeof size === "object" && "value" in size) {
|
|
51297
|
-
if (size.unit === "px") return size.value;
|
|
51298
|
-
if (size.unit === "rem") return size.value * 16;
|
|
51299
|
-
if (size.unit === "em") return size.value * 16;
|
|
51300
|
-
return size.value;
|
|
51301
|
-
}
|
|
51302
|
-
return 16;
|
|
51303
|
-
}
|
|
51304
|
-
getTitleFontSize(level) {
|
|
51305
|
-
const sizes = { 1: 36, 2: 30, 3: 24, 4: 20, 5: 18, 6: 16 };
|
|
51306
|
-
return sizes[level] || 20;
|
|
51307
|
-
}
|
|
51308
|
-
escapeXml(str) {
|
|
51309
|
-
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
51310
|
-
}
|
|
51311
|
-
};
|
|
51312
|
-
function createSvgRenderer(options) {
|
|
51313
|
-
return new SvgRenderer(options);
|
|
51314
|
-
}
|
|
51315
|
-
function renderToSvg(doc, options) {
|
|
51316
|
-
const renderer = new SvgRenderer(options);
|
|
51317
|
-
return renderer.render(doc);
|
|
51318
|
-
}
|
|
51319
|
-
|
|
51320
49669
|
// src/renderer/index.ts
|
|
51321
49670
|
function render(document, options = {}) {
|
|
51322
49671
|
const renderer = createHtmlRenderer(options);
|
|
@@ -51353,7 +49702,7 @@ ${html}
|
|
|
51353
49702
|
</body>
|
|
51354
49703
|
</html>`;
|
|
51355
49704
|
}
|
|
51356
|
-
function
|
|
49705
|
+
function renderToSvg(document, options = {}) {
|
|
51357
49706
|
const firstPage = document.children[0];
|
|
51358
49707
|
let width = options.width ?? 800;
|
|
51359
49708
|
let height = options.height ?? 600;
|
|
@@ -51389,14 +49738,9 @@ ${css}
|
|
|
51389
49738
|
</svg>`;
|
|
51390
49739
|
return { svg, width, height };
|
|
51391
49740
|
}
|
|
51392
|
-
function renderToPureSvg(document, options = {}) {
|
|
51393
|
-
return renderToSvg(document, options);
|
|
51394
|
-
}
|
|
51395
49741
|
export {
|
|
51396
49742
|
HtmlRenderer,
|
|
51397
|
-
SvgRenderer,
|
|
51398
49743
|
createHtmlRenderer,
|
|
51399
|
-
createSvgRenderer,
|
|
51400
49744
|
darkTheme,
|
|
51401
49745
|
defaultTheme,
|
|
51402
49746
|
generateComponentStyles,
|
|
@@ -51407,8 +49751,7 @@ export {
|
|
|
51407
49751
|
render,
|
|
51408
49752
|
renderIconSvg,
|
|
51409
49753
|
renderToHtml,
|
|
51410
|
-
|
|
51411
|
-
renderToSvg2 as renderToSvg
|
|
49754
|
+
renderToSvg
|
|
51412
49755
|
};
|
|
51413
49756
|
/**
|
|
51414
49757
|
* Lucide Icons Data
|