feat: standardize Beam viewer environment settings

This commit is contained in:
CODEX
2026-06-05 17:04:11 +03:00
parent be2294d3fa
commit ef5b0a42a6
12 changed files with 556 additions and 194 deletions
+68 -37
View File
@@ -2,7 +2,7 @@ import { createSliderControl } from "./controls/slider.js";
import { createColorControl } from "./controls/color.js";
const defaultSettings = {
themeVersion: "v4-beam-lime",
themeVersion: "v5-drone-lime",
bgOuter: "#0f0f0f",
canvasTop: "#1c1c1c",
canvasBottom: "#1c1c1c",
@@ -10,27 +10,27 @@ const defaultSettings = {
loadingBottom: "#1c1c1c",
accent: "#ffea00",
accent2: "#ffea00",
templateFill: "#1c1c1c",
templateOutline: "#233044",
templateOutlineHover: "rgba(255,234,0,0.7)",
projectBtnFill: "#1c1c1c",
projectBtnBorder: "#233044",
projectBtnHover: "rgba(255,234,0,0.7)",
templateFill: "#292929",
templateOutline: "#292929",
templateOutlineHover: "#1c1c1c",
projectBtnFill: "#292929",
projectBtnBorder: "#292929",
projectBtnHover: "#1c1c1c",
modalBtnPrimary: "#c4ff67",
modalBtnSecondary: "#292929",
loaderColor: "#c4ff67",
templateGlow: 80,
toolbarBg: "#1c1c1c",
toolbarBg: "#292929",
toolbarBgActive: "#c4ff67",
toolbarBorder: "#233044",
toolbarOutline: "#c4ff67",
toolbarBorder: "#292929",
toolbarOutline: "#292929",
modalBg: "#1c1c1c",
modalBgAlpha: 1,
modalFocus: "#292929",
modalFocusAlpha: 1,
modalBorder: "#292929",
modalElement: "#292929",
modalElementOutline: "#2b2b2b",
modalFocusAlpha: 0.35,
modalBorder: "#1c1c1c",
modalElement: "#262626",
modalElementOutline: "#262626",
modalRadius: "14px",
border: "#233044",
text: "#e6edf3",
@@ -255,6 +255,40 @@ export function createSettingsMenu({ panel, controls = {}, onChange = null, onSh
return slider;
};
const addNumber = ({
parent,
label,
value,
min = 0,
max,
step = 1,
onChange,
}) => {
const row = document.createElement("div");
row.className = "color-row";
const lbl = document.createElement("div");
lbl.textContent = label;
const input = document.createElement("input");
input.className = "env-number-field";
input.type = "number";
input.value = value;
input.min = min;
input.step = step;
if (max !== undefined) {
input.max = max;
}
input.addEventListener("input", () => {
const nextValue = Number(input.value);
if (Number.isFinite(nextValue)) {
onChange?.(nextValue);
}
});
row.appendChild(lbl);
row.appendChild(input);
parent.appendChild(row);
return input;
};
const font = section("Фон");
addColor(font, "Фон внешний", "bgOuter");
addColor(font, "Фон холста верх", "canvasTop");
@@ -327,16 +361,17 @@ export function createSettingsMenu({ panel, controls = {}, onChange = null, onSh
const viewport = section("Viewport");
const addCheck = (label, checked, handler) => {
const row = document.createElement("div");
const row = document.createElement("label");
row.className = "checkbox-row";
const text = document.createElement("span");
text.className = "checkbox-row__label";
text.textContent = label;
const chk = document.createElement("input");
chk.type = "checkbox";
chk.checked = checked;
chk.addEventListener("change", () => handler(chk.checked));
const lbl = document.createElement("label");
lbl.textContent = label;
row.appendChild(text);
row.appendChild(chk);
row.appendChild(lbl);
viewport.appendChild(row);
};
if (controls.toggleEdges) addCheck("Рёбра", controls.toggleEdges.checked, (v) => { controls.toggleEdges.checked = v; controls.toggleEdges.dispatchEvent(new Event("change")); });
@@ -378,29 +413,25 @@ export function createSettingsMenu({ panel, controls = {}, onChange = null, onSh
});
addColor(modals, "Аутлайн", "modalBorder");
addColor(modals, "Фон элемента", "modalElement");
addColor(modals, "Контролы", "modalElement");
addColor(modals, "Аутлайн элемента", "modalElementOutline");
const radiusRow = document.createElement("div");
radiusRow.className = "color-row";
const radiusLbl = document.createElement("label");
radiusLbl.textContent = "Радиус";
const radiusInput = document.createElement("input");
radiusInput.type = "number";
radiusInput.value = parseInt(getComputedStyle(document.documentElement).getPropertyValue("--modal-radius")) || 14;
radiusInput.addEventListener("change", () => {
const val = `${radiusInput.value}px`;
document.documentElement.style.setProperty("--modal-radius", val);
setVal("modalRadius", val);
addNumber({
parent: modals,
label: "Радиус",
value: parseInt(getComputedStyle(document.documentElement).getPropertyValue("--modal-radius")) || 14,
min: 0,
max: 48,
step: 1,
onChange: (nextValue) => {
const val = `${Math.max(0, Math.min(48, Math.round(nextValue)))}px`;
setVal("modalRadius", val);
},
});
radiusRow.appendChild(radiusLbl);
radiusRow.appendChild(radiusInput);
radiusRow.appendChild(document.createElement("div"));
modals.appendChild(radiusRow);
panel.appendChild(modals);
const cube = section("Выделение объектов");
addColor(cube, "Подсветка объектов", "highlight");
panel.appendChild(cube);
const cube = section("Выделение объектов");
addColor(cube, "Подсветка объектов", "highlight");
panel.appendChild(cube);
};
const show = () => {
+15 -4
View File
@@ -62,16 +62,27 @@ export function createTemplatesMenu({ panel, fetchProjects, openProject, onShow,
header.className = "templates-header";
header.innerHTML = `<span class="templates-title">Проекты и шаблоны</span>`;
const actions = document.createElement("div");
actions.style.display = "flex";
actions.style.gap = "6px";
actions.className = "templates-actions";
const refresh = document.createElement("button");
refresh.className = "templates-close";
refresh.type = "button";
refresh.title = "Обновить список";
refresh.textContent = "↻";
refresh.setAttribute("aria-label", "Обновить список");
refresh.innerHTML = `
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
<path d="M12.2 5.3A4.4 4.4 0 0 0 4.7 3.4L3.6 4.5M3.7 2.1v2.4h2.4M3.8 10.7a4.4 4.4 0 0 0 7.5 1.9l1.1-1.1M12.3 13.9v-2.4H9.9" fill="none" stroke="currentColor" stroke-width="1.35" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
`;
refresh.addEventListener("click", () => load());
const closeBtn = document.createElement("button");
closeBtn.className = "templates-close";
closeBtn.textContent = "×";
closeBtn.type = "button";
closeBtn.setAttribute("aria-label", "Закрыть проекты и шаблоны");
closeBtn.innerHTML = `
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
<path d="M4.25 4.25 11.75 11.75M11.75 4.25 4.25 11.75" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path>
</svg>
`;
closeBtn.addEventListener("click", hide);
actions.appendChild(refresh);
actions.appendChild(closeBtn);