remirror/remirror

View on GitHub
packages/remirror__extension-react-tables/src/utils/dom.ts

Summary

Maintainability
A
0 mins
Test Coverage
F
0%
import { cx, isNullOrUndefined } from '@remirror/core';

export function h<T extends keyof HTMLElementTagNameMap>(
  tagName: T,
  attrs?: HTMLAttributes<T> | null,
  ...children: Array<string | Node>
): HTMLElementTagNameMap[T] {
  const element = document.createElement(tagName);

  if (attrs) {
    for (let [key, value] of Object.entries(attrs)) {
      if (isNullOrUndefined(value)) {
        continue;
      }

      key = key.toLowerCase();

      if (/^on[a-z]+/.test(key) && typeof value === 'function') {
        element.addEventListener(key.slice(2), value as EventHandler);
      } else if (['class', 'classname'].includes(key)) {
        element.className = cx(value as string);
      } else if (key === 'dataset') {
        for (const [dataKey, dataValue] of Object.entries(value as Record<string, string>)) {
          element.dataset[dataKey] = dataValue;
        }
      } else if (key === 'style' && typeof value === 'object') {
        Object.assign(element.style, value);
      } else if (['number', 'boolean', 'string'].includes(typeof value)) {
        element.setAttribute(key, `${value}`);
      } else {
        throw new TypeError(`Unexpected ${typeof value} value for attribute "${key}"`);
      }
    }
  }

  element.append(...children);
  return element;
}

export function stopEvent(e: Pick<MouseEvent, 'preventDefault' | 'stopPropagation'>): void {
  e.preventDefault();
  e.stopPropagation();
}

interface Coord {
  x: number;
  y: number;
}

export function getRelativeCoord(absoluteCoord: Coord, parent: Element): Coord {
  const parentRect = parent.getBoundingClientRect();
  return {
    x: absoluteCoord.x + parent.scrollLeft - parentRect.left,
    y: absoluteCoord.y + parent.scrollTop - parentRect.top,
  };
}

export function getAbsoluteCoord(relativeCoord: Coord, parent: Element): Coord {
  const parentRect = parent.getBoundingClientRect();
  return {
    x: relativeCoord.x - parent.scrollLeft + parentRect.left,
    y: relativeCoord.y - parent.scrollTop + parentRect.top,
  };
}

type EventHandler<E extends Event = Event, T = Element> = (this: T, event: E) => void;

type ClipboardEventHandler<T = Element> = EventHandler<ClipboardEvent, T>;
type CompositionEventHandler<T = Element> = EventHandler<CompositionEvent, T>;
type DragEventHandler<T = Element> = EventHandler<DragEvent, T>;
type FocusEventHandler<T = Element> = EventHandler<FocusEvent, T>;
type FormEventHandler<T = Element> = EventHandler<Event, T>;
type KeyboardEventHandler<T = Element> = EventHandler<KeyboardEvent, T>;
type MouseEventHandler<T = Element> = EventHandler<MouseEvent, T>;
type TouchEventHandler<T = Element> = EventHandler<TouchEvent, T>;
type PointerEventHandler<T = Element> = EventHandler<PointerEvent, T>;
type UIEventHandler<T = Element> = EventHandler<UIEvent, T>;
type WheelEventHandler<T = Element> = EventHandler<WheelEvent, T>;
type AnimationEventHandler<T = Element> = EventHandler<AnimationEvent, T>;
type TransitionEventHandler<T = Element> = EventHandler<TransitionEvent, T>;

export interface DOMEvents<T> {
  // Clipboard Events
  onCopy?: ClipboardEventHandler<T> | undefined;
  onCopyCapture?: ClipboardEventHandler<T> | undefined;
  onCut?: ClipboardEventHandler<T> | undefined;
  onCutCapture?: ClipboardEventHandler<T> | undefined;
  onPaste?: ClipboardEventHandler<T> | undefined;
  onPasteCapture?: ClipboardEventHandler<T> | undefined;

  // Composition Events
  onCompositionEnd?: CompositionEventHandler<T> | undefined;
  onCompositionEndCapture?: CompositionEventHandler<T> | undefined;
  onCompositionStart?: CompositionEventHandler<T> | undefined;
  onCompositionStartCapture?: CompositionEventHandler<T> | undefined;
  onCompositionUpdate?: CompositionEventHandler<T> | undefined;
  onCompositionUpdateCapture?: CompositionEventHandler<T> | undefined;

  // Focus Events
  onFocus?: FocusEventHandler<T> | undefined;
  onFocusCapture?: FocusEventHandler<T> | undefined;
  onBlur?: FocusEventHandler<T> | undefined;
  onBlurCapture?: FocusEventHandler<T> | undefined;

  // Form Events
  onChange?: FormEventHandler<T> | undefined;
  onChangeCapture?: FormEventHandler<T> | undefined;
  onBeforeInput?: FormEventHandler<T> | undefined;
  onBeforeInputCapture?: FormEventHandler<T> | undefined;
  onInput?: FormEventHandler<T> | undefined;
  onInputCapture?: FormEventHandler<T> | undefined;
  onReset?: FormEventHandler<T> | undefined;
  onResetCapture?: FormEventHandler<T> | undefined;
  onSubmit?: FormEventHandler<T> | undefined;
  onSubmitCapture?: FormEventHandler<T> | undefined;
  onInvalid?: FormEventHandler<T> | undefined;
  onInvalidCapture?: FormEventHandler<T> | undefined;

  // Keyboard Events
  onKeyDown?: KeyboardEventHandler<T> | undefined;
  onKeyDownCapture?: KeyboardEventHandler<T> | undefined;
  onKeyPress?: KeyboardEventHandler<T> | undefined;
  onKeyPressCapture?: KeyboardEventHandler<T> | undefined;
  onKeyUp?: KeyboardEventHandler<T> | undefined;
  onKeyUpCapture?: KeyboardEventHandler<T> | undefined;

  // MouseEvents
  onAuxClick?: MouseEventHandler<T> | undefined;
  onAuxClickCapture?: MouseEventHandler<T> | undefined;
  onClick?: MouseEventHandler<T> | undefined;
  onClickCapture?: MouseEventHandler<T> | undefined;
  onContextMenu?: MouseEventHandler<T> | undefined;
  onContextMenuCapture?: MouseEventHandler<T> | undefined;
  onDblClick?: MouseEventHandler<T> | undefined;
  onDblClickCapture?: MouseEventHandler<T> | undefined;
  onDoubleClick?: MouseEventHandler<T> | undefined;
  onDoubleClickCapture?: MouseEventHandler<T> | undefined;
  onDrag?: DragEventHandler<T> | undefined;
  onDragCapture?: DragEventHandler<T> | undefined;
  onDragEnd?: DragEventHandler<T> | undefined;
  onDragEndCapture?: DragEventHandler<T> | undefined;
  onDragEnter?: DragEventHandler<T> | undefined;
  onDragEnterCapture?: DragEventHandler<T> | undefined;
  onDragExit?: DragEventHandler<T> | undefined;
  onDragExitCapture?: DragEventHandler<T> | undefined;
  onDragLeave?: DragEventHandler<T> | undefined;
  onDragLeaveCapture?: DragEventHandler<T> | undefined;
  onDragOver?: DragEventHandler<T> | undefined;
  onDragOverCapture?: DragEventHandler<T> | undefined;
  onDragStart?: DragEventHandler<T> | undefined;
  onDragStartCapture?: DragEventHandler<T> | undefined;
  onDrop?: DragEventHandler<T> | undefined;
  onDropCapture?: DragEventHandler<T> | undefined;
  onMouseDown?: MouseEventHandler<T> | undefined;
  onMouseDownCapture?: MouseEventHandler<T> | undefined;
  onMouseEnter?: MouseEventHandler<T> | undefined;
  onMouseLeave?: MouseEventHandler<T> | undefined;
  onMouseMove?: MouseEventHandler<T> | undefined;
  onMouseMoveCapture?: MouseEventHandler<T> | undefined;
  onMouseOut?: MouseEventHandler<T> | undefined;
  onMouseOutCapture?: MouseEventHandler<T> | undefined;
  onMouseOver?: MouseEventHandler<T> | undefined;
  onMouseOverCapture?: MouseEventHandler<T> | undefined;
  onMouseUp?: MouseEventHandler<T> | undefined;
  onMouseUpCapture?: MouseEventHandler<T> | undefined;

  // Touch Events
  onTouchCancel?: TouchEventHandler<T> | undefined;
  onTouchCancelCapture?: TouchEventHandler<T> | undefined;
  onTouchEnd?: TouchEventHandler<T> | undefined;
  onTouchEndCapture?: TouchEventHandler<T> | undefined;
  onTouchMove?: TouchEventHandler<T> | undefined;
  onTouchMoveCapture?: TouchEventHandler<T> | undefined;
  onTouchStart?: TouchEventHandler<T> | undefined;
  onTouchStartCapture?: TouchEventHandler<T> | undefined;

  // Pointer Events
  onPointerDown?: PointerEventHandler<T> | undefined;
  onPointerDownCapture?: PointerEventHandler<T> | undefined;
  onPointerMove?: PointerEventHandler<T> | undefined;
  onPointerMoveCapture?: PointerEventHandler<T> | undefined;
  onPointerUp?: PointerEventHandler<T> | undefined;
  onPointerUpCapture?: PointerEventHandler<T> | undefined;
  onPointerCancel?: PointerEventHandler<T> | undefined;
  onPointerCancelCapture?: PointerEventHandler<T> | undefined;
  onPointerEnter?: PointerEventHandler<T> | undefined;
  onPointerEnterCapture?: PointerEventHandler<T> | undefined;
  onPointerLeave?: PointerEventHandler<T> | undefined;
  onPointerLeaveCapture?: PointerEventHandler<T> | undefined;
  onPointerOver?: PointerEventHandler<T> | undefined;
  onPointerOverCapture?: PointerEventHandler<T> | undefined;
  onPointerOut?: PointerEventHandler<T> | undefined;
  onPointerOutCapture?: PointerEventHandler<T> | undefined;
  onGotPointerCapture?: PointerEventHandler<T> | undefined;
  onGotPointerCaptureCapture?: PointerEventHandler<T> | undefined;
  onLostPointerCapture?: PointerEventHandler<T> | undefined;
  onLostPointerCaptureCapture?: PointerEventHandler<T> | undefined;

  // UI Events
  onScroll?: UIEventHandler<T> | undefined;
  onScrollCapture?: UIEventHandler<T> | undefined;

  // Wheel Events
  onWheel?: WheelEventHandler<T> | undefined;
  onWheelCapture?: WheelEventHandler<T> | undefined;

  // Animation Events
  onAnimationStart?: AnimationEventHandler<T> | undefined;
  onAnimationStartCapture?: AnimationEventHandler<T> | undefined;
  onAnimationEnd?: AnimationEventHandler<T> | undefined;
  onAnimationEndCapture?: AnimationEventHandler<T> | undefined;
  onAnimationIteration?: AnimationEventHandler<T> | undefined;
  onAnimationIterationCapture?: AnimationEventHandler<T> | undefined;

  // Transition Events
  onTransitionEnd?: TransitionEventHandler<T> | undefined;
  onTransitionEndCapture?: TransitionEventHandler<T> | undefined;
}

type HTMLAttributes<T extends keyof HTMLElementTagNameMap> = Partial<
  Omit<HTMLElementTagNameMap[T], 'style'> & { style: Partial<HTMLElement['style']> }
> &
  DOMEvents<HTMLElementTagNameMap[T]>;