Add collapsible inspector sections with persisted state

This commit is contained in:
Rbanh 2026-02-18 20:36:01 -05:00
parent c02b14649e
commit bf64195c45
3 changed files with 84 additions and 8 deletions

View File

@ -1,6 +1,7 @@
const GRID = 20;
const SNAPSHOTS_KEY = "schemeta:snapshots:v2";
const SCHEMA_URL = "/schemeta.schema.json";
const INSPECTOR_SECTIONS_KEY = "schemeta:inspector-sections:v1";
const NET_CLASSES = ["power", "ground", "signal", "analog", "differential", "clock", "bus"];
const PIN_SIDES = ["left", "right", "top", "bottom"];
const PIN_TYPES = ["power_in", "power_out", "input", "output", "bidirectional", "passive", "analog", "ground"];
@ -53,9 +54,13 @@ const el = {
compileStatus: document.getElementById("compileStatus"),
selectedSummary: document.getElementById("selectedSummary"),
componentEditor: document.getElementById("componentEditor"),
componentSection: document.getElementById("componentSection"),
symbolEditor: document.getElementById("symbolEditor"),
symbolSection: document.getElementById("symbolSection"),
pinEditor: document.getElementById("pinEditor"),
pinSection: document.getElementById("pinSection"),
netEditor: document.getElementById("netEditor"),
netSection: document.getElementById("netSection"),
instRefInput: document.getElementById("instRefInput"),
instValueInput: document.getElementById("instValueInput"),
instNotesInput: document.getElementById("instNotesInput"),
@ -1653,6 +1658,33 @@ function sortKeysDeep(value) {
return value;
}
function saveInspectorSectionState() {
const stateObj = {
component: Boolean(el.componentSection?.open),
symbol: Boolean(el.symbolSection?.open),
pin: Boolean(el.pinSection?.open),
net: Boolean(el.netSection?.open)
};
localStorage.setItem(INSPECTOR_SECTIONS_KEY, JSON.stringify(stateObj));
}
function loadInspectorSectionState() {
try {
const raw = localStorage.getItem(INSPECTOR_SECTIONS_KEY);
if (!raw) {
return;
}
const parsed = JSON.parse(raw);
if (typeof parsed !== "object" || !parsed) {
return;
}
if (el.componentSection) el.componentSection.open = parsed.component !== false;
if (el.symbolSection) el.symbolSection.open = parsed.symbol !== false;
if (el.pinSection) el.pinSection.open = parsed.pin !== false;
if (el.netSection) el.netSection.open = parsed.net !== false;
} catch {}
}
async function loadSchemaText() {
if (state.schemaText) {
return state.schemaText;
@ -1890,6 +1922,12 @@ function setupEvents() {
});
el.instanceList.addEventListener("scroll", renderInstances, { passive: true });
el.netList.addEventListener("scroll", renderNets, { passive: true });
[el.componentSection, el.symbolSection, el.pinSection, el.netSection].forEach((section) => {
if (!section) {
return;
}
section.addEventListener("toggle", saveInspectorSectionState);
});
el.instanceList.addEventListener("click", (evt) => {
const item = evt.target.closest("[data-ref-item]");
@ -2869,6 +2907,7 @@ function setupEvents() {
(async function init() {
setupEvents();
loadInspectorSectionState();
updateTransform();
const snapshots = JSON.parse(localStorage.getItem(SNAPSHOTS_KEY) ?? "[]");

View File

@ -72,6 +72,8 @@
<section>
<h2>Selected</h2>
<div id="selectedSummary" class="card">Click a component, net, or pin to inspect it.</div>
<details id="componentSection" class="editorSection" open>
<summary>Component</summary>
<div id="componentEditor" class="editorCard hidden">
<div class="editorGrid">
<label>Ref <input id="instRefInput" type="text" /></label>
@ -97,6 +99,9 @@
<button id="isolateSelectedComponentBtn">Isolate</button>
</div>
</div>
</details>
<details id="symbolSection" class="editorSection" open>
<summary>Symbol</summary>
<div id="symbolEditor" class="editorCard hidden">
<div id="symbolMeta" class="hintText"></div>
<div class="editorGrid">
@ -111,6 +116,9 @@
<div id="symbolValidation" class="hintText"></div>
<div id="symbolPinsList" class="miniList"></div>
</div>
</details>
<details id="pinSection" class="editorSection" open>
<summary>Pin</summary>
<div id="pinEditor" class="editorCard hidden">
<div id="pinMeta" class="hintText"></div>
<div class="editorGrid">
@ -167,6 +175,9 @@
</div>
<div id="pinConnections" class="miniList"></div>
</div>
</details>
<details id="netSection" class="editorSection" open>
<summary>Net</summary>
<div id="netEditor" class="editorCard hidden">
<div class="editorGrid">
<label>Name <input id="netNameInput" type="text" /></label>
@ -195,6 +206,7 @@
</div>
<div id="netNodesList" class="miniList"></div>
</div>
</details>
</section>
<section>

View File

@ -218,6 +218,31 @@ textarea {
gap: 8px;
}
.editorSection {
border: 1px solid var(--line);
border-radius: 8px;
margin-top: 8px;
background: #fff;
}
.editorSection > summary {
cursor: pointer;
list-style: none;
padding: 8px 10px;
font-size: 0.8rem;
font-weight: 700;
color: var(--ink);
border-bottom: 1px solid transparent;
}
.editorSection[open] > summary {
border-bottom-color: var(--line);
}
.editorSection > summary::-webkit-details-marker {
display: none;
}
.editorGrid {
display: grid;
grid-template-columns: 1fr 1fr;