// Layout Settings panel (extracted from Sidebar.js in H4 4.1). // Owns the "Layout Settings" card: mode selector, THREADS/RELIEF sub-mode toggles, // thread spacing/width/thickness sliders, and the COMPARE linear-separation slider. // The relief controls (with the nested SAE + model sub-panels) live inside this card // and are composed from ReliefPanel to keep the DOM identical. import { STATE, CONFIG } from '../../core/State.js'; import { updateAllThreadPositions } from '../../visualizer/LayoutEngine.js'; import { updateThreadVisibility } from '../../visualizer/ThreadManager.js'; import { reliefVisualizerMarkup, wireReliefPanel } from './ReliefPanel.js'; import { wireModelPanel } from './ModelPanel.js'; /** @typedef {import('../types.js').PanelContext} PanelContext */ /** * Wire the layout-mode selector and thread sliders. The sub-mode toggles + relief * controls are wired by ReliefPanel. * @param {PanelContext} ctx * @returns {void} */ function wireLayoutControls(ctx) { const layoutSelector = document.getElementById('layout-mode-selector'); const blanketControls = document.getElementById('blanket-controls'); const compareControls = document.getElementById('compare-controls'); const spacingSlider = document.getElementById('thread-spacing-slider'); const widthSlider = document.getElementById('thread-width-slider'); const thicknessSlider = document.getElementById('thread-thickness-slider'); const compSpacingSlider = document.getElementById('compare-spacing-slider'); if (layoutSelector) { layoutSelector.onchange = (e) => { STATE.layoutMode = e.target.value; ctx.refresh.subModeUI?.(); updateAllThreadPositions(); updateThreadVisibility(); }; } if (spacingSlider) { spacingSlider.oninput = function() { CONFIG.threadSpacing = parseFloat(this.value); updateAllThreadPositions(); }; } if (widthSlider) { widthSlider.oninput = function() { CONFIG.threadWidth = parseFloat(this.value); updateAllThreadPositions(); }; } if (thicknessSlider) { thicknessSlider.oninput = function() { CONFIG.threadThickness = parseFloat(this.value); updateAllThreadPositions(); }; } if (compSpacingSlider) { compSpacingSlider.oninput = function() { CONFIG.compareSpacing = parseFloat(this.value); updateAllThreadPositions(); }; } } /** * Build the Layout Settings card (composing the relief controls) and schedule the * layout/model/relief wiring. Model is wired before relief so its refreshers are * published before the relief panel may invoke them. * @param {PanelContext} ctx * @returns {HTMLElement} */ export function buildLayoutPanel(ctx) { const layoutSection = document.createElement('div'); layoutSection.className = 'section-card'; layoutSection.innerHTML = `