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