import { EventEmitter } from '@stencil/core'; import { Side } from '../interface'; declare const __zone_symbol__requestAnimationFrame: any; declare const requestAnimationFrame: any; /** * Patched version of requestAnimationFrame that avoids ngzone * Use only when you know ngzone should not run */ export const raf = (h: any) => { if (typeof __zone_symbol__requestAnimationFrame === 'function') { return __zone_symbol__requestAnimationFrame(h); } if (typeof requestAnimationFrame === 'function') { return requestAnimationFrame(h); } return setTimeout(h); }; export const hasShadowDom = (el: HTMLElement) => { return !!el.shadowRoot && !!(el as any).attachShadow; }; export const findItemLabel = (componentEl: HTMLElement) => { const itemEl = componentEl.closest('ion-item'); if (itemEl) { return itemEl.querySelector('ion-label'); } return null; }; export const renderHiddenInput = (always: boolean, container: HTMLElement, name: string, value: string | undefined | null, disabled: boolean) => { if (always || hasShadowDom(container)) { let input = container.querySelector('input.aux-input') as HTMLInputElement | null; if (!input) { input = container.ownerDocument!.createElement('input'); input.type = 'hidden'; input.classList.add('aux-input'); container.appendChild(input); } input.disabled = disabled; input.name = name; input.value = value || ''; } }; export const clamp = (min: number, n: number, max: number) => { return Math.max(min, Math.min(n, max)); }; export const assert = (actual: any, reason: string) => { if (!actual) { const message = 'ASSERT: ' + reason; console.error(message); debugger; // tslint:disable-line throw new Error(message); } }; export const now = (ev: UIEvent) => { return ev.timeStamp || Date.now(); }; export const pointerCoord = (ev: any): { x: number, y: number } => { // get X coordinates for either a mouse click // or a touch depending on the given event if (ev) { const changedTouches = ev.changedTouches; if (changedTouches && changedTouches.length > 0) { const touch = changedTouches[0]; return { x: touch.clientX, y: touch.clientY }; } if (ev.pageX !== undefined) { return { x: ev.pageX, y: ev.pageY }; } } return { x: 0, y: 0 }; }; /** * @hidden * Given a side, return if it should be on the end * based on the value of dir * @param side the side * @param isRTL whether the application dir is rtl */ export const isEndSide = (side: Side): boolean => { const isRTL = document.dir === 'rtl'; switch (side) { case 'start': return isRTL; case 'end': return !isRTL; default: throw new Error(`"${side}" is not a valid value for [side]. Use "start" or "end" instead.`); } }; export const deferEvent = (event: EventEmitter): EventEmitter => { return debounceEvent(event, 0); }; export const debounceEvent = (event: EventEmitter, wait: number): EventEmitter => { const original = (event as any)._original || event; return { _original: event, emit: debounce(original.emit.bind(original), wait) } as EventEmitter; }; export const debounce = (func: (...args: any[]) => void, wait = 0) => { let timer: any; return (...args: any[]): any => { clearTimeout(timer); timer = setTimeout(func, wait, ...args); }; };