diff --git a/edit/edit.css b/edit/edit.css index 21f27057..5489a7ad 100644 --- a/edit/edit.css +++ b/edit/edit.css @@ -263,14 +263,20 @@ input:invalid { #lint:not([open]) + #footer { margin-top: 4em; } -/************ content ***********/ -#sections > * { +/************ section editor ***********/ +.section-editor .section { margin: 0 0.7rem; padding: 1rem; } -#sections > :not(:first-child) { +.section-editor .section:not(:first-child) { border-top: 2px solid hsl(0, 0%, 80%); } +.section-editor:not(.section-editor-ready) .section { + visibility: hidden; +} +.section-editor:not(.section-editor-ready) .CodeMirror { + height: 0; +} .add-section:after { content: attr(short-text); } @@ -311,6 +317,7 @@ input:invalid { } .section .CodeMirror { margin-bottom: .875rem; + box-sizing: border-box; } /* deleted section */ .deleted-section { @@ -950,12 +957,8 @@ html:not(.usercss) .usercss-only, flex: 1; } #sections > * { - margin: 0 .5rem .5rem; - padding: .5rem 0 0; - } - #sections > *:first-child { - margin: .5rem; - padding: 0; + margin: 0 .5rem; + padding: .5rem 0; } .usercss .CodeMirror-scroll { max-height: calc(100vh - var(--header-narrow-min-height)); diff --git a/edit/refresh-on-view.js b/edit/refresh-on-view.js index 0fa123d6..ffbc0589 100644 --- a/edit/refresh-on-view.js +++ b/edit/refresh-on-view.js @@ -10,6 +10,7 @@ CodeMirror.defineExtension('refreshOnView', function () { const cm = this; if (typeof IntersectionObserver === 'undefined') { // uh + cm.isRefreshed = true; cm.refresh(); return; } @@ -18,6 +19,7 @@ CodeMirror.defineExtension('refreshOnView', function () { for (const entry of entries) { if (entry.isIntersecting) { // wrapper.style.visibility = 'visible'; + cm.isRefreshed = true; cm.refresh(); observer.disconnect(); } diff --git a/edit/sections-editor-section.js b/edit/sections-editor-section.js index 74540e79..67880a35 100644 --- a/edit/sections-editor-section.js +++ b/edit/sections-editor-section.js @@ -9,7 +9,11 @@ function createResizeGrip(cm) { const resizeGrip = template.resizeGrip.cloneNode(true); wrapper.appendChild(resizeGrip); let lastClickTime = 0; + let initHeight; + let initY; resizeGrip.onmousedown = event => { + initHeight = wrapper.offsetHeight; + initY = event.pageY; if (event.button !== 0) { return; } @@ -31,9 +35,8 @@ function createResizeGrip(cm) { document.addEventListener('mouseup', resizeStop); function resize(e) { - const cmPageY = wrapper.getBoundingClientRect().top + window.scrollY; - const height = Math.max(minHeight, e.pageY - cmPageY); - if (height !== wrapper.clientHeight) { + const height = Math.max(minHeight, initHeight + e.pageY - initY); + if (height !== wrapper.offsetHeight) { cm.setSize(null, height); } } diff --git a/edit/sections-editor.js b/edit/sections-editor.js index 99772f2b..c4b7cab3 100644 --- a/edit/sections-editor.js +++ b/edit/sections-editor.js @@ -13,6 +13,8 @@ function createSectionsEditor({style, onTitleChanged}) { const container = $('#sections'); const sections = []; + container.classList.add('section-editor'); + const nameEl = $('#name'); nameEl.addEventListener('input', () => { dirty.modify('name', style.name, nameEl.value); @@ -48,12 +50,11 @@ function createSectionsEditor({style, onTitleChanged}) { const initializing = new Promise(resolve => initSection({ sections: style.sections.slice(), done:() => { - // FIXME: implement this with CSS? - // https://github.com/openstyles/stylus/commit/2895ce11e271788df0e4f7314b3b981fde086574 dirty.clear(); rerouteHotkeys(true); resolve(); updateHeader(); + sections.forEach(fitToContent); } })); @@ -80,6 +81,45 @@ function createSectionsEditor({style, onTitleChanged}) { getSearchableInputs, }; + function fitToContent(section) { + if (section.cm.isRefreshed) { + resize(); + } else { + section.cm.on('update', resize); + } + + function resize() { + let contentHeight = section.el.querySelector('.CodeMirror-sizer').offsetHeight; + if (contentHeight < section.cm.defaultTextHeight()) { + return; + } + contentHeight += 9; // border & resize grip + section.cm.off('update', resize); + const cmHeight = section.cm.getWrapperElement().offsetHeight; + const maxHeight = cmHeight + window.innerHeight - section.el.offsetHeight; + section.cm.setSize(null, Math.min(contentHeight, maxHeight)); + if (sections.every(s => s.cm.isRefreshed)) { + fitToAvailableSpace(); + } + setTimeout(() => { + container.classList.add('section-editor-ready'); + }, 50); + } + } + + function fitToAvailableSpace() { + const available = + Math.floor(container.offsetHeight - sections.reduce((h, s) => h + s.el.offsetHeight, 0)) || + window.innerHeight - container.offsetHeight; + if (available <= 0) { + return; + } + const cmHeights = sections.map(s => s.cm.getWrapperElement().offsetHeight); + sections.forEach((section, i) => { + section.cm.setSize(null, cmHeights[i] + Math.floor(available / sections.length)); + }); + } + function genId() { return INC_ID++; }