Reshape the editor frame to OpenCut's layout (Assets | Preview | Properties over a full-width Timeline), keeping every panel's mount point so existing modules keep working: - index.html: single horizontal main-row of three resizable columns; preview is the flexible center, Assets/Properties flank it. Plan strip removed (recipe now lives in the Properties column per the one-timeline model). - styles.css: new workspace layout + graceful column-toggle degradation; floating-window + Composer-button styling. - app.js / layout.js: rewire splitters (--media-w / --properties-w / --timeline-h) and column-visibility chips for the new arrangement. - floating_window.js: reusable OS-style window (drag / minimize-to-pill / maximize / close); foundation Models & Engine settings can adopt later. - composer.js: Composer window hosting Characters / Shortcuts / Split markers, toggled by a header "Composer" button. - remove plan_strip.js (superseded). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
84 lines
2.6 KiB
JavaScript
84 lines
2.6 KiB
JavaScript
// Column visibility: Assets / Preview / Properties toggles (chips in the timeline header).
|
|
// Canonical layout is all three side-by-side; collapsing a column gives its space to the rest.
|
|
(function () {
|
|
const KEY = "funpack_dock_panels";
|
|
const PANELS = [
|
|
{ id: "media", label: "Assets" },
|
|
{ id: "preview", label: "Preview" },
|
|
{ id: "settings", label: "Properties" },
|
|
];
|
|
|
|
const mainRow = document.getElementById("main-row");
|
|
const tabsEl = document.getElementById("dock-tabs");
|
|
if (!mainRow || !tabsEl) return;
|
|
|
|
function load() {
|
|
try {
|
|
const raw = localStorage.getItem(KEY);
|
|
if (raw) {
|
|
const p = JSON.parse(raw);
|
|
return {
|
|
media: p.media !== false,
|
|
preview: p.preview !== false,
|
|
settings: p.settings !== false,
|
|
};
|
|
}
|
|
} catch (_) {}
|
|
return { media: true, preview: true, settings: true };
|
|
}
|
|
|
|
let state = load();
|
|
|
|
function save() {
|
|
localStorage.setItem(KEY, JSON.stringify(state));
|
|
}
|
|
|
|
const panelEls = {
|
|
media: document.getElementById("media-zone"),
|
|
preview: document.getElementById("preview-zone"),
|
|
settings: document.getElementById("inspector-zone"),
|
|
};
|
|
|
|
function setVis(el, show) {
|
|
if (!el) return;
|
|
if (show) el.removeAttribute("hidden"); else el.setAttribute("hidden", "");
|
|
}
|
|
|
|
function apply() {
|
|
// CSS reads these data attrs to size columns and hide the dividing splitters.
|
|
mainRow.dataset.media = state.media ? "1" : "0";
|
|
mainRow.dataset.preview = state.preview ? "1" : "0";
|
|
mainRow.dataset.settings = state.settings ? "1" : "0";
|
|
setVis(panelEls.media, state.media);
|
|
setVis(panelEls.preview, state.preview);
|
|
setVis(panelEls.settings, state.settings);
|
|
tabsEl.querySelectorAll(".dock-tab").forEach((btn) => {
|
|
const id = btn.dataset.panel;
|
|
const on = !!state[id];
|
|
btn.classList.toggle("on", on);
|
|
btn.setAttribute("aria-pressed", on ? "true" : "false");
|
|
});
|
|
}
|
|
|
|
function toggle(id) {
|
|
const on = Object.values(state).filter(Boolean).length;
|
|
if (state[id] && on <= 1) return; // keep at least one panel visible
|
|
state[id] = !state[id];
|
|
save();
|
|
apply();
|
|
}
|
|
|
|
PANELS.forEach(({ id, label }) => {
|
|
const btn = document.createElement("button");
|
|
btn.type = "button";
|
|
btn.className = "dock-tab";
|
|
btn.dataset.panel = id;
|
|
btn.textContent = label;
|
|
btn.title = `Show or hide ${label}`;
|
|
btn.onclick = () => toggle(id);
|
|
tabsEl.append(btn);
|
|
});
|
|
|
|
apply();
|
|
window.DockLayout = { get: () => ({ ...state }), set: (patch) => { state = { ...state, ...patch }; save(); apply(); } };
|
|
})(); |