runtimeDelegationJs top-level constant

String const runtimeDelegationJs

Implementation

const String runtimeDelegationJs = r'''
function findActionTarget(el, attr) {
  let cur = el;
  while (cur && cur !== document) {
    if (cur.nodeType === 1 && cur.hasAttribute(attr)) return cur;
    cur = cur.parentNode;
  }
  return null;
}

function shouldHandleClick(el) {
  if (!el) return false;
  if (el.hasAttribute('data-arcane-disabled')) return false;
  if (el.hasAttribute('disabled')) return false;
  return true;
}

function autoDismissAfterAction(trigger) {
  if (!trigger) return;
  if (trigger.getAttribute('data-arcane-keep-open') === 'true') return;
  const surf = withinSurface(trigger);
  if (!surf) return;
  const stype = surfaceType(surf);
  if (stype !== 'menu' && stype !== 'context-menu' && stype !== 'popover') return;
  if (surf.getAttribute('data-arcane-keep-open-on-action') === 'true') return;
  const sid = surfaceId(surf);
  setTimeout(function() { closeSurface(stype, sid); }, 0);
}

function onDocumentClick(e) {
  if (e.defaultPrevented) return;

  const trigger = findActionTarget(e.target, 'data-arcane-action');
  if (trigger && shouldHandleClick(trigger)) {
    if (trigger.tagName === 'A' && trigger.getAttribute('href')) {
      const href = trigger.getAttribute('href');
      if (href.indexOf('#') !== 0 && trigger.target !== '_blank') {
        e.preventDefault();
      }
    }
    if (trigger.tagName === 'BUTTON' || trigger.getAttribute('role') === 'button') {
      e.preventDefault();
    }
    runActions(trigger.getAttribute('data-arcane-action'), { trigger: trigger, event: e });
    autoDismissAfterAction(trigger);
    return;
  }

  if (ARCANE.stack.length > 0) {
    const top = ARCANE.stack[ARCANE.stack.length - 1];
    const surfaceEl = top.el;
    if (surfaceEl && !surfaceEl.contains(e.target)) {
      const scrimCloses = surfaceEl.getAttribute('data-arcane-scrim-closes') !== 'false';
      const dismissible = surfaceEl.getAttribute('data-arcane-dismissible') !== 'false';
      if (scrimCloses && dismissible) {
        if ((top.type === 'popover' || top.type === 'menu' || top.type === 'context-menu' || top.type === 'tooltip') ||
            e.target.classList.contains('arcane-overlay-scrim') ||
            e.target.hasAttribute('data-arcane-scrim') ||
            (top.type === 'dialog' || top.type === 'sheet' || top.type === 'drawer')) {
          if (top.type === 'dialog' || top.type === 'sheet' || top.type === 'drawer') {
            if (e.target.classList.contains('arcane-overlay-scrim') ||
                e.target.hasAttribute('data-arcane-scrim') ||
                e.target === surfaceEl.parentElement) {
              closeSurface(top.type, top.id);
            }
          } else {
            closeSurface(top.type, top.id);
          }
        }
      }
    }
  }
}

function onDocumentChange(e) {
  const target = findActionTarget(e.target, 'data-arcane-change');
  if (target) {
    runActions(target.getAttribute('data-arcane-change'), { trigger: target, event: e });
  }
  if (e.target.matches && e.target.matches('[data-arcane-form] [data-arcane-field]')) {
    const formEl = findClosest(e.target, '[data-arcane-form]');
    if (formEl) {
      const fid = formEl.getAttribute('data-arcane-form');
      const fname = e.target.getAttribute('data-arcane-field');
      if (fid && fname) validateField(fid, fname);
    }
  }
}

function onDocumentInput(e) {
  const target = findActionTarget(e.target, 'data-arcane-input');
  if (target) {
    runActions(target.getAttribute('data-arcane-input'), { trigger: target, event: e });
  }
}

function onDocumentSubmit(e) {
  const formEl = findActionTarget(e.target, 'data-arcane-form');
  if (formEl) {
    e.preventDefault();
    const fid = formEl.getAttribute('data-arcane-form');
    if (fid) submitForm(fid);
  }
  const target = findActionTarget(e.target, 'data-arcane-submit');
  if (target) {
    runActions(target.getAttribute('data-arcane-submit'), { trigger: target, event: e });
  }
}

function onDocumentDblClick(e) {
  const target = findActionTarget(e.target, 'data-arcane-dblclick');
  if (target) {
    runActions(target.getAttribute('data-arcane-dblclick'), { trigger: target, event: e });
  }
}

function onDocumentContextMenu(e) {
  const target = findActionTarget(e.target, 'data-arcane-contextmenu');
  if (target) {
    e.preventDefault();
    runActions(target.getAttribute('data-arcane-contextmenu'), { trigger: target, event: e });
  }
}

function onDocumentKeyDown(e) {
  if (e.key === 'Escape') {
    if (ARCANE.stack.length > 0) {
      const top = ARCANE.stack[ARCANE.stack.length - 1];
      const surfaceEl = top.el;
      if (surfaceEl && surfaceEl.getAttribute('data-arcane-escape-closes') !== 'false') {
        closeSurface(top.type, top.id);
        e.preventDefault();
        e.stopPropagation();
        return;
      }
    }
  }
  if (e.key === 'Tab' && ARCANE.stack.length > 0) {
    const top = ARCANE.stack[ARCANE.stack.length - 1];
    const surfaceEl = top.el;
    if (surfaceEl && (top.type === 'dialog' || top.type === 'sheet' ||
        surfaceEl.getAttribute('data-arcane-focus-trap') === 'true')) {
      trapFocus(surfaceEl, e);
    }
  }
  if (e.key === 'Enter' || e.key === ' ') {
    const target = e.target;
    if (target && target.matches && target.matches('[data-arcane-action]') &&
        target.tagName !== 'BUTTON' && target.tagName !== 'A' &&
        target.tagName !== 'INPUT' && target.tagName !== 'TEXTAREA' &&
        target.tagName !== 'SELECT') {
      e.preventDefault();
      runActions(target.getAttribute('data-arcane-action'), { trigger: target, event: e });
    }
  }
  if (e.key === 'ArrowLeft' || e.key === 'ArrowRight' ||
      e.key === 'ArrowUp' || e.key === 'ArrowDown') {
    handleArrowKey(e);
  }

  const keyTarget = findActionTarget(e.target, 'data-arcane-keydown');
  if (keyTarget) {
    runActions(keyTarget.getAttribute('data-arcane-keydown'), { trigger: keyTarget, event: e });
  }
}

function handleArrowKey(e) {
  const tab = findClosest(e.target, '[role="tab"][data-arcane-tab]');
  if (tab) {
    const groupId = tab.getAttribute('data-arcane-tabs-group');
    const orientation = (findClosest(tab, '[data-arcane-tabs-orientation]') || {}).getAttribute &&
      findClosest(tab, '[data-arcane-tabs-orientation]').getAttribute('data-arcane-tabs-orientation') || 'horizontal';
    const isHorizontal = orientation === 'horizontal';
    const forward = isHorizontal ? e.key === 'ArrowRight' : e.key === 'ArrowDown';
    const backward = isHorizontal ? e.key === 'ArrowLeft' : e.key === 'ArrowUp';
    if (forward || backward) {
      e.preventDefault();
      const triggers = Array.prototype.slice.call(document.querySelectorAll(
        '[data-arcane-tabs-group="' + cssEscape(groupId) + '"][data-arcane-tab]'
      ));
      const idx = triggers.indexOf(tab);
      let next = forward ? idx + 1 : idx - 1;
      if (next < 0) next = triggers.length - 1;
      if (next >= triggers.length) next = 0;
      const nextTab = triggers[next];
      if (nextTab) {
        activateTab(groupId, nextTab.getAttribute('data-arcane-tab'));
        nextTab.focus();
      }
      return;
    }
  }

  const opt = findClosest(e.target, '[data-arcane-group][data-arcane-value]');
  if (opt) {
    const surf = withinSurface(opt);
    if (surf && (surfaceType(surf) === 'menu' || surfaceType(surf) === 'context-menu' ||
        surfaceType(surf) === 'popover' || surfaceType(surf) === 'command')) {
      const forward = e.key === 'ArrowDown';
      const backward = e.key === 'ArrowUp';
      if (forward || backward) {
        e.preventDefault();
        const groupId = opt.getAttribute('data-arcane-group');
        const items = Array.prototype.slice.call(surf.querySelectorAll(
          '[data-arcane-group="' + cssEscape(groupId) + '"][data-arcane-value]:not([data-arcane-disabled="true"])'
        ));
        const idx = items.indexOf(opt);
        let next = forward ? idx + 1 : idx - 1;
        if (next < 0) next = items.length - 1;
        if (next >= items.length) next = 0;
        if (items[next]) items[next].focus();
        return;
      }
    }
  }
}

function onPointerOver(e) {
  const trigger = findActionTarget(e.target, 'data-arcane-mouseenter');
  if (trigger) {
    runActions(trigger.getAttribute('data-arcane-mouseenter'), { trigger: trigger, event: e });
  }
  const hoverTrigger = findActionTarget(e.target, 'data-arcane-hover-target');
  if (hoverTrigger) {
    const targetId = hoverTrigger.getAttribute('data-arcane-hover-target');
    const surfaceType = hoverTrigger.getAttribute('data-arcane-hover-surface') || 'tooltip';
    const delay = parseInt(hoverTrigger.getAttribute('data-arcane-hover-delay') || '120', 10);
    if (hoverTrigger._arcaneHoverTimer) clearTimeout(hoverTrigger._arcaneHoverTimer);
    hoverTrigger._arcaneHoverTimer = setTimeout(function() {
      openSurface(surfaceType, targetId, { trigger: hoverTrigger });
    }, delay);
  }
}

function onPointerOut(e) {
  const trigger = findActionTarget(e.target, 'data-arcane-mouseleave');
  if (trigger && !trigger.contains(e.relatedTarget)) {
    runActions(trigger.getAttribute('data-arcane-mouseleave'), { trigger: trigger, event: e });
  }
  const hoverTrigger = findActionTarget(e.target, 'data-arcane-hover-target');
  if (hoverTrigger && !hoverTrigger.contains(e.relatedTarget)) {
    if (hoverTrigger._arcaneHoverTimer) clearTimeout(hoverTrigger._arcaneHoverTimer);
    const targetId = hoverTrigger.getAttribute('data-arcane-hover-target');
    const surfaceType = hoverTrigger.getAttribute('data-arcane-hover-surface') || 'tooltip';
    const delay = parseInt(hoverTrigger.getAttribute('data-arcane-hover-close-delay') || '60', 10);
    hoverTrigger._arcaneHoverTimer = setTimeout(function() {
      const surf = querySurface(surfaceType, targetId);
      if (surf && !surf.matches(':hover')) {
        closeSurface(surfaceType, targetId);
      }
    }, delay);
  }
}

function onFocusIn(e) {
  const trigger = findActionTarget(e.target, 'data-arcane-focus');
  if (trigger) {
    runActions(trigger.getAttribute('data-arcane-focus'), { trigger: trigger, event: e });
  }
}

function onFocusOut(e) {
  const trigger = findActionTarget(e.target, 'data-arcane-blur');
  if (trigger) {
    runActions(trigger.getAttribute('data-arcane-blur'), { trigger: trigger, event: e });
  }
}

ARCANE.delegation = {
  click: onDocumentClick,
  change: onDocumentChange,
  input: onDocumentInput,
  submit: onDocumentSubmit,
  dblclick: onDocumentDblClick,
  contextmenu: onDocumentContextMenu,
  keydown: onDocumentKeyDown,
  pointerover: onPointerOver,
  pointerout: onPointerOut,
  focusin: onFocusIn,
  focusout: onFocusOut
};
''';