Add collapsible inspector sections with persisted state
This commit is contained in:
parent
c02b14649e
commit
bf64195c45
@ -1,6 +1,7 @@
|
|||||||
const GRID = 20;
|
const GRID = 20;
|
||||||
const SNAPSHOTS_KEY = "schemeta:snapshots:v2";
|
const SNAPSHOTS_KEY = "schemeta:snapshots:v2";
|
||||||
const SCHEMA_URL = "/schemeta.schema.json";
|
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 NET_CLASSES = ["power", "ground", "signal", "analog", "differential", "clock", "bus"];
|
||||||
const PIN_SIDES = ["left", "right", "top", "bottom"];
|
const PIN_SIDES = ["left", "right", "top", "bottom"];
|
||||||
const PIN_TYPES = ["power_in", "power_out", "input", "output", "bidirectional", "passive", "analog", "ground"];
|
const PIN_TYPES = ["power_in", "power_out", "input", "output", "bidirectional", "passive", "analog", "ground"];
|
||||||
@ -53,9 +54,13 @@ const el = {
|
|||||||
compileStatus: document.getElementById("compileStatus"),
|
compileStatus: document.getElementById("compileStatus"),
|
||||||
selectedSummary: document.getElementById("selectedSummary"),
|
selectedSummary: document.getElementById("selectedSummary"),
|
||||||
componentEditor: document.getElementById("componentEditor"),
|
componentEditor: document.getElementById("componentEditor"),
|
||||||
|
componentSection: document.getElementById("componentSection"),
|
||||||
symbolEditor: document.getElementById("symbolEditor"),
|
symbolEditor: document.getElementById("symbolEditor"),
|
||||||
|
symbolSection: document.getElementById("symbolSection"),
|
||||||
pinEditor: document.getElementById("pinEditor"),
|
pinEditor: document.getElementById("pinEditor"),
|
||||||
|
pinSection: document.getElementById("pinSection"),
|
||||||
netEditor: document.getElementById("netEditor"),
|
netEditor: document.getElementById("netEditor"),
|
||||||
|
netSection: document.getElementById("netSection"),
|
||||||
instRefInput: document.getElementById("instRefInput"),
|
instRefInput: document.getElementById("instRefInput"),
|
||||||
instValueInput: document.getElementById("instValueInput"),
|
instValueInput: document.getElementById("instValueInput"),
|
||||||
instNotesInput: document.getElementById("instNotesInput"),
|
instNotesInput: document.getElementById("instNotesInput"),
|
||||||
@ -1653,6 +1658,33 @@ function sortKeysDeep(value) {
|
|||||||
return 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() {
|
async function loadSchemaText() {
|
||||||
if (state.schemaText) {
|
if (state.schemaText) {
|
||||||
return state.schemaText;
|
return state.schemaText;
|
||||||
@ -1890,6 +1922,12 @@ function setupEvents() {
|
|||||||
});
|
});
|
||||||
el.instanceList.addEventListener("scroll", renderInstances, { passive: true });
|
el.instanceList.addEventListener("scroll", renderInstances, { passive: true });
|
||||||
el.netList.addEventListener("scroll", renderNets, { 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) => {
|
el.instanceList.addEventListener("click", (evt) => {
|
||||||
const item = evt.target.closest("[data-ref-item]");
|
const item = evt.target.closest("[data-ref-item]");
|
||||||
@ -2869,6 +2907,7 @@ function setupEvents() {
|
|||||||
|
|
||||||
(async function init() {
|
(async function init() {
|
||||||
setupEvents();
|
setupEvents();
|
||||||
|
loadInspectorSectionState();
|
||||||
updateTransform();
|
updateTransform();
|
||||||
|
|
||||||
const snapshots = JSON.parse(localStorage.getItem(SNAPSHOTS_KEY) ?? "[]");
|
const snapshots = JSON.parse(localStorage.getItem(SNAPSHOTS_KEY) ?? "[]");
|
||||||
|
|||||||
@ -72,6 +72,8 @@
|
|||||||
<section>
|
<section>
|
||||||
<h2>Selected</h2>
|
<h2>Selected</h2>
|
||||||
<div id="selectedSummary" class="card">Click a component, net, or pin to inspect it.</div>
|
<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 id="componentEditor" class="editorCard hidden">
|
||||||
<div class="editorGrid">
|
<div class="editorGrid">
|
||||||
<label>Ref <input id="instRefInput" type="text" /></label>
|
<label>Ref <input id="instRefInput" type="text" /></label>
|
||||||
@ -97,6 +99,9 @@
|
|||||||
<button id="isolateSelectedComponentBtn">Isolate</button>
|
<button id="isolateSelectedComponentBtn">Isolate</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</details>
|
||||||
|
<details id="symbolSection" class="editorSection" open>
|
||||||
|
<summary>Symbol</summary>
|
||||||
<div id="symbolEditor" class="editorCard hidden">
|
<div id="symbolEditor" class="editorCard hidden">
|
||||||
<div id="symbolMeta" class="hintText"></div>
|
<div id="symbolMeta" class="hintText"></div>
|
||||||
<div class="editorGrid">
|
<div class="editorGrid">
|
||||||
@ -111,6 +116,9 @@
|
|||||||
<div id="symbolValidation" class="hintText"></div>
|
<div id="symbolValidation" class="hintText"></div>
|
||||||
<div id="symbolPinsList" class="miniList"></div>
|
<div id="symbolPinsList" class="miniList"></div>
|
||||||
</div>
|
</div>
|
||||||
|
</details>
|
||||||
|
<details id="pinSection" class="editorSection" open>
|
||||||
|
<summary>Pin</summary>
|
||||||
<div id="pinEditor" class="editorCard hidden">
|
<div id="pinEditor" class="editorCard hidden">
|
||||||
<div id="pinMeta" class="hintText"></div>
|
<div id="pinMeta" class="hintText"></div>
|
||||||
<div class="editorGrid">
|
<div class="editorGrid">
|
||||||
@ -167,6 +175,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="pinConnections" class="miniList"></div>
|
<div id="pinConnections" class="miniList"></div>
|
||||||
</div>
|
</div>
|
||||||
|
</details>
|
||||||
|
<details id="netSection" class="editorSection" open>
|
||||||
|
<summary>Net</summary>
|
||||||
<div id="netEditor" class="editorCard hidden">
|
<div id="netEditor" class="editorCard hidden">
|
||||||
<div class="editorGrid">
|
<div class="editorGrid">
|
||||||
<label>Name <input id="netNameInput" type="text" /></label>
|
<label>Name <input id="netNameInput" type="text" /></label>
|
||||||
@ -195,6 +206,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="netNodesList" class="miniList"></div>
|
<div id="netNodesList" class="miniList"></div>
|
||||||
</div>
|
</div>
|
||||||
|
</details>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
|||||||
@ -218,6 +218,31 @@ textarea {
|
|||||||
gap: 8px;
|
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 {
|
.editorGrid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user