This commit is contained in:
2026-03-10 15:16:39 -07:00
parent 31b94b818b
commit d3d96912c1
3 changed files with 121 additions and 13 deletions

View File

@@ -1687,7 +1687,7 @@
.cube-rotation-controls { .cube-rotation-controls {
display: grid; display: grid;
grid-template-columns: repeat(5, minmax(0, 1fr)); grid-template-columns: repeat(6, minmax(0, 1fr));
gap: 6px; gap: 6px;
padding: 8px 12px 6px; padding: 8px 12px 6px;
border-bottom: 1px solid #27272a; border-bottom: 1px solid #27272a;
@@ -1710,6 +1710,12 @@
color: #f4f4f5; color: #f4f4f5;
} }
.cube-rotation-btn[aria-pressed="true"] {
background: #312e81;
border-color: #818cf8;
color: #e0e7ff;
}
.cube-marker-mode-control { .cube-marker-mode-control {
grid-column: 1 / -1; grid-column: 1 / -1;
display: flex; display: flex;
@@ -2108,6 +2114,31 @@
border-bottom: none; border-bottom: none;
} }
.kab-layout.is-cube-focus {
grid-template-rows: minmax(0, 1fr);
}
.kab-layout.is-cube-focus > .kab-detail-panel {
display: none;
}
.kab-layout.is-cube-focus > .kab-tree-panel {
max-height: none;
min-height: 0;
height: 100%;
border-bottom: none;
}
.kab-layout.is-cube-focus .kab-tree-container {
align-items: center;
padding: 18px;
}
.kab-layout.is-cube-focus .kab-tree-container > .cube-svg {
width: min(100%, 760px);
max-height: calc(100vh - 190px);
}
.kab-tree-container { .kab-tree-container {
flex: 1; flex: 1;
padding: 12px 14px 16px; padding: 12px 14px 16px;

View File

@@ -15,7 +15,8 @@
showPrimalPoint: true, showPrimalPoint: true,
selectedConnectorId: null, selectedConnectorId: null,
selectedWallId: null, selectedWallId: null,
selectedEdgeId: null selectedEdgeId: null,
focusMode: false
}; };
const CUBE_VERTICES = [ const CUBE_VERTICES = [
@@ -126,12 +127,15 @@
function getElements() { function getElements() {
return { return {
cubeSectionEl: document.getElementById("cube-section"),
cubeLayoutEl: document.getElementById("cube-layout"),
viewContainerEl: document.getElementById("cube-view-container"), viewContainerEl: document.getElementById("cube-view-container"),
rotateLeftEl: document.getElementById("cube-rotate-left"), rotateLeftEl: document.getElementById("cube-rotate-left"),
rotateRightEl: document.getElementById("cube-rotate-right"), rotateRightEl: document.getElementById("cube-rotate-right"),
rotateUpEl: document.getElementById("cube-rotate-up"), rotateUpEl: document.getElementById("cube-rotate-up"),
rotateDownEl: document.getElementById("cube-rotate-down"), rotateDownEl: document.getElementById("cube-rotate-down"),
rotateResetEl: document.getElementById("cube-rotate-reset"), rotateResetEl: document.getElementById("cube-rotate-reset"),
focusToggleEl: document.getElementById("cube-focus-toggle"),
markerModeEl: document.getElementById("cube-marker-mode"), markerModeEl: document.getElementById("cube-marker-mode"),
connectorToggleEl: document.getElementById("cube-connector-toggle"), connectorToggleEl: document.getElementById("cube-connector-toggle"),
primalToggleEl: document.getElementById("cube-primal-toggle"), primalToggleEl: document.getElementById("cube-primal-toggle"),
@@ -301,23 +305,58 @@
return cubeMathUi.getEdgeDirectionLabelForWall(wallId, edgeId); return cubeMathUi.getEdgeDirectionLabelForWall(wallId, edgeId);
} }
function rotateAndRender(deltaX, deltaY) {
setRotation(state.rotationX + deltaX, state.rotationY + deltaY);
render(getElements());
}
function resetRotationAndRender() {
setRotation(18, -28);
render(getElements());
}
function isKeyboardEditableTarget(target) {
if (!(target instanceof HTMLElement)) {
return false;
}
if (target.isContentEditable) {
return true;
}
return ["INPUT", "TEXTAREA", "SELECT"].includes(target.tagName);
}
function isCubeFocusKeyboardModeActive(elements = getElements()) {
return Boolean(state.focusMode)
&& elements?.cubeSectionEl instanceof HTMLElement
&& !elements.cubeSectionEl.hidden;
}
function syncFocusControls(elements) {
if (elements?.cubeLayoutEl instanceof HTMLElement) {
elements.cubeLayoutEl.classList.toggle("is-cube-focus", Boolean(state.focusMode));
}
if (elements?.focusToggleEl instanceof HTMLButtonElement) {
elements.focusToggleEl.setAttribute("aria-pressed", state.focusMode ? "true" : "false");
elements.focusToggleEl.textContent = state.focusMode ? "Show Full Cube" : "Focus Cube";
}
}
function bindRotationControls(elements) { function bindRotationControls(elements) {
if (state.controlsBound) { if (state.controlsBound) {
return; return;
} }
const rotateAndRender = (deltaX, deltaY) => {
setRotation(state.rotationX + deltaX, state.rotationY + deltaY);
render(getElements());
};
elements.rotateLeftEl?.addEventListener("click", () => rotateAndRender(0, -9)); elements.rotateLeftEl?.addEventListener("click", () => rotateAndRender(0, -9));
elements.rotateRightEl?.addEventListener("click", () => rotateAndRender(0, 9)); elements.rotateRightEl?.addEventListener("click", () => rotateAndRender(0, 9));
elements.rotateUpEl?.addEventListener("click", () => rotateAndRender(-9, 0)); elements.rotateUpEl?.addEventListener("click", () => rotateAndRender(-9, 0));
elements.rotateDownEl?.addEventListener("click", () => rotateAndRender(9, 0)); elements.rotateDownEl?.addEventListener("click", () => rotateAndRender(9, 0));
elements.rotateResetEl?.addEventListener("click", () => { elements.rotateResetEl?.addEventListener("click", resetRotationAndRender);
setRotation(18, -28); elements.focusToggleEl?.addEventListener("click", () => {
render(getElements()); state.focusMode = !state.focusMode;
syncFocusControls(getElements());
}); });
elements.markerModeEl?.addEventListener("change", (event) => { elements.markerModeEl?.addEventListener("change", (event) => {
@@ -351,6 +390,41 @@
}); });
} }
document.addEventListener("keydown", (event) => {
if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey) {
return;
}
if (!isCubeFocusKeyboardModeActive(getElements())) {
return;
}
if (isKeyboardEditableTarget(event.target)) {
return;
}
switch (String(event.key || "").toLowerCase()) {
case "a":
event.preventDefault();
rotateAndRender(0, -9);
break;
case "d":
event.preventDefault();
rotateAndRender(0, 9);
break;
case "w":
event.preventDefault();
rotateAndRender(-9, 0);
break;
case "s":
event.preventDefault();
rotateAndRender(9, 0);
break;
default:
break;
}
});
state.controlsBound = true; state.controlsBound = true;
} }
@@ -620,6 +694,8 @@
} }
function render(elements) { function render(elements) {
syncFocusControls(elements);
if (elements?.markerModeEl) { if (elements?.markerModeEl) {
elements.markerModeEl.value = state.markerDisplayMode; elements.markerModeEl.value = state.markerDisplayMode;
} }

View File

@@ -16,7 +16,7 @@
<link rel="stylesheet" href="node_modules/@fontsource/amiri/arabic-400.css"> <link rel="stylesheet" href="node_modules/@fontsource/amiri/arabic-400.css">
<link rel="stylesheet" href="node_modules/@fontsource/amiri/arabic-700.css"> <link rel="stylesheet" href="node_modules/@fontsource/amiri/arabic-700.css">
<link rel="stylesheet" href="node_modules/@fontsource/noto-naskh-arabic/arabic-400.css"> <link rel="stylesheet" href="node_modules/@fontsource/noto-naskh-arabic/arabic-400.css">
<link rel="stylesheet" href="app/styles.css?v=20260310-now-stats-01"> <link rel="stylesheet" href="app/styles.css?v=20260310-cube-focus-01">
</head> </head>
<body> <body>
<div class="topbar"> <div class="topbar">
@@ -756,7 +756,7 @@
</section> </section>
<section id="cube-section" hidden> <section id="cube-section" hidden>
<div class="kab-layout"> <div id="cube-layout" class="kab-layout">
<aside class="kab-tree-panel"> <aside class="kab-tree-panel">
<div class="planet-list-header"> <div class="planet-list-header">
<strong>Cube of Space</strong> <strong>Cube of Space</strong>
@@ -768,6 +768,7 @@
<button id="cube-rotate-up" class="cube-rotation-btn" type="button" title="Rotate up"></button> <button id="cube-rotate-up" class="cube-rotation-btn" type="button" title="Rotate up"></button>
<button id="cube-rotate-down" class="cube-rotation-btn" type="button" title="Rotate down"></button> <button id="cube-rotate-down" class="cube-rotation-btn" type="button" title="Rotate down"></button>
<button id="cube-rotate-reset" class="cube-rotation-btn" type="button" title="Reset rotation">Reset</button> <button id="cube-rotate-reset" class="cube-rotation-btn" type="button" title="Reset rotation">Reset</button>
<button id="cube-focus-toggle" class="cube-rotation-btn cube-focus-toggle" type="button" aria-pressed="false">Focus Cube</button>
<div class="cube-marker-mode-control"> <div class="cube-marker-mode-control">
<label for="cube-marker-mode" class="cube-marker-mode-label">Marker display</label> <label for="cube-marker-mode" class="cube-marker-mode-label">Marker display</label>
<select id="cube-marker-mode" class="cube-marker-mode-select" aria-label="Cube marker display mode"> <select id="cube-marker-mode" class="cube-marker-mode-select" aria-label="Cube marker display mode">
@@ -988,7 +989,7 @@
<script src="app/ui-cube-chassis.js"></script> <script src="app/ui-cube-chassis.js"></script>
<script src="app/ui-cube-math.js"></script> <script src="app/ui-cube-math.js"></script>
<script src="app/ui-cube-selection.js"></script> <script src="app/ui-cube-selection.js"></script>
<script src="app/ui-cube.js"></script> <script src="app/ui-cube.js?v=20260310-cube-focus-01"></script>
<script src="app/ui-alphabet-gematria.js?v=20260308b"></script> <script src="app/ui-alphabet-gematria.js?v=20260308b"></script>
<script src="app/ui-alphabet-browser.js?v=20260309-enochian-api"></script> <script src="app/ui-alphabet-browser.js?v=20260309-enochian-api"></script>
<script src="app/ui-alphabet-references.js"></script> <script src="app/ui-alphabet-references.js"></script>