mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-07 07:59:42 +02:00
Merge pull request #334 from aakhter/pr/cod-358-vertical-rail
feat(tabs): add a resizable vertical session rail
This commit is contained in:
@@ -156,6 +156,43 @@ function shouldAutoWrapTabs(input) {
|
||||
return scrollWidth > clientWidth + 1;
|
||||
}
|
||||
|
||||
function resolveTabOrientation(input) {
|
||||
if (!input || input.setting !== 'vertical') return 'horizontal';
|
||||
if (input.deviceType === 'mobile') return 'horizontal';
|
||||
return 'vertical';
|
||||
}
|
||||
|
||||
const TAB_RAIL_MIN_WIDTH = 208;
|
||||
const TAB_RAIL_DEFAULT_WIDTH = 256;
|
||||
const TAB_RAIL_MAX_WIDTH = 360;
|
||||
|
||||
function resolveTabRailWidth(input = {}) {
|
||||
const viewportWidth = Number(input.viewportWidth);
|
||||
const mainWidth = Number(input.mainWidth);
|
||||
const minTerminalWidth = Number(input.minTerminalWidth);
|
||||
const limits = [TAB_RAIL_MAX_WIDTH];
|
||||
if (Number.isFinite(viewportWidth) && viewportWidth > 0) limits.push(Math.floor(viewportWidth * 0.4));
|
||||
if (Number.isFinite(mainWidth) && mainWidth > 0 && Number.isFinite(minTerminalWidth) && minTerminalWidth > 0) {
|
||||
limits.push(Math.floor(mainWidth - minTerminalWidth));
|
||||
}
|
||||
const effectiveMax = Math.max(TAB_RAIL_MIN_WIDTH, Math.min(...limits));
|
||||
const requested = Number(input.width);
|
||||
const width = Number.isFinite(requested) ? requested : TAB_RAIL_DEFAULT_WIDTH;
|
||||
return Math.round(Math.min(effectiveMax, Math.max(TAB_RAIL_MIN_WIDTH, width)));
|
||||
}
|
||||
|
||||
function resolveTabRailKeyboardWidth(input = {}) {
|
||||
let width;
|
||||
if (input.key === 'Home') width = TAB_RAIL_MIN_WIDTH;
|
||||
else if (input.key === 'End') width = TAB_RAIL_MAX_WIDTH;
|
||||
else if (input.key === 'Enter') width = TAB_RAIL_DEFAULT_WIDTH;
|
||||
else if (input.key === 'ArrowLeft' || input.key === 'ArrowRight') {
|
||||
const direction = input.key === 'ArrowLeft' ? -1 : 1;
|
||||
width = (Number(input.currentWidth) || TAB_RAIL_DEFAULT_WIDTH) + direction * (input.shiftKey ? 32 : 8);
|
||||
} else return null;
|
||||
return resolveTabRailWidth({ ...input, width });
|
||||
}
|
||||
|
||||
// Sliver of the neighbouring tab left visible when the strip scrolls a tab into
|
||||
// view. Landing a tab flush against the edge reads as "this is the last one";
|
||||
// the gap is what tells the user there is more strip to swipe to.
|
||||
@@ -243,6 +280,9 @@ const LINEAGE_DIP_MAX_PX = 64;
|
||||
// apart bled into one thick band instead of reading as three separate lines.
|
||||
const LINEAGE_SIBLING_STEP_PX = 8;
|
||||
const LINEAGE_STRIP_TOLERANCE_PX = 4;
|
||||
const LINEAGE_VERTICAL_TRACK_INSET_PX = 6;
|
||||
const LINEAGE_VERTICAL_SIBLING_STEP_PX = 3;
|
||||
const LINEAGE_VERTICAL_ANCHOR_CLEARANCE_PX = 4;
|
||||
// Lineage palette, assigned per SPAWNING TAB in first-seen order and cycled
|
||||
// (session-lineage.js). Every arc leaving one tab shares its colour however many
|
||||
// workers it spawns; a child that spawns in turn gets its own for the arcs below it.
|
||||
@@ -265,21 +305,44 @@ function computeLineagePath(input) {
|
||||
const ch = Number(child.height) || 0;
|
||||
if (pw <= 0 || ph <= 0 || cw <= 0 || ch <= 0) return null;
|
||||
|
||||
const px = Number(parent.left) + pw / 2;
|
||||
const cx = Number(child.left) + cw / 2;
|
||||
if (!Number.isFinite(px) || !Number.isFinite(cx)) return null;
|
||||
|
||||
const orientation = input?.orientation === 'vertical' ? 'vertical' : 'horizontal';
|
||||
const strip = input?.strip;
|
||||
const depth = Math.max(0, Math.min(6, Number(input?.depth) || 0));
|
||||
const pLeft = Number(parent.left);
|
||||
const cLeft = Number(child.left);
|
||||
const pTop = Number(parent.top);
|
||||
const cTop = Number(child.top);
|
||||
if (![pLeft, cLeft, pTop, cTop].every(Number.isFinite)) return null;
|
||||
|
||||
if (orientation === 'vertical') {
|
||||
const py = pTop + ph / 2;
|
||||
const cy = cTop + ch / 2;
|
||||
if (strip && Number(strip.height) > 0) {
|
||||
const min = Number(strip.top) - LINEAGE_STRIP_TOLERANCE_PX;
|
||||
const max = Number(strip.top) + Number(strip.height) + LINEAGE_STRIP_TOLERANCE_PX;
|
||||
if (py < min || py > max || cy < min || cy > max) return null;
|
||||
}
|
||||
|
||||
const stripLeft =
|
||||
strip && Number.isFinite(Number(strip.left))
|
||||
? Number(strip.left)
|
||||
: Math.min(pLeft, cLeft) - LINEAGE_VERTICAL_TRACK_INSET_PX * 2;
|
||||
const requestedTrack =
|
||||
stripLeft + LINEAGE_VERTICAL_TRACK_INSET_PX + depth * LINEAGE_VERTICAL_SIBLING_STEP_PX;
|
||||
const trackX = Math.min(requestedTrack, Math.min(pLeft, cLeft) - LINEAGE_VERTICAL_ANCHOR_CLEARANCE_PX);
|
||||
const d = `M ${r1(pLeft)} ${r1(py)} H ${r1(trackX)} V ${r1(cy)} H ${r1(cLeft)}`;
|
||||
return { d, endX: cLeft, endY: cy, sameRow: false };
|
||||
}
|
||||
|
||||
const px = pLeft + pw / 2;
|
||||
const cx = cLeft + cw / 2;
|
||||
if (strip && Number(strip.width) > 0) {
|
||||
const min = Number(strip.left) - LINEAGE_STRIP_TOLERANCE_PX;
|
||||
const max = Number(strip.left) + Number(strip.width) + LINEAGE_STRIP_TOLERANCE_PX;
|
||||
if (px < min || px > max || cx < min || cx > max) return null;
|
||||
}
|
||||
|
||||
const depth = Math.max(0, Math.min(6, Number(input?.depth) || 0));
|
||||
const pTop = Number(parent.top);
|
||||
const pBottom = pTop + ph;
|
||||
const cTop = Number(child.top);
|
||||
const cBottom = cTop + ch;
|
||||
const sameRow = Math.abs(pTop + ph / 2 - (cTop + ch / 2)) <= Math.min(ph, ch) / 2;
|
||||
|
||||
@@ -617,9 +680,17 @@ if (typeof window !== 'undefined') {
|
||||
window.shouldSkipWebGL = shouldSkipWebGL;
|
||||
window.CodemanTabOverflow = {
|
||||
shouldAutoWrapTabs,
|
||||
resolveTabOrientation,
|
||||
computeTabScrollLeft,
|
||||
TAB_SCROLL_REVEAL_PX,
|
||||
};
|
||||
window.CodemanTabRail = {
|
||||
DEFAULT_WIDTH: TAB_RAIL_DEFAULT_WIDTH,
|
||||
MIN_WIDTH: TAB_RAIL_MIN_WIDTH,
|
||||
MAX_WIDTH: TAB_RAIL_MAX_WIDTH,
|
||||
resolveWidth: resolveTabRailWidth,
|
||||
resolveKeyboardWidth: resolveTabRailKeyboardWidth,
|
||||
};
|
||||
window.CodemanWsReconnect = {
|
||||
plan: planWsReconnect,
|
||||
};
|
||||
@@ -628,6 +699,8 @@ if (typeof window !== 'undefined') {
|
||||
DIP_MIN_PX: LINEAGE_DIP_MIN_PX,
|
||||
DIP_MAX_PX: LINEAGE_DIP_MAX_PX,
|
||||
SIBLING_STEP_PX: LINEAGE_SIBLING_STEP_PX,
|
||||
VERTICAL_TRACK_INSET_PX: LINEAGE_VERTICAL_TRACK_INSET_PX,
|
||||
VERTICAL_SIBLING_STEP_PX: LINEAGE_VERTICAL_SIBLING_STEP_PX,
|
||||
COLORS: LINEAGE_COLORS,
|
||||
};
|
||||
window.CodemanConnectionLoss = {
|
||||
|
||||
Reference in New Issue
Block a user