Explorar o código

[frontend] Add an overflow on hover Vue directive

Similar to the ko binding we have to only show scrollbars when mouse is hovering over an element
Johan Ahlen %!s(int64=4) %!d(string=hai) anos
pai
achega
ef24732d51

+ 82 - 0
desktop/core/src/desktop/js/components/directives/overflowOnHoverDirective.ts

@@ -0,0 +1,82 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  Cloudera, Inc. licenses this file
+// to you under the Apache License, Version 2.0 (the
+// 'License'); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an 'AS IS' BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { DirectiveOptions } from 'vue';
+
+interface OverflowOnHoverHTMLElement extends HTMLElement {
+  disposeOverflowOnHover?: () => void;
+}
+
+interface OverflowOnHoverValue {
+  direction?: 'y' | 'x' | 'both';
+}
+
+const getOverflowStyle = (
+  value: OverflowOnHoverValue
+): keyof Pick<CSSStyleDeclaration, 'overflow' | 'overflowX' | 'overflowY'> => {
+  if (value && value.direction === 'x') {
+    return 'overflowX';
+  }
+  if (value && value.direction === 'y') {
+    return 'overflowY';
+  }
+  return 'overflow';
+};
+
+export const overflowOnHover: DirectiveOptions = {
+  bind: (el: OverflowOnHoverHTMLElement, binding) => {
+    const value = <OverflowOnHoverValue>binding.value;
+    const overflowStyle = getOverflowStyle(value);
+    const initialOverflowValue = el.style[overflowStyle];
+    el.style[overflowStyle] = 'hidden';
+
+    let isTouch = false;
+    const onTouchStart = () => {
+      isTouch = true;
+    };
+
+    let showDelay = -1;
+    const onMouseEnter = () => {
+      showDelay = window.setTimeout(() => {
+        el.style[overflowStyle] = 'auto';
+      }, 30);
+    };
+
+    const onMouseLeave = () => {
+      window.clearTimeout(showDelay);
+      if (!isTouch) {
+        el.style[overflowStyle] = 'hidden';
+      }
+    };
+
+    el.addEventListener('touchstart', onTouchStart);
+    el.addEventListener('mouseenter', onMouseEnter);
+    el.addEventListener('mouseleave', onMouseLeave);
+
+    el.disposeOverflowOnHover = () => {
+      window.clearTimeout(showDelay);
+      el.removeEventListener('touchstart', onTouchStart);
+      el.removeEventListener('mouseenter', onMouseEnter);
+      el.removeEventListener('mouseleave', onMouseLeave);
+      el.style[overflowStyle] = initialOverflowValue;
+    };
+  },
+  unbind: (el: OverflowOnHoverHTMLElement) => {
+    if (el.disposeOverflowOnHover) {
+      el.disposeOverflowOnHover();
+    }
+  }
+};