|
|
|
|
@ -1312,7 +1312,7 @@ HTML = """<!doctype html>
|
|
|
|
|
.config-deleted-list { display: grid; gap: 5px; padding-top: 4px; border-top: 1px solid var(--ui-border); }
|
|
|
|
|
.config-deleted-list[hidden] { display: none !important; }
|
|
|
|
|
.config-restore-panel[hidden], .config-trash[hidden] { display: none !important; }
|
|
|
|
|
.config-canvas { position: relative; display: block; min-height: 760px; padding: 8px 6px 18px; overflow: auto; overscroll-behavior: contain; background: radial-gradient(circle at 12% 8%, color-mix(in srgb, var(--ui-accent) 7%, transparent), transparent 28%), linear-gradient(135deg, color-mix(in srgb, var(--ui-bg) 74%, var(--ui-panel)), var(--ui-bg)); }
|
|
|
|
|
.config-canvas { position: relative; display: block; min-height: 760px; padding: 8px 6px 18px; overflow: auto; overscroll-behavior: auto; background: radial-gradient(circle at 12% 8%, color-mix(in srgb, var(--ui-accent) 7%, transparent), transparent 28%), linear-gradient(135deg, color-mix(in srgb, var(--ui-bg) 74%, var(--ui-panel)), var(--ui-bg)); }
|
|
|
|
|
.config-canvas::before { content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none; opacity: .34; background-image: linear-gradient(color-mix(in srgb, var(--ui-text) 5%, transparent) 1px, transparent 1px), linear-gradient(90deg, color-mix(in srgb, var(--ui-text) 5%, transparent) 1px, transparent 1px); background-size: 28px 28px; mask-image: linear-gradient(to bottom, black, transparent 86%); }
|
|
|
|
|
.config-canvas > .config-block { position: absolute; z-index: 1; box-sizing: border-box; container: config-block / inline-size; margin: 0; min-width: 240px; min-height: 110px; border: 1px solid var(--ui-border) !important; border-radius: 14px; background: color-mix(in srgb, var(--ui-panel) 94%, var(--ui-accent)) !important; box-shadow: 0 8px 22px color-mix(in srgb, var(--ui-bg) 22%, transparent); overflow: auto; transition: border-color .2s ease, box-shadow .2s ease, opacity .2s ease, transform .2s ease; }
|
|
|
|
|
body[data-card-style="flat"] .config-canvas > .config-block { box-shadow: none; border-radius: 8px; }
|
|
|
|
|
@ -1485,7 +1485,7 @@ HTML = """<!doctype html>
|
|
|
|
|
.network-workspace.has-structure > .network-restore-panel { grid-column: 1; border-right: 1px solid var(--ui-border); border-bottom: 0; }
|
|
|
|
|
.network-workspace.has-structure > .network-canvas { grid-column: 2; }
|
|
|
|
|
.network-restore-panel { min-height: 0; max-height: calc(100vh - 128px); }
|
|
|
|
|
.network-canvas { position: relative; display: block; min-height: 720px; padding: 14px; overflow: auto; background: radial-gradient(circle at 10% 0%, color-mix(in srgb, var(--ui-accent) 7%, transparent), transparent 32%), color-mix(in srgb, var(--ui-bg) 74%, var(--ui-panel)); }
|
|
|
|
|
.network-canvas { position: relative; display: block; min-height: 720px; padding: 14px; overflow: auto; overscroll-behavior: auto; background: radial-gradient(circle at 10% 0%, color-mix(in srgb, var(--ui-accent) 7%, transparent), transparent 32%), color-mix(in srgb, var(--ui-bg) 74%, var(--ui-panel)); }
|
|
|
|
|
.network-block { --block-scale: 1; position: absolute; min-width: 240px; min-height: 110px; margin: 0; padding: 14px; border: 1px solid var(--ui-border) !important; border-radius: 14px !important; background: color-mix(in srgb, var(--ui-panel) 94%, var(--ui-accent)) !important; box-shadow: 0 8px 22px color-mix(in srgb, var(--ui-bg) 20%, transparent); overflow: auto; transition: border-color .2s ease, box-shadow .2s ease, transform .2s ease; cursor: grab; touch-action: none; }
|
|
|
|
|
.network-block:hover { border-color: color-mix(in srgb, var(--ui-accent) 48%, var(--ui-border)) !important; transform: translateY(-2px); }
|
|
|
|
|
.network-block.is-selected { border-color: color-mix(in srgb, var(--ui-accent) 70%, var(--ui-border)) !important; box-shadow: 0 0 0 2px color-mix(in srgb, var(--ui-accent) 12%, transparent), 0 8px 22px color-mix(in srgb, var(--ui-bg) 20%, transparent); }
|
|
|
|
|
@ -2661,6 +2661,7 @@ HTML = """<!doctype html>
|
|
|
|
|
function initConfigCanvas() {
|
|
|
|
|
configCanvas = $('controlForm');
|
|
|
|
|
if (!configCanvas) return;
|
|
|
|
|
enableCanvasWheel(configCanvas, '.config-block');
|
|
|
|
|
configLayout = readConfigLayout();
|
|
|
|
|
configBlocks = Array.from(configCanvas.children).filter(node => node.matches('details[data-section]'));
|
|
|
|
|
Object.entries(configLayout).forEach(([key, entry]) => {
|
|
|
|
|
@ -2714,6 +2715,20 @@ HTML = """<!doctype html>
|
|
|
|
|
selectConfigBlock(selectedConfigBlock);
|
|
|
|
|
$('configContentScale')?.addEventListener('input', event => applyConfigContentScale(event.target.value));
|
|
|
|
|
}
|
|
|
|
|
function enableCanvasWheel(canvas, blockSelector) {
|
|
|
|
|
canvas.addEventListener('wheel', event => {
|
|
|
|
|
if (event.defaultPrevented || event.target instanceof Element && event.target.closest(blockSelector)) return;
|
|
|
|
|
const maxLeft = Math.max(0, canvas.scrollWidth - canvas.clientWidth);
|
|
|
|
|
const maxTop = Math.max(0, canvas.scrollHeight - canvas.clientHeight);
|
|
|
|
|
if (!maxLeft && !maxTop) return;
|
|
|
|
|
const left = Math.max(0, Math.min(maxLeft, canvas.scrollLeft + event.deltaX));
|
|
|
|
|
const top = Math.max(0, Math.min(maxTop, canvas.scrollTop + event.deltaY));
|
|
|
|
|
if (left === canvas.scrollLeft && top === canvas.scrollTop) return;
|
|
|
|
|
canvas.scrollLeft = left;
|
|
|
|
|
canvas.scrollTop = top;
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
}, {passive: false});
|
|
|
|
|
}
|
|
|
|
|
let networkCanvas = null;
|
|
|
|
|
let networkBlocks = [];
|
|
|
|
|
let networkLayout = {};
|
|
|
|
|
@ -3137,6 +3152,7 @@ HTML = """<!doctype html>
|
|
|
|
|
function initNetworkCanvas() {
|
|
|
|
|
networkCanvas = $('networkCanvas');
|
|
|
|
|
if (!networkCanvas) return;
|
|
|
|
|
enableCanvasWheel(networkCanvas, '.network-block');
|
|
|
|
|
networkLayout = readNetworkLayout();
|
|
|
|
|
networkBlocks = Array.from(networkCanvas.children).filter(node => node.classList.contains('network-block'));
|
|
|
|
|
Object.entries(networkLayout).forEach(([key, entry]) => {
|
|
|
|
|
|