/* part: split (behaviour) — the drag half of split.css. * * Derived from common/ui/src/components/SplitPane.vue's pointer handlers. Plain * DOM, no framework, no build step, no imports: a (or paste it; it self-starts) * *
* * data-split marks the element. Required. * data-size (default 1) initial size of the anchored pane * data-mode ratio | px (default ratio) * data-anchor first | second (default first) * data-min / data-max clamps, in the same unit as data-size * * Direction comes from the `horizontal` / `vertical` class, so CSS and JS * cannot disagree about it. */ (function () { 'use strict' function setup(root) { var divider = root.querySelector(':scope > .split-divider') if (!divider) return // no divider: a fixed split, deliberately var first = root.querySelector(':scope > .split-first') var second = root.querySelector(':scope > .split-second') if (!first || !second) return var horizontal = !root.classList.contains('vertical') var mode = root.dataset.mode === 'px' ? 'px' : 'ratio' var anchor = root.dataset.anchor === 'second' ? 'second' : 'first' var size = parseFloat(root.dataset.size) if (isNaN(size)) size = 1 var min = parseFloat(root.dataset.min) if (isNaN(min)) min = mode === 'px' ? 0 : 0.1 var max = parseFloat(root.dataset.max) if (isNaN(max)) max = mode === 'px' ? Infinity : 10 var sized = anchor === 'second' ? second : first var flexed = anchor === 'second' ? first : second var dragging = false var startPos = 0 function apply() { flexed.style.flex = '1' if (mode === 'px') { sized.style.flex = '0 0 auto' sized.style[horizontal ? 'width' : 'height'] = size + 'px' } else { sized.style.flex = String(size) } } divider.addEventListener('pointerdown', function (e) { dragging = true startPos = horizontal ? e.clientX : e.clientY divider.classList.add('dragging') divider.setPointerCapture(e.pointerId) }) divider.addEventListener('pointermove', function (e) { if (!dragging) return var pos = horizontal ? e.clientX : e.clientY var delta = pos - startPos startPos = pos // Dragging right/down grows the first pane. When the SECOND pane is the // anchored one, that same gesture must shrink it, so invert. if (anchor === 'second') delta = -delta // Ratio mode is unitless, so pixels are scaled into it. The two constants // are the SFC's, kept rather than re-derived: they are what the existing // panes were tuned against, and vertical drags cover less travel. var step = mode === 'px' ? delta : delta * (horizontal ? 0.01 : 0.02) size = Math.max(min, Math.min(max, size + step)) apply() }) function end(e) { if (!dragging) return dragging = false divider.classList.remove('dragging') if (e && e.pointerId !== undefined && divider.hasPointerCapture(e.pointerId)) { divider.releasePointerCapture(e.pointerId) } } divider.addEventListener('pointerup', end) divider.addEventListener('pointercancel', end) apply() } function start() { var panes = document.querySelectorAll('[data-split]') for (var i = 0; i < panes.length; i++) setup(panes[i]) } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', start) } else { start() } })()