mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-09 08:59:40 +02:00
feat(tiles): draggable column and row dividers
The grid now places every tile explicitly (grid-column / grid-row, reading order) with a 6px divider track between columns and between rows, instead of relying on DOM order and a gap. Track sizes are fractions (grid-template fr values) that reset to equal whenever the column or row count changes. Dragging a divider trades size between the two tracks either side, each kept at the minimum tile size (the pure dragTrackFractions in constants.js, always computed from the fractions the drag started with, so it cannot drift). The affected tiles reflow locally at most once per animation frame, with no PTY resize; each hears exactly one fit (one PTY resize) at pointer-up, and tiles in other tracks hear nothing. Pointer capture keeps the drag on the divider, the body locks the resize cursor and text selection for its duration, and closing the grid or removing a tile mid-drag tears it down, as the split's divider does. A zoomed grid shows no dividers. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -144,10 +144,7 @@ describe('sanitizeTileGridState', () => {
|
||||
});
|
||||
|
||||
it('drops malformed track fractions', () => {
|
||||
const out = T.sanitizeTileGridState(
|
||||
{ v: 1, open: true, ids: ['a'], colFr: [1, -1], rowFr: [1, 1, 1, 1] },
|
||||
live
|
||||
);
|
||||
const out = T.sanitizeTileGridState({ v: 1, open: true, ids: ['a'], colFr: [1, -1], rowFr: [1, 1, 1, 1] }, live);
|
||||
expect(out?.colFr).toBeNull();
|
||||
expect(out?.rowFr).toBeNull();
|
||||
});
|
||||
@@ -188,6 +185,37 @@ describe('focus helpers', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('dragTrackFractions (divider drags)', () => {
|
||||
const drag = (fr: number[], i: number, d: number, total = 1200, min = 300) =>
|
||||
(T as unknown as { dragTrackFractions: (...a: unknown[]) => number[] }).dragTrackFractions(fr, i, d, total, min);
|
||||
const px = (fr: number[], total = 1200) => fr.map((f) => Math.round((f / fr.reduce((a, b) => a + b, 0)) * total));
|
||||
|
||||
it('moves size from one neighbour to the other, the rest untouched', () => {
|
||||
// 3 equal tracks of 400px; divider 0 moves 100px right.
|
||||
expect(px(drag([1, 1, 1], 0, 100))).toEqual([500, 300, 400]);
|
||||
expect(px(drag([1, 1, 1], 1, -50))).toEqual([400, 350, 450]);
|
||||
});
|
||||
|
||||
it('clamps both neighbours to the minimum size', () => {
|
||||
expect(px(drag([1, 1, 1], 0, 300))).toEqual([500, 300, 400]);
|
||||
expect(px(drag([1, 1, 1], 0, -300))).toEqual([300, 500, 400]);
|
||||
});
|
||||
|
||||
it('a pair too small for two minimums splits evenly instead of inverting', () => {
|
||||
expect(px(drag([1, 1], 0, 200, 500, 300), 500)).toEqual([250, 250]);
|
||||
});
|
||||
|
||||
it('works from the fractions the drag started with (no drift)', () => {
|
||||
const start = [2, 1];
|
||||
expect(px(drag(start, 0, 0))).toEqual([800, 400]);
|
||||
expect(start).toEqual([2, 1]);
|
||||
});
|
||||
|
||||
it('ignores a divider that is not between two tracks', () => {
|
||||
expect(drag([1, 1], 1, 100)).toEqual([1, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('tile constants', () => {
|
||||
it('a tile keeps 10,000 lines of scrollback, not the primary pane 50,000', () => {
|
||||
expect(T.TILE_SCROLLBACK).toBe(10000);
|
||||
|
||||
Reference in New Issue
Block a user