@diabolic/hangover 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +25 -7
- package/dist/index.esm.js +25 -7
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -737,12 +737,16 @@ function DropdownContent({
|
|
|
737
737
|
if (displayMode !== 'scroll') return;
|
|
738
738
|
const list = contentRef.current;
|
|
739
739
|
if (!list) return;
|
|
740
|
-
|
|
740
|
+
let rafId = null;
|
|
741
|
+
function computeBottomSpace() {
|
|
742
|
+
rafId = null;
|
|
741
743
|
const sections = list.querySelectorAll('[data-section-for]');
|
|
742
744
|
const lastSection = sections[sections.length - 1];
|
|
743
745
|
if (!lastSection) {
|
|
744
|
-
|
|
745
|
-
|
|
746
|
+
if (bottomPadRef.current !== 0) {
|
|
747
|
+
list.style.paddingBottom = '';
|
|
748
|
+
bottomPadRef.current = 0;
|
|
749
|
+
}
|
|
746
750
|
return;
|
|
747
751
|
}
|
|
748
752
|
|
|
@@ -755,20 +759,34 @@ function DropdownContent({
|
|
|
755
759
|
const listTop = list.getBoundingClientRect().top;
|
|
756
760
|
const lastTopWithinContent = lastSection.getBoundingClientRect().top - listTop + list.scrollTop;
|
|
757
761
|
const spaceBelowLastTop = naturalScrollHeight - lastTopWithinContent;
|
|
758
|
-
const pad = Math.max(0, available - spaceBelowLastTop);
|
|
762
|
+
const pad = Math.max(0, Math.round(available - spaceBelowLastTop));
|
|
763
|
+
|
|
764
|
+
// Only touch the DOM when the reserved space actually changes by a whole
|
|
765
|
+
// pixel — this ignores sub-pixel/floating jitter from the observer and
|
|
766
|
+
// keeps the value stable.
|
|
767
|
+
if (Math.abs(pad - bottomPadRef.current) < 1) return;
|
|
759
768
|
bottomPadRef.current = pad;
|
|
760
769
|
list.style.paddingBottom = `${pad}px`;
|
|
761
770
|
}
|
|
762
|
-
|
|
771
|
+
|
|
772
|
+
// Coalesce bursts of observer callbacks into a single measurement per frame.
|
|
773
|
+
function scheduleBottomSpace() {
|
|
774
|
+
if (rafId !== null) return;
|
|
775
|
+
rafId = requestAnimationFrame(computeBottomSpace);
|
|
776
|
+
}
|
|
777
|
+
scheduleBottomSpace();
|
|
763
778
|
|
|
764
779
|
// Observe both the container (viewport resize) and every section (group
|
|
765
780
|
// expand/collapse, late reflows) so the reserved space stays accurate.
|
|
766
|
-
const observer = new ResizeObserver(
|
|
781
|
+
const observer = new ResizeObserver(scheduleBottomSpace);
|
|
767
782
|
observer.observe(list);
|
|
768
783
|
list.querySelectorAll('[data-section-for]').forEach(section => {
|
|
769
784
|
observer.observe(section);
|
|
770
785
|
});
|
|
771
|
-
return () =>
|
|
786
|
+
return () => {
|
|
787
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
788
|
+
observer.disconnect();
|
|
789
|
+
};
|
|
772
790
|
}, [displayMode, contentRef, children, searchQuery]);
|
|
773
791
|
function handleSearch(e) {
|
|
774
792
|
fireEvent('search', {
|
package/dist/index.esm.js
CHANGED
|
@@ -733,12 +733,16 @@ function DropdownContent({
|
|
|
733
733
|
if (displayMode !== 'scroll') return;
|
|
734
734
|
const list = contentRef.current;
|
|
735
735
|
if (!list) return;
|
|
736
|
-
|
|
736
|
+
let rafId = null;
|
|
737
|
+
function computeBottomSpace() {
|
|
738
|
+
rafId = null;
|
|
737
739
|
const sections = list.querySelectorAll('[data-section-for]');
|
|
738
740
|
const lastSection = sections[sections.length - 1];
|
|
739
741
|
if (!lastSection) {
|
|
740
|
-
|
|
741
|
-
|
|
742
|
+
if (bottomPadRef.current !== 0) {
|
|
743
|
+
list.style.paddingBottom = '';
|
|
744
|
+
bottomPadRef.current = 0;
|
|
745
|
+
}
|
|
742
746
|
return;
|
|
743
747
|
}
|
|
744
748
|
|
|
@@ -751,20 +755,34 @@ function DropdownContent({
|
|
|
751
755
|
const listTop = list.getBoundingClientRect().top;
|
|
752
756
|
const lastTopWithinContent = lastSection.getBoundingClientRect().top - listTop + list.scrollTop;
|
|
753
757
|
const spaceBelowLastTop = naturalScrollHeight - lastTopWithinContent;
|
|
754
|
-
const pad = Math.max(0, available - spaceBelowLastTop);
|
|
758
|
+
const pad = Math.max(0, Math.round(available - spaceBelowLastTop));
|
|
759
|
+
|
|
760
|
+
// Only touch the DOM when the reserved space actually changes by a whole
|
|
761
|
+
// pixel — this ignores sub-pixel/floating jitter from the observer and
|
|
762
|
+
// keeps the value stable.
|
|
763
|
+
if (Math.abs(pad - bottomPadRef.current) < 1) return;
|
|
755
764
|
bottomPadRef.current = pad;
|
|
756
765
|
list.style.paddingBottom = `${pad}px`;
|
|
757
766
|
}
|
|
758
|
-
|
|
767
|
+
|
|
768
|
+
// Coalesce bursts of observer callbacks into a single measurement per frame.
|
|
769
|
+
function scheduleBottomSpace() {
|
|
770
|
+
if (rafId !== null) return;
|
|
771
|
+
rafId = requestAnimationFrame(computeBottomSpace);
|
|
772
|
+
}
|
|
773
|
+
scheduleBottomSpace();
|
|
759
774
|
|
|
760
775
|
// Observe both the container (viewport resize) and every section (group
|
|
761
776
|
// expand/collapse, late reflows) so the reserved space stays accurate.
|
|
762
|
-
const observer = new ResizeObserver(
|
|
777
|
+
const observer = new ResizeObserver(scheduleBottomSpace);
|
|
763
778
|
observer.observe(list);
|
|
764
779
|
list.querySelectorAll('[data-section-for]').forEach(section => {
|
|
765
780
|
observer.observe(section);
|
|
766
781
|
});
|
|
767
|
-
return () =>
|
|
782
|
+
return () => {
|
|
783
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
784
|
+
observer.disconnect();
|
|
785
|
+
};
|
|
768
786
|
}, [displayMode, contentRef, children, searchQuery]);
|
|
769
787
|
function handleSearch(e) {
|
|
770
788
|
fireEvent('search', {
|