@trackunit/react-components 1.14.29 → 1.14.30
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/index.cjs.js +41 -7
- package/index.esm.js +41 -7
- package/package.json +1 -1
package/index.cjs.js
CHANGED
|
@@ -7697,6 +7697,9 @@ const getWindowSize = () => {
|
|
|
7697
7697
|
|
|
7698
7698
|
/**
|
|
7699
7699
|
* Blocks scrolling on the document and compensates for scrollbar width to prevent layout shift.
|
|
7700
|
+
* Uses scrollbar-gutter: stable to reserve space for the scrollbar when hiding overflow,
|
|
7701
|
+
* but only if a scrollbar was actually visible before blocking.
|
|
7702
|
+
* This only has an effect with classic scrollbars - overlay scrollbars (macOS default) are unaffected.
|
|
7700
7703
|
* Returns the original styles so they can be restored later.
|
|
7701
7704
|
*
|
|
7702
7705
|
* @returns {OriginalStyles} The original styles before blocking
|
|
@@ -7704,6 +7707,18 @@ const getWindowSize = () => {
|
|
|
7704
7707
|
const blockDocumentScroll = () => {
|
|
7705
7708
|
const { body } = document;
|
|
7706
7709
|
const html = document.documentElement;
|
|
7710
|
+
// Check if there's a visible scrollbar before we hide it
|
|
7711
|
+
// The scrollbar can be on either <html> or <body> depending on CSS setup
|
|
7712
|
+
// (e.g., Storybook sets overflow:hidden on html and overflow:auto on body)
|
|
7713
|
+
// Check html scrollbar: window.innerWidth includes scrollbar, clientWidth doesn't
|
|
7714
|
+
const htmlScrollbarWidth = window.innerWidth - html.clientWidth;
|
|
7715
|
+
// Check body scrollbar: offsetWidth includes border+scrollbar, clientWidth excludes both
|
|
7716
|
+
const bodyStyle = window.getComputedStyle(body);
|
|
7717
|
+
const bodyBorderLeft = parseInt(bodyStyle.borderLeftWidth) || 0;
|
|
7718
|
+
const bodyBorderRight = parseInt(bodyStyle.borderRightWidth) || 0;
|
|
7719
|
+
const bodyScrollbarWidth = body.offsetWidth - bodyBorderLeft - bodyBorderRight - body.clientWidth;
|
|
7720
|
+
// Use whichever scrollbar is present
|
|
7721
|
+
const hasVisibleScrollbar = htmlScrollbarWidth > 0 || bodyScrollbarWidth > 0;
|
|
7707
7722
|
// Store original values before modifying
|
|
7708
7723
|
const originalStyles = {
|
|
7709
7724
|
html: {
|
|
@@ -7713,19 +7728,20 @@ const blockDocumentScroll = () => {
|
|
|
7713
7728
|
body: {
|
|
7714
7729
|
position: body.style.position,
|
|
7715
7730
|
overflow: body.style.overflow,
|
|
7716
|
-
|
|
7731
|
+
scrollbarGutter: body.style.scrollbarGutter,
|
|
7717
7732
|
},
|
|
7718
7733
|
};
|
|
7719
|
-
// Calculate scrollbar width to prevent layout shift when hiding scrollbar
|
|
7720
|
-
const scrollBarWidth = window.innerWidth - (html.clientWidth || 0);
|
|
7721
|
-
const bodyPaddingRight = parseInt(window.getComputedStyle(body).getPropertyValue("padding-right")) || 0;
|
|
7722
7734
|
// Block scroll on both html and body for cross-browser compatibility
|
|
7723
7735
|
html.style.position = "relative";
|
|
7724
7736
|
html.style.overflow = "hidden";
|
|
7725
7737
|
body.style.position = "relative";
|
|
7726
7738
|
body.style.overflow = "hidden";
|
|
7727
|
-
//
|
|
7728
|
-
|
|
7739
|
+
// Apply scrollbar-gutter on body (where the scrollbar typically lives when content scrolls)
|
|
7740
|
+
// This reserves space for the scrollbar even when overflow is hidden, preventing layout shift.
|
|
7741
|
+
// Only has effect with classic scrollbars - overlay scrollbars (macOS default) are unaffected.
|
|
7742
|
+
if (hasVisibleScrollbar) {
|
|
7743
|
+
body.style.scrollbarGutter = "stable";
|
|
7744
|
+
}
|
|
7729
7745
|
return originalStyles;
|
|
7730
7746
|
};
|
|
7731
7747
|
/**
|
|
@@ -7744,23 +7760,40 @@ const restoreDocumentScroll = (originalStyles) => {
|
|
|
7744
7760
|
if (originalStyles.body) {
|
|
7745
7761
|
body.style.position = originalStyles.body.position;
|
|
7746
7762
|
body.style.overflow = originalStyles.body.overflow;
|
|
7747
|
-
body.style.
|
|
7763
|
+
body.style.scrollbarGutter = originalStyles.body.scrollbarGutter;
|
|
7748
7764
|
}
|
|
7749
7765
|
};
|
|
7750
7766
|
/**
|
|
7751
7767
|
* Blocks scrolling on a custom container element.
|
|
7768
|
+
* Uses scrollbar-gutter: stable to reserve space for the scrollbar when hiding overflow,
|
|
7769
|
+
* but only if a scrollbar was actually visible before blocking.
|
|
7770
|
+
* This only has an effect with classic scrollbars - overlay scrollbars (macOS default) are unaffected.
|
|
7752
7771
|
* Returns the original styles so they can be restored later.
|
|
7753
7772
|
*
|
|
7754
7773
|
* @param container - The container element to block scroll on
|
|
7755
7774
|
* @returns {OriginalStyles} The original styles before blocking
|
|
7756
7775
|
*/
|
|
7757
7776
|
const blockContainerScroll = (container) => {
|
|
7777
|
+
// Check if there's a visible scrollbar before we hide it
|
|
7778
|
+
// offsetWidth includes border + scrollbar, clientWidth excludes both
|
|
7779
|
+
// We need to subtract borders to isolate the scrollbar width
|
|
7780
|
+
const style = window.getComputedStyle(container);
|
|
7781
|
+
const borderLeft = parseInt(style.borderLeftWidth) || 0;
|
|
7782
|
+
const borderRight = parseInt(style.borderRightWidth) || 0;
|
|
7783
|
+
const scrollbarWidth = container.offsetWidth - borderLeft - borderRight - container.clientWidth;
|
|
7784
|
+
const hasVisibleScrollbar = scrollbarWidth > 0;
|
|
7758
7785
|
const originalStyles = {
|
|
7759
7786
|
container: {
|
|
7760
7787
|
overflow: container.style.overflow,
|
|
7788
|
+
scrollbarGutter: container.style.scrollbarGutter,
|
|
7761
7789
|
},
|
|
7762
7790
|
};
|
|
7763
7791
|
container.style.overflow = "hidden";
|
|
7792
|
+
// Only add scrollbar-gutter if there was a visible scrollbar to preserve space for
|
|
7793
|
+
// This prevents adding unnecessary space when content doesn't overflow
|
|
7794
|
+
if (hasVisibleScrollbar) {
|
|
7795
|
+
container.style.scrollbarGutter = "stable";
|
|
7796
|
+
}
|
|
7764
7797
|
return originalStyles;
|
|
7765
7798
|
};
|
|
7766
7799
|
/**
|
|
@@ -7772,6 +7805,7 @@ const blockContainerScroll = (container) => {
|
|
|
7772
7805
|
const restoreContainerScroll = (container, originalStyles) => {
|
|
7773
7806
|
if (originalStyles.container) {
|
|
7774
7807
|
container.style.overflow = originalStyles.container.overflow;
|
|
7808
|
+
container.style.scrollbarGutter = originalStyles.container.scrollbarGutter;
|
|
7775
7809
|
}
|
|
7776
7810
|
};
|
|
7777
7811
|
/**
|
package/index.esm.js
CHANGED
|
@@ -7695,6 +7695,9 @@ const getWindowSize = () => {
|
|
|
7695
7695
|
|
|
7696
7696
|
/**
|
|
7697
7697
|
* Blocks scrolling on the document and compensates for scrollbar width to prevent layout shift.
|
|
7698
|
+
* Uses scrollbar-gutter: stable to reserve space for the scrollbar when hiding overflow,
|
|
7699
|
+
* but only if a scrollbar was actually visible before blocking.
|
|
7700
|
+
* This only has an effect with classic scrollbars - overlay scrollbars (macOS default) are unaffected.
|
|
7698
7701
|
* Returns the original styles so they can be restored later.
|
|
7699
7702
|
*
|
|
7700
7703
|
* @returns {OriginalStyles} The original styles before blocking
|
|
@@ -7702,6 +7705,18 @@ const getWindowSize = () => {
|
|
|
7702
7705
|
const blockDocumentScroll = () => {
|
|
7703
7706
|
const { body } = document;
|
|
7704
7707
|
const html = document.documentElement;
|
|
7708
|
+
// Check if there's a visible scrollbar before we hide it
|
|
7709
|
+
// The scrollbar can be on either <html> or <body> depending on CSS setup
|
|
7710
|
+
// (e.g., Storybook sets overflow:hidden on html and overflow:auto on body)
|
|
7711
|
+
// Check html scrollbar: window.innerWidth includes scrollbar, clientWidth doesn't
|
|
7712
|
+
const htmlScrollbarWidth = window.innerWidth - html.clientWidth;
|
|
7713
|
+
// Check body scrollbar: offsetWidth includes border+scrollbar, clientWidth excludes both
|
|
7714
|
+
const bodyStyle = window.getComputedStyle(body);
|
|
7715
|
+
const bodyBorderLeft = parseInt(bodyStyle.borderLeftWidth) || 0;
|
|
7716
|
+
const bodyBorderRight = parseInt(bodyStyle.borderRightWidth) || 0;
|
|
7717
|
+
const bodyScrollbarWidth = body.offsetWidth - bodyBorderLeft - bodyBorderRight - body.clientWidth;
|
|
7718
|
+
// Use whichever scrollbar is present
|
|
7719
|
+
const hasVisibleScrollbar = htmlScrollbarWidth > 0 || bodyScrollbarWidth > 0;
|
|
7705
7720
|
// Store original values before modifying
|
|
7706
7721
|
const originalStyles = {
|
|
7707
7722
|
html: {
|
|
@@ -7711,19 +7726,20 @@ const blockDocumentScroll = () => {
|
|
|
7711
7726
|
body: {
|
|
7712
7727
|
position: body.style.position,
|
|
7713
7728
|
overflow: body.style.overflow,
|
|
7714
|
-
|
|
7729
|
+
scrollbarGutter: body.style.scrollbarGutter,
|
|
7715
7730
|
},
|
|
7716
7731
|
};
|
|
7717
|
-
// Calculate scrollbar width to prevent layout shift when hiding scrollbar
|
|
7718
|
-
const scrollBarWidth = window.innerWidth - (html.clientWidth || 0);
|
|
7719
|
-
const bodyPaddingRight = parseInt(window.getComputedStyle(body).getPropertyValue("padding-right")) || 0;
|
|
7720
7732
|
// Block scroll on both html and body for cross-browser compatibility
|
|
7721
7733
|
html.style.position = "relative";
|
|
7722
7734
|
html.style.overflow = "hidden";
|
|
7723
7735
|
body.style.position = "relative";
|
|
7724
7736
|
body.style.overflow = "hidden";
|
|
7725
|
-
//
|
|
7726
|
-
|
|
7737
|
+
// Apply scrollbar-gutter on body (where the scrollbar typically lives when content scrolls)
|
|
7738
|
+
// This reserves space for the scrollbar even when overflow is hidden, preventing layout shift.
|
|
7739
|
+
// Only has effect with classic scrollbars - overlay scrollbars (macOS default) are unaffected.
|
|
7740
|
+
if (hasVisibleScrollbar) {
|
|
7741
|
+
body.style.scrollbarGutter = "stable";
|
|
7742
|
+
}
|
|
7727
7743
|
return originalStyles;
|
|
7728
7744
|
};
|
|
7729
7745
|
/**
|
|
@@ -7742,23 +7758,40 @@ const restoreDocumentScroll = (originalStyles) => {
|
|
|
7742
7758
|
if (originalStyles.body) {
|
|
7743
7759
|
body.style.position = originalStyles.body.position;
|
|
7744
7760
|
body.style.overflow = originalStyles.body.overflow;
|
|
7745
|
-
body.style.
|
|
7761
|
+
body.style.scrollbarGutter = originalStyles.body.scrollbarGutter;
|
|
7746
7762
|
}
|
|
7747
7763
|
};
|
|
7748
7764
|
/**
|
|
7749
7765
|
* Blocks scrolling on a custom container element.
|
|
7766
|
+
* Uses scrollbar-gutter: stable to reserve space for the scrollbar when hiding overflow,
|
|
7767
|
+
* but only if a scrollbar was actually visible before blocking.
|
|
7768
|
+
* This only has an effect with classic scrollbars - overlay scrollbars (macOS default) are unaffected.
|
|
7750
7769
|
* Returns the original styles so they can be restored later.
|
|
7751
7770
|
*
|
|
7752
7771
|
* @param container - The container element to block scroll on
|
|
7753
7772
|
* @returns {OriginalStyles} The original styles before blocking
|
|
7754
7773
|
*/
|
|
7755
7774
|
const blockContainerScroll = (container) => {
|
|
7775
|
+
// Check if there's a visible scrollbar before we hide it
|
|
7776
|
+
// offsetWidth includes border + scrollbar, clientWidth excludes both
|
|
7777
|
+
// We need to subtract borders to isolate the scrollbar width
|
|
7778
|
+
const style = window.getComputedStyle(container);
|
|
7779
|
+
const borderLeft = parseInt(style.borderLeftWidth) || 0;
|
|
7780
|
+
const borderRight = parseInt(style.borderRightWidth) || 0;
|
|
7781
|
+
const scrollbarWidth = container.offsetWidth - borderLeft - borderRight - container.clientWidth;
|
|
7782
|
+
const hasVisibleScrollbar = scrollbarWidth > 0;
|
|
7756
7783
|
const originalStyles = {
|
|
7757
7784
|
container: {
|
|
7758
7785
|
overflow: container.style.overflow,
|
|
7786
|
+
scrollbarGutter: container.style.scrollbarGutter,
|
|
7759
7787
|
},
|
|
7760
7788
|
};
|
|
7761
7789
|
container.style.overflow = "hidden";
|
|
7790
|
+
// Only add scrollbar-gutter if there was a visible scrollbar to preserve space for
|
|
7791
|
+
// This prevents adding unnecessary space when content doesn't overflow
|
|
7792
|
+
if (hasVisibleScrollbar) {
|
|
7793
|
+
container.style.scrollbarGutter = "stable";
|
|
7794
|
+
}
|
|
7762
7795
|
return originalStyles;
|
|
7763
7796
|
};
|
|
7764
7797
|
/**
|
|
@@ -7770,6 +7803,7 @@ const blockContainerScroll = (container) => {
|
|
|
7770
7803
|
const restoreContainerScroll = (container, originalStyles) => {
|
|
7771
7804
|
if (originalStyles.container) {
|
|
7772
7805
|
container.style.overflow = originalStyles.container.overflow;
|
|
7806
|
+
container.style.scrollbarGutter = originalStyles.container.scrollbarGutter;
|
|
7773
7807
|
}
|
|
7774
7808
|
};
|
|
7775
7809
|
/**
|