@agent-scope/site 1.18.1 → 1.20.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 +259 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +259 -66
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -68,21 +68,24 @@ function slugify(name) {
|
|
|
68
68
|
}
|
|
69
69
|
function renderDOMTree(node, depth = 0) {
|
|
70
70
|
const indent = " ".repeat(depth);
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
const attrsHtml = Object.entries(node.attrs).map(([k, v]) => {
|
|
72
|
+
const display = v.length > 60 ? `${v.slice(0, 57)}\u2026` : v;
|
|
73
|
+
return ` <span class="dom-attr-name">${escapeHtml(k)}</span>=<span class="dom-attr-value">"${escapeHtml(display)}"</span>`;
|
|
74
|
+
}).join("");
|
|
75
|
+
const nodeIdAttr = node.nodeId !== void 0 ? ` data-node-id="${node.nodeId}"` : "";
|
|
76
|
+
const clickable = node.nodeId !== void 0 ? " dom-node-clickable" : "";
|
|
74
77
|
const hasChildren = node.children.length > 0;
|
|
75
78
|
const hasText = node.text !== void 0 && node.text.trim().length > 0;
|
|
76
79
|
if (!hasChildren && !hasText) {
|
|
77
|
-
return `${indent}<span class="dom-tag-open"><${escapeHtml(node.tag)}${
|
|
80
|
+
return `${indent}<span class="dom-tag-open${clickable}"${nodeIdAttr}><${escapeHtml(node.tag)}${attrsHtml} /></span>
|
|
78
81
|
`;
|
|
79
82
|
}
|
|
80
83
|
const childrenHtml = node.children.map((child) => renderDOMTree(child, depth + 1)).join("");
|
|
81
84
|
const textHtml = hasText ? `${indent} <span class="dom-text">${escapeHtml(node.text ?? "")}</span>
|
|
82
85
|
` : "";
|
|
83
|
-
return `<details class="dom-node" ${depth < 2 ? "open" : ""}>
|
|
84
|
-
${indent}<summary><span class="dom-tag-open"><${escapeHtml(node.tag)}${
|
|
85
|
-
${textHtml}${childrenHtml}${indent}<span class="dom-tag-
|
|
86
|
+
return `<details class="dom-node${clickable}" ${depth < 2 ? "open" : ""}${nodeIdAttr}>
|
|
87
|
+
${indent}<summary><span class="dom-tag-open"><${escapeHtml(node.tag)}${attrsHtml}></span></summary>
|
|
88
|
+
${textHtml}${childrenHtml}${indent}<span class="dom-tag-close"></${escapeHtml(node.tag)}></span>
|
|
86
89
|
</details>`;
|
|
87
90
|
}
|
|
88
91
|
function propTableRow(name, prop) {
|
|
@@ -298,6 +301,7 @@ body {
|
|
|
298
301
|
max-width: 100%;
|
|
299
302
|
}
|
|
300
303
|
.render-preview img { display: block; max-width: 100%; }
|
|
304
|
+
.scope-screenshot { zoom: 0.5; display: block; image-rendering: -webkit-optimize-contrast; }
|
|
301
305
|
|
|
302
306
|
/* Props table */
|
|
303
307
|
.props-table { width: 100%; border-collapse: collapse; font-size: 13px; }
|
|
@@ -437,7 +441,7 @@ pre.code-block {
|
|
|
437
441
|
overflow: hidden;
|
|
438
442
|
}
|
|
439
443
|
.matrix-cell { background: var(--color-bg); padding: 8px; text-align: center; }
|
|
440
|
-
.matrix-cell img {
|
|
444
|
+
.matrix-cell img { border-radius: 2px; }
|
|
441
445
|
.matrix-cell .cell-label { font-size: 10px; color: var(--color-muted); margin-top: 4px; }
|
|
442
446
|
.matrix-header { background: var(--color-bg-subtle); padding: 6px 8px; font-size: 11px; font-weight: 600; color: var(--color-muted); }
|
|
443
447
|
|
|
@@ -446,6 +450,13 @@ pre.code-block {
|
|
|
446
450
|
details.dom-node > summary { cursor: pointer; list-style: none; }
|
|
447
451
|
details.dom-node > summary::-webkit-details-marker { display: none; }
|
|
448
452
|
.dom-tag-open { color: #f07178; }
|
|
453
|
+
.dom-tag-close { color: #f07178; }
|
|
454
|
+
.dom-attr-name { color: #ffcb6b; }
|
|
455
|
+
.dom-attr-value { color: #c3e88d; }
|
|
456
|
+
.dom-text { color: #82aaff; font-style: italic; }
|
|
457
|
+
.dom-node-clickable { cursor: pointer; border-radius: 3px; transition: background 0.1s; }
|
|
458
|
+
.dom-node-clickable:hover, details.dom-node-clickable > summary:hover { background: rgba(255,255,255,0.08); }
|
|
459
|
+
.dom-node-selected, details.dom-node-selected > summary { background: rgba(99,179,237,0.15) !important; outline: 1px solid rgba(99,179,237,0.4); border-radius: 3px; }
|
|
449
460
|
.dom-attr-name { color: #ffcb6b; }
|
|
450
461
|
.dom-attr-value { color: #c3e88d; }
|
|
451
462
|
.dom-text { color: #a0a0b0; font-style: italic; }
|
|
@@ -486,7 +497,7 @@ details.dom-node > summary::-webkit-details-marker { display: none; }
|
|
|
486
497
|
justify-content: center;
|
|
487
498
|
border-bottom: 1px solid var(--color-border);
|
|
488
499
|
}
|
|
489
|
-
.card-preview img {
|
|
500
|
+
.card-preview img { object-fit: contain; }
|
|
490
501
|
.card-preview .no-preview { color: var(--color-muted); font-size: 12px; }
|
|
491
502
|
.card-body { padding: 12px 16px; }
|
|
492
503
|
.card-name { font-weight: 600; font-size: 14px; margin-bottom: 4px; }
|
|
@@ -506,6 +517,58 @@ details.dom-node > summary::-webkit-details-marker { display: none; }
|
|
|
506
517
|
.content-body { padding: 20px 16px; }
|
|
507
518
|
.analysis-grid { grid-template-columns: 1fr; }
|
|
508
519
|
.composition-lists { grid-template-columns: 1fr; }
|
|
520
|
+
}
|
|
521
|
+
/* Collection section headers in sidebar */
|
|
522
|
+
.sidebar-collection-header {
|
|
523
|
+
font-size: 10px;
|
|
524
|
+
font-weight: 700;
|
|
525
|
+
letter-spacing: 0.08em;
|
|
526
|
+
text-transform: uppercase;
|
|
527
|
+
color: var(--color-muted);
|
|
528
|
+
padding: 12px 16px 4px;
|
|
529
|
+
margin-top: 4px;
|
|
530
|
+
border-top: 1px solid var(--color-border);
|
|
531
|
+
}
|
|
532
|
+
.sidebar-collection-header:first-child {
|
|
533
|
+
margin-top: 0;
|
|
534
|
+
border-top: none;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/* Collection section headers on index page */
|
|
538
|
+
.collection-section {
|
|
539
|
+
margin-bottom: 40px;
|
|
540
|
+
}
|
|
541
|
+
.collection-section-header {
|
|
542
|
+
margin-bottom: 16px;
|
|
543
|
+
padding-bottom: 10px;
|
|
544
|
+
border-bottom: 2px solid var(--color-border);
|
|
545
|
+
}
|
|
546
|
+
.collection-section-header h2 {
|
|
547
|
+
font-size: 18px;
|
|
548
|
+
font-weight: 600;
|
|
549
|
+
margin: 0 0 4px;
|
|
550
|
+
color: var(--color-text);
|
|
551
|
+
}
|
|
552
|
+
.collection-section-header p {
|
|
553
|
+
font-size: 13px;
|
|
554
|
+
color: var(--color-muted);
|
|
555
|
+
margin: 0;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/* Internal component badge */
|
|
559
|
+
.badge-internal {
|
|
560
|
+
display: inline-flex;
|
|
561
|
+
align-items: center;
|
|
562
|
+
padding: 1px 6px;
|
|
563
|
+
border-radius: 999px;
|
|
564
|
+
font-size: 10px;
|
|
565
|
+
font-weight: 500;
|
|
566
|
+
border: 1px solid #d1d5db;
|
|
567
|
+
color: #9ca3af;
|
|
568
|
+
background: #f3f4f6;
|
|
569
|
+
margin-left: 4px;
|
|
570
|
+
vertical-align: middle;
|
|
571
|
+
line-height: 1.4;
|
|
509
572
|
}`;
|
|
510
573
|
return `<style>
|
|
511
574
|
${css}
|
|
@@ -513,14 +576,54 @@ ${css}
|
|
|
513
576
|
}
|
|
514
577
|
|
|
515
578
|
// src/templates/layout.ts
|
|
516
|
-
function sidebarLinks(
|
|
517
|
-
const
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
579
|
+
function sidebarLinks(data, currentSlug) {
|
|
580
|
+
const { components } = data.manifest;
|
|
581
|
+
const collections = data.manifest.collections ?? [];
|
|
582
|
+
const basePath = data.options.basePath;
|
|
583
|
+
const visibleEntries = Object.entries(components).filter(([, c]) => !c.internal);
|
|
584
|
+
const collectionMap = /* @__PURE__ */ new Map();
|
|
585
|
+
for (const col of collections) {
|
|
586
|
+
collectionMap.set(col.name, []);
|
|
587
|
+
}
|
|
588
|
+
const ungrouped = [];
|
|
589
|
+
for (const [name, component] of visibleEntries) {
|
|
590
|
+
if (component.collection) {
|
|
591
|
+
if (!collectionMap.has(component.collection)) {
|
|
592
|
+
collectionMap.set(component.collection, []);
|
|
593
|
+
}
|
|
594
|
+
collectionMap.get(component.collection)?.push(name);
|
|
595
|
+
} else {
|
|
596
|
+
ungrouped.push(name);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
const hasAnyCollections = collectionMap.size > 0 || ungrouped.length < visibleEntries.length;
|
|
600
|
+
function renderLinks(names) {
|
|
601
|
+
return names.sort().map((name) => {
|
|
602
|
+
const slug = slugify(name);
|
|
603
|
+
const isActive = slug === currentSlug;
|
|
604
|
+
return `<a href="${basePath}${slug}.html" class="${isActive ? "active" : ""}">${escapeHtml(name)}</a>`;
|
|
605
|
+
}).join("\n");
|
|
606
|
+
}
|
|
607
|
+
if (!hasAnyCollections) {
|
|
608
|
+
const links = renderLinks(visibleEntries.map(([name]) => name));
|
|
609
|
+
return `<div class="sidebar-heading">Components</div>
|
|
523
610
|
${links}`;
|
|
611
|
+
}
|
|
612
|
+
const sections = [];
|
|
613
|
+
for (const [colName, names] of collectionMap) {
|
|
614
|
+
if (names.length === 0) continue;
|
|
615
|
+
sections.push(
|
|
616
|
+
`<div class="sidebar-collection-header">${escapeHtml(colName)}</div>
|
|
617
|
+
${renderLinks(names)}`
|
|
618
|
+
);
|
|
619
|
+
}
|
|
620
|
+
if (ungrouped.length > 0) {
|
|
621
|
+
sections.push(
|
|
622
|
+
`<div class="sidebar-collection-header">Ungrouped</div>
|
|
623
|
+
${renderLinks(ungrouped)}`
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
return sections.join("\n");
|
|
524
627
|
}
|
|
525
628
|
function htmlShell(options) {
|
|
526
629
|
const { title, body, sidebar, onThisPage, basePath } = options;
|
|
@@ -619,8 +722,11 @@ function renderPlayground(name, data) {
|
|
|
619
722
|
${props.map(([n, p]) => propTableRow(n, p)).join("\n ")}
|
|
620
723
|
</tbody>
|
|
621
724
|
</table>` : `<p style="color:var(--color-muted);font-size:13px">No props defined.</p>`;
|
|
725
|
+
const renderW = render?.width != null ? render.width : void 0;
|
|
726
|
+
const renderH = render?.height != null ? render.height : void 0;
|
|
727
|
+
const renderSizeAttr = renderW != null && renderH != null ? ` width="${renderW}" height="${renderH}"` : "";
|
|
622
728
|
const renderHtml = render?.screenshot ? `<div class="render-preview">
|
|
623
|
-
<img src="data:image/png;base64,${render.screenshot}" alt="${escapeHtml(name)} render" />
|
|
729
|
+
<img src="data:image/png;base64,${render.screenshot}" alt="${escapeHtml(name)} render"${renderSizeAttr} />
|
|
624
730
|
</div>` : notGenerated("Render not generated. Run scope render to produce screenshots.");
|
|
625
731
|
return sectionWrap(
|
|
626
732
|
"playground",
|
|
@@ -644,7 +750,7 @@ function renderMatrix(name, data) {
|
|
|
644
750
|
const cols = Math.ceil(Math.sqrt(cells.length));
|
|
645
751
|
const cellsHtml = cells.map((cell) => {
|
|
646
752
|
const label = cell.axisValues.join(" / ");
|
|
647
|
-
const imgHtml = cell.screenshot ? `<img src="data:image/png;base64,${cell.screenshot}" alt="${escapeHtml(label)}" />` : `<span style="color:var(--color-muted);font-size:11px">${cell.error ? escapeHtml(cell.error) : "failed"}</span>`;
|
|
753
|
+
const imgHtml = cell.screenshot ? `<img class="scope-screenshot" src="data:image/png;base64,${cell.screenshot}" alt="${escapeHtml(label)}" />` : `<span style="color:var(--color-muted);font-size:11px">${cell.error ? escapeHtml(cell.error) : "failed"}</span>`;
|
|
648
754
|
return `<div class="matrix-cell">${imgHtml}<div class="cell-label">${escapeHtml(label)}</div></div>`;
|
|
649
755
|
}).join("\n");
|
|
650
756
|
const grid = `<div class="matrix-grid" style="grid-template-columns: repeat(${cols}, 1fr)">
|
|
@@ -745,25 +851,56 @@ function renderXRay(name, data) {
|
|
|
745
851
|
);
|
|
746
852
|
}
|
|
747
853
|
const dom = render.dom;
|
|
854
|
+
const nodeStylesMap = {};
|
|
855
|
+
if (render.computedStyles) {
|
|
856
|
+
for (const [key, styles] of Object.entries(render.computedStyles)) {
|
|
857
|
+
const m = key.match(/^#node-(\d+)$/);
|
|
858
|
+
if (m?.[1] !== void 0) nodeStylesMap[parseInt(m[1], 10)] = styles;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
const nodeStylesJson = escapeHtml(JSON.stringify(nodeStylesMap));
|
|
748
862
|
const treeHtml = `<div class="dom-tree">${renderDOMTree(dom.tree)}</div>`;
|
|
749
|
-
const
|
|
750
|
-
|
|
751
|
-
<
|
|
752
|
-
<
|
|
753
|
-
<
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
)
|
|
758
|
-
).join("\n ")}
|
|
759
|
-
</tbody>
|
|
863
|
+
const stylesPanelHtml = `
|
|
864
|
+
<div id="xray-styles-panel-${escapeHtml(name)}" class="xray-styles-panel" style="display:none;margin-top:16px;border:1px solid var(--color-border);border-radius:6px;overflow:hidden">
|
|
865
|
+
<div class="xray-styles-header" style="padding:8px 12px;background:var(--color-surface-2);font-size:12px;font-weight:600;color:var(--color-muted);display:flex;justify-content:space-between;align-items:center">
|
|
866
|
+
<span id="xray-styles-label-${escapeHtml(name)}">\u2014 no node selected \u2014</span>
|
|
867
|
+
<button onclick="document.getElementById('xray-styles-panel-${escapeHtml(name)}').style.display='none'" style="background:none;border:none;cursor:pointer;color:var(--color-muted);font-size:16px;line-height:1">\xD7</button>
|
|
868
|
+
</div>
|
|
869
|
+
<table class="token-table" style="margin:0">
|
|
870
|
+
<thead><tr><th>Property</th><th>Value</th></tr></thead>
|
|
871
|
+
<tbody id="xray-styles-body-${escapeHtml(name)}"></tbody>
|
|
760
872
|
</table>
|
|
761
|
-
</
|
|
873
|
+
</div>
|
|
874
|
+
<script>
|
|
875
|
+
(function() {
|
|
876
|
+
var nodeStyles = JSON.parse(${nodeStylesJson});
|
|
877
|
+
var container = document.currentScript.parentElement;
|
|
878
|
+
container.addEventListener("click", function(e) {
|
|
879
|
+
var el = e.target.closest("[data-node-id]");
|
|
880
|
+
if (!el) return;
|
|
881
|
+
var id = parseInt(el.getAttribute("data-node-id"), 10);
|
|
882
|
+
var styles = nodeStyles[id];
|
|
883
|
+
if (!styles) return;
|
|
884
|
+
var panel = document.getElementById("xray-styles-panel-${escapeHtml(name)}");
|
|
885
|
+
var label = document.getElementById("xray-styles-label-${escapeHtml(name)}");
|
|
886
|
+
var body = document.getElementById("xray-styles-body-${escapeHtml(name)}");
|
|
887
|
+
var tag = el.tagName === "DETAILS" ? el.querySelector("summary .dom-tag-open") : el;
|
|
888
|
+
label.textContent = tag ? tag.textContent.trim().slice(0, 60) : "node #" + id;
|
|
889
|
+
body.innerHTML = Object.entries(styles).map(function(e) {
|
|
890
|
+
return "<tr><td>" + e[0] + "</td><td style="font-family:monospace">" + e[1] + "</td></tr>";
|
|
891
|
+
}).join("");
|
|
892
|
+
panel.style.display = "block";
|
|
893
|
+
// Highlight selected node
|
|
894
|
+
container.querySelectorAll(".dom-node-selected").forEach(function(n) { n.classList.remove("dom-node-selected"); });
|
|
895
|
+
el.classList.add("dom-node-selected");
|
|
896
|
+
});
|
|
897
|
+
})();
|
|
898
|
+
</script>`;
|
|
762
899
|
return sectionWrap(
|
|
763
900
|
"x-ray",
|
|
764
901
|
"X-Ray",
|
|
765
|
-
`DOM structure \u2014 ${dom.elementCount} elements.`,
|
|
766
|
-
`${treeHtml}${
|
|
902
|
+
`DOM structure \u2014 ${dom.elementCount} elements. Click any element to inspect its computed styles.`,
|
|
903
|
+
`${treeHtml}${stylesPanelHtml}`
|
|
767
904
|
);
|
|
768
905
|
}
|
|
769
906
|
function renderTokens(name, data) {
|
|
@@ -849,9 +986,11 @@ function renderComposition(name, data) {
|
|
|
849
986
|
if (items.length === 0) {
|
|
850
987
|
return `<div class="comp-list"><h3>${escapeHtml(title)}</h3><p style="color:var(--color-muted);font-size:12px">None</p></div>`;
|
|
851
988
|
}
|
|
852
|
-
const liItems = items.map(
|
|
853
|
-
|
|
854
|
-
|
|
989
|
+
const liItems = items.map((n) => {
|
|
990
|
+
const compData = data.manifest.components[n];
|
|
991
|
+
const internalBadge = compData?.internal === true ? `<span class="badge-internal">internal</span>` : "";
|
|
992
|
+
return `<li><a href="${data.options.basePath}${slugify(n)}.html">${escapeHtml(n)}</a>${internalBadge}</li>`;
|
|
993
|
+
}).join("");
|
|
855
994
|
return `<div class="comp-list"><h3>${escapeHtml(title)}</h3><ul>${liItems}</ul></div>`;
|
|
856
995
|
}
|
|
857
996
|
return sectionWrap(
|
|
@@ -905,8 +1044,7 @@ function renderComponentDetail(name, data) {
|
|
|
905
1044
|
const id = s.toLowerCase().replace(/\s+/g, "-");
|
|
906
1045
|
return `<a href="#${id}">${escapeHtml(s)}</a>`;
|
|
907
1046
|
}).join("\n");
|
|
908
|
-
const
|
|
909
|
-
const sidebar = sidebarLinks(componentNames, slug, data.options.basePath);
|
|
1047
|
+
const sidebar = sidebarLinks(data, slug);
|
|
910
1048
|
return htmlShell({
|
|
911
1049
|
title: `${name} \u2014 ${data.options.title}`,
|
|
912
1050
|
body,
|
|
@@ -917,17 +1055,45 @@ function renderComponentDetail(name, data) {
|
|
|
917
1055
|
}
|
|
918
1056
|
|
|
919
1057
|
// src/templates/component-index.ts
|
|
1058
|
+
function renderCard(name, data) {
|
|
1059
|
+
const component = data.manifest.components[name];
|
|
1060
|
+
if (!component) return "";
|
|
1061
|
+
const slug = slugify(name);
|
|
1062
|
+
const render = data.renders.get(name);
|
|
1063
|
+
const propCount = Object.keys(component.props).length;
|
|
1064
|
+
const hookCount = component.detectedHooks.length;
|
|
1065
|
+
const previewHtml = render?.screenshot ? `<img class="scope-screenshot" src="data:image/png;base64,${render.screenshot}" alt="${escapeHtml(name)}" />` : `<span class="no-preview">No preview</span>`;
|
|
1066
|
+
return `<a class="component-card" href="${data.options.basePath}${slug}.html" data-name="${escapeHtml(name.toLowerCase())}">
|
|
1067
|
+
<div class="card-preview">${previewHtml}</div>
|
|
1068
|
+
<div class="card-body">
|
|
1069
|
+
<div class="card-name">${escapeHtml(name)}</div>
|
|
1070
|
+
<div class="card-meta">
|
|
1071
|
+
<span>${propCount} props</span>
|
|
1072
|
+
<span class="badge ${component.complexityClass}" style="font-size:10px">${escapeHtml(component.complexityClass)}</span>
|
|
1073
|
+
${hookCount > 0 ? `<span>${hookCount} hooks</span>` : ""}
|
|
1074
|
+
</div>
|
|
1075
|
+
</div>
|
|
1076
|
+
</a>`;
|
|
1077
|
+
}
|
|
920
1078
|
function renderComponentIndex(data) {
|
|
921
|
-
const
|
|
922
|
-
const
|
|
923
|
-
const
|
|
924
|
-
const
|
|
925
|
-
const
|
|
1079
|
+
const allComponents = Object.entries(data.manifest.components);
|
|
1080
|
+
const collections = data.manifest.collections ?? [];
|
|
1081
|
+
const visibleComponents = allComponents.filter(([, c]) => !c.internal);
|
|
1082
|
+
const totalCount = allComponents.length;
|
|
1083
|
+
const visibleCount = visibleComponents.length;
|
|
1084
|
+
const collectionCount = collections.length;
|
|
1085
|
+
const simpleCount = visibleComponents.filter(([, c]) => c.complexityClass === "simple").length;
|
|
1086
|
+
const complexCount = visibleComponents.filter(([, c]) => c.complexityClass === "complex").length;
|
|
1087
|
+
const memoizedCount = visibleComponents.filter(([, c]) => c.memoized).length;
|
|
926
1088
|
const statsGrid = `<div class="stats-grid">
|
|
927
1089
|
<div class="stat-card">
|
|
928
1090
|
<div class="stat-label">Total Components</div>
|
|
929
1091
|
<div class="stat-value">${totalCount}</div>
|
|
930
1092
|
</div>
|
|
1093
|
+
<div class="stat-card">
|
|
1094
|
+
<div class="stat-label">Collections</div>
|
|
1095
|
+
<div class="stat-value">${collectionCount}</div>
|
|
1096
|
+
</div>
|
|
931
1097
|
<div class="stat-card">
|
|
932
1098
|
<div class="stat-label">Simple</div>
|
|
933
1099
|
<div class="stat-value">${simpleCount}</div>
|
|
@@ -941,25 +1107,54 @@ function renderComponentIndex(data) {
|
|
|
941
1107
|
<div class="stat-value">${memoizedCount}</div>
|
|
942
1108
|
</div>
|
|
943
1109
|
</div>`;
|
|
944
|
-
const
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
1110
|
+
const collectionMap = /* @__PURE__ */ new Map();
|
|
1111
|
+
for (const col of collections) {
|
|
1112
|
+
collectionMap.set(col.name, []);
|
|
1113
|
+
}
|
|
1114
|
+
const ungrouped = [];
|
|
1115
|
+
for (const [name, component] of visibleComponents) {
|
|
1116
|
+
if (component.collection) {
|
|
1117
|
+
if (!collectionMap.has(component.collection)) {
|
|
1118
|
+
collectionMap.set(component.collection, []);
|
|
1119
|
+
}
|
|
1120
|
+
collectionMap.get(component.collection)?.push(name);
|
|
1121
|
+
} else {
|
|
1122
|
+
ungrouped.push(name);
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
const hasCollections = collectionCount > 0 || visibleComponents.some(([, c]) => c.collection);
|
|
1126
|
+
let cardSections;
|
|
1127
|
+
if (!hasCollections) {
|
|
1128
|
+
const cards = visibleComponents.sort(([a], [b]) => a.localeCompare(b)).map(([name]) => renderCard(name, data)).join("\n");
|
|
1129
|
+
cardSections = `<div class="component-grid" id="component-grid">${cards}</div>`;
|
|
1130
|
+
} else {
|
|
1131
|
+
const sectionParts = [];
|
|
1132
|
+
for (const col of collections) {
|
|
1133
|
+
const names = collectionMap.get(col.name) ?? [];
|
|
1134
|
+
if (names.length === 0) continue;
|
|
1135
|
+
const collectionConfig = collections.find((c) => c.name === col.name);
|
|
1136
|
+
const descHtml = collectionConfig?.description ? `<p>${escapeHtml(collectionConfig.description)}</p>` : "";
|
|
1137
|
+
const cards = names.sort().map((name) => renderCard(name, data)).join("\n");
|
|
1138
|
+
sectionParts.push(`<div class="collection-section">
|
|
1139
|
+
<div class="collection-section-header">
|
|
1140
|
+
<h2>${escapeHtml(col.name)}</h2>
|
|
1141
|
+
${descHtml}
|
|
959
1142
|
</div>
|
|
960
|
-
</
|
|
961
|
-
|
|
962
|
-
|
|
1143
|
+
<div class="component-grid">${cards}</div>
|
|
1144
|
+
</div>`);
|
|
1145
|
+
}
|
|
1146
|
+
if (ungrouped.length > 0) {
|
|
1147
|
+
const cards = ungrouped.sort().map((name) => renderCard(name, data)).join("\n");
|
|
1148
|
+
sectionParts.push(`<div class="collection-section">
|
|
1149
|
+
<div class="collection-section-header">
|
|
1150
|
+
<h2>Ungrouped</h2>
|
|
1151
|
+
<p>Components not assigned to a collection.</p>
|
|
1152
|
+
</div>
|
|
1153
|
+
<div class="component-grid">${cards}</div>
|
|
1154
|
+
</div>`);
|
|
1155
|
+
}
|
|
1156
|
+
cardSections = `<div id="component-grid">${sectionParts.join("\n")}</div>`;
|
|
1157
|
+
}
|
|
963
1158
|
const filterScript = `<script>
|
|
964
1159
|
(function () {
|
|
965
1160
|
var grid = document.getElementById('component-grid');
|
|
@@ -981,12 +1176,11 @@ function renderComponentIndex(data) {
|
|
|
981
1176
|
</script>`;
|
|
982
1177
|
const header = `<div class="index-header">
|
|
983
1178
|
<h1>${escapeHtml(data.options.title)}</h1>
|
|
984
|
-
<p>${
|
|
1179
|
+
<p>${visibleCount} component${visibleCount === 1 ? "" : "s"} analysed</p>
|
|
985
1180
|
<input class="search-box" type="search" id="index-search" placeholder="Filter components\u2026" style="margin-top:12px" />
|
|
986
1181
|
</div>`;
|
|
987
|
-
const body = `${header}${statsGrid}${
|
|
988
|
-
const
|
|
989
|
-
const sidebar = sidebarLinks(componentNames, null, data.options.basePath);
|
|
1182
|
+
const body = `${header}${statsGrid}${cardSections}${filterScript}`;
|
|
1183
|
+
const sidebar = sidebarLinks(data, null);
|
|
990
1184
|
const onThisPage = `<a href="#top">Overview</a>
|
|
991
1185
|
<a href="#component-grid">Components</a>`;
|
|
992
1186
|
return htmlShell({
|
|
@@ -1096,8 +1290,7 @@ function renderDashboard(data) {
|
|
|
1096
1290
|
<p style="color:var(--color-muted);font-size:14px">Overview of all ${totalCount} analysed components.</p>
|
|
1097
1291
|
</div>`;
|
|
1098
1292
|
const body = `${header}${statsGrid}${complexitySection}${topPropsSection}${complianceSection}`;
|
|
1099
|
-
const
|
|
1100
|
-
const sidebar = sidebarLinks(componentNames, null, data.options.basePath);
|
|
1293
|
+
const sidebar = sidebarLinks(data, null);
|
|
1101
1294
|
const onThisPage = `<a href="#top">Overview</a>
|
|
1102
1295
|
<a href="#complexity">Complexity</a>
|
|
1103
1296
|
<a href="#top-props">Top by Props</a>
|