resizeHandle.js 3.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
(function() {
    const GRADIO_MIN_WIDTH = 320;
    const GRID_TEMPLATE_COLUMNS = '1fr 16px 1fr';
    const PAD = 16;
    const DEBOUNCE_TIME = 100;

    const R = {
        tracking: false,
        parent: null,
        parentWidth: null,
        leftCol: null,
        leftColStartWidth: null,
        screenX: null,
    };

    let resizeTimer;
    let parents = [];

    function setLeftColGridTemplate(el, width) {
        el.style.gridTemplateColumns = `${width}px 16px 1fr`;
    }

    function displayResizeHandle(parent) {
        if (window.innerWidth < GRADIO_MIN_WIDTH * 2 + PAD * 4) {
            parent.style.display = 'flex';
            if (R.handle != null) {
                R.handle.style.opacity = '0';
            }
            return false;
        } else {
            parent.style.display = 'grid';
            if (R.handle != null) {
                R.handle.style.opacity = '100';
            }
            return true;
        }
    }

    function afterResize(parent) {
        if (displayResizeHandle(parent) && parent.style.gridTemplateColumns != GRID_TEMPLATE_COLUMNS) {
            const oldParentWidth = R.parentWidth;
            const newParentWidth = parent.offsetWidth;
            const widthL = parseInt(parent.style.gridTemplateColumns.split(' ')[0]);

            const ratio = newParentWidth / oldParentWidth;

            const newWidthL = Math.max(Math.floor(ratio * widthL), GRADIO_MIN_WIDTH);
            setLeftColGridTemplate(parent, newWidthL);

            R.parentWidth = newParentWidth;
        }
    }

    function setup(parent) {
        const leftCol = parent.firstElementChild;
        const rightCol = parent.lastElementChild;

        parents.push(parent);

        parent.style.display = 'grid';
        parent.style.gap = '0';
        parent.style.gridTemplateColumns = GRID_TEMPLATE_COLUMNS;

        const resizeHandle = document.createElement('div');
        resizeHandle.classList.add('resize-handle');
        parent.insertBefore(resizeHandle, rightCol);

        resizeHandle.addEventListener('mousedown', (evt) => {
M
MMP0 已提交
69 70 71 72 73
            evt.preventDefault();
            evt.stopPropagation();

            document.body.classList.add('resizing');

74 75 76 77 78 79 80 81 82
            R.tracking = true;
            R.parent = parent;
            R.parentWidth = parent.offsetWidth;
            R.handle = resizeHandle;
            R.leftCol = leftCol;
            R.leftColStartWidth = leftCol.offsetWidth;
            R.screenX = evt.screenX;
        });

M
MMP0 已提交
83 84 85 86 87 88
        resizeHandle.addEventListener('dblclick', (evt) => {
            evt.preventDefault();
            evt.stopPropagation();

            parent.style.gridTemplateColumns = GRID_TEMPLATE_COLUMNS;
        });
89

90 91 92 93 94
        afterResize(parent);
    }

    window.addEventListener('mousemove', (evt) => {
        if (R.tracking) {
M
MMP0 已提交
95 96 97
            evt.preventDefault();
            evt.stopPropagation();

98 99 100 101 102 103
            const delta = R.screenX - evt.screenX;
            const leftColWidth = Math.max(Math.min(R.leftColStartWidth - delta, R.parent.offsetWidth - GRADIO_MIN_WIDTH - PAD), GRADIO_MIN_WIDTH);
            setLeftColGridTemplate(R.parent, leftColWidth);
        }
    });

M
MMP0 已提交
104 105 106 107 108 109 110 111 112 113
    window.addEventListener('mouseup', (evt) => {
        if (R.tracking) {
            evt.preventDefault();
            evt.stopPropagation();

            R.tracking = false;

            document.body.classList.remove('resizing');
        }
    });
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133


    window.addEventListener('resize', () => {
        clearTimeout(resizeTimer);

        resizeTimer = setTimeout(function() {
            for (const parent of parents) {
                afterResize(parent);
            }
        }, DEBOUNCE_TIME);
    });

    setupResizeHandle = setup;
})();

onUiLoaded(function() {
    for (var elem of gradioApp().querySelectorAll('.resize-handle-row')) {
        setupResizeHandle(elem);
    }
});