scrolling-BkvA05C8.mjs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /** The possible ways the browser may handle the horizontal scroll axis in RTL languages. */
  2. var RtlScrollAxisType;
  3. (function (RtlScrollAxisType) {
  4. /**
  5. * scrollLeft is 0 when scrolled all the way left and (scrollWidth - clientWidth) when scrolled
  6. * all the way right.
  7. */
  8. RtlScrollAxisType[RtlScrollAxisType["NORMAL"] = 0] = "NORMAL";
  9. /**
  10. * scrollLeft is -(scrollWidth - clientWidth) when scrolled all the way left and 0 when scrolled
  11. * all the way right.
  12. */
  13. RtlScrollAxisType[RtlScrollAxisType["NEGATED"] = 1] = "NEGATED";
  14. /**
  15. * scrollLeft is (scrollWidth - clientWidth) when scrolled all the way left and 0 when scrolled
  16. * all the way right.
  17. */
  18. RtlScrollAxisType[RtlScrollAxisType["INVERTED"] = 2] = "INVERTED";
  19. })(RtlScrollAxisType || (RtlScrollAxisType = {}));
  20. /** Cached result of the way the browser handles the horizontal scroll axis in RTL mode. */
  21. let rtlScrollAxisType;
  22. /** Cached result of the check that indicates whether the browser supports scroll behaviors. */
  23. let scrollBehaviorSupported;
  24. /** Check whether the browser supports scroll behaviors. */
  25. function supportsScrollBehavior() {
  26. if (scrollBehaviorSupported == null) {
  27. // If we're not in the browser, it can't be supported. Also check for `Element`, because
  28. // some projects stub out the global `document` during SSR which can throw us off.
  29. if (typeof document !== 'object' || !document || typeof Element !== 'function' || !Element) {
  30. scrollBehaviorSupported = false;
  31. return scrollBehaviorSupported;
  32. }
  33. // If the element can have a `scrollBehavior` style, we can be sure that it's supported.
  34. if ('scrollBehavior' in document.documentElement.style) {
  35. scrollBehaviorSupported = true;
  36. }
  37. else {
  38. // At this point we have 3 possibilities: `scrollTo` isn't supported at all, it's
  39. // supported but it doesn't handle scroll behavior, or it has been polyfilled.
  40. const scrollToFunction = Element.prototype.scrollTo;
  41. if (scrollToFunction) {
  42. // We can detect if the function has been polyfilled by calling `toString` on it. Native
  43. // functions are obfuscated using `[native code]`, whereas if it was overwritten we'd get
  44. // the actual function source. Via https://davidwalsh.name/detect-native-function. Consider
  45. // polyfilled functions as supporting scroll behavior.
  46. scrollBehaviorSupported = !/\{\s*\[native code\]\s*\}/.test(scrollToFunction.toString());
  47. }
  48. else {
  49. scrollBehaviorSupported = false;
  50. }
  51. }
  52. }
  53. return scrollBehaviorSupported;
  54. }
  55. /**
  56. * Checks the type of RTL scroll axis used by this browser. As of time of writing, Chrome is NORMAL,
  57. * Firefox & Safari are NEGATED, and IE & Edge are INVERTED.
  58. */
  59. function getRtlScrollAxisType() {
  60. // We can't check unless we're on the browser. Just assume 'normal' if we're not.
  61. if (typeof document !== 'object' || !document) {
  62. return RtlScrollAxisType.NORMAL;
  63. }
  64. if (rtlScrollAxisType == null) {
  65. // Create a 1px wide scrolling container and a 2px wide content element.
  66. const scrollContainer = document.createElement('div');
  67. const containerStyle = scrollContainer.style;
  68. scrollContainer.dir = 'rtl';
  69. containerStyle.width = '1px';
  70. containerStyle.overflow = 'auto';
  71. containerStyle.visibility = 'hidden';
  72. containerStyle.pointerEvents = 'none';
  73. containerStyle.position = 'absolute';
  74. const content = document.createElement('div');
  75. const contentStyle = content.style;
  76. contentStyle.width = '2px';
  77. contentStyle.height = '1px';
  78. scrollContainer.appendChild(content);
  79. document.body.appendChild(scrollContainer);
  80. rtlScrollAxisType = RtlScrollAxisType.NORMAL;
  81. // The viewport starts scrolled all the way to the right in RTL mode. If we are in a NORMAL
  82. // browser this would mean that the scrollLeft should be 1. If it's zero instead we know we're
  83. // dealing with one of the other two types of browsers.
  84. if (scrollContainer.scrollLeft === 0) {
  85. // In a NEGATED browser the scrollLeft is always somewhere in [-maxScrollAmount, 0]. For an
  86. // INVERTED browser it is always somewhere in [0, maxScrollAmount]. We can determine which by
  87. // setting to the scrollLeft to 1. This is past the max for a NEGATED browser, so it will
  88. // return 0 when we read it again.
  89. scrollContainer.scrollLeft = 1;
  90. rtlScrollAxisType =
  91. scrollContainer.scrollLeft === 0 ? RtlScrollAxisType.NEGATED : RtlScrollAxisType.INVERTED;
  92. }
  93. scrollContainer.remove();
  94. }
  95. return rtlScrollAxisType;
  96. }
  97. export { RtlScrollAxisType as R, getRtlScrollAxisType as g, supportsScrollBehavior as s };
  98. //# sourceMappingURL=scrolling-BkvA05C8.mjs.map