Расширение интерфейсов

Tippy.js предоставляет гибкий API для создания интерактивных всплывающих подсказок, которое можно расширять через интерфейсы и плагины. Важным аспектом является возможность расширять существующие типы и интерфейсы для адаптации поведения тултипов под специфические задачи приложения.


Интерфейс TippyProps

Основной интерфейс конфигурации — TippyProps. Он определяет все опции, которые могут быть переданы при инициализации тултипа:

interface TippyProps {
  content: string | Element;
  placement?: 'top' | 'bottom' | 'left' | 'right' | 'auto';
  trigger?: 'mouseenter' | 'click' | 'focus' | 'manual';
  animation?: 'fade' | 'scale' | 'shift-away' | 'perspective';
  duration?: number | [number, number];
  delay?: number | [number, number];
  interactive?: boolean;
  arrow?: boolean | Element;
  theme?: string;
  maxWidth?: number | string;
  onShow?: (instance: Instance) => void;
  onHide?: (instance: Instance) => void;
  [key: string]: any;
}

Ключевой момент: интерфейс допускает добавление произвольных свойств через [key: string]: any;, что позволяет создавать расширенные конфигурации без изменения исходного кода библиотеки.


Создание собственных типов тултипов

Можно определить собственный интерфейс, который расширяет TippyProps и добавляет специфические свойства. Например, для тултипов с подсветкой текста:

interface HighlightTippyProps extends TippyProps {
  highlightColor?: string;
  animationSpeed?: number;
}

Теперь при инициализации тултипа можно использовать новые свойства:

tippy('.highlight', {
  content: 'Выделенный текст',
  highlightColor: '#ffcc00',
  animationSpeed: 500,
});

Эти свойства можно использовать в пользовательских плагинах или при кастомизации анимации.


Расширение интерфейса Instance

Объект Instance возвращается при создании тултипа и содержит методы управления тултипом:

interface Instance {
  show(): void;
  hide(): void;
  setContent(content: string | Element): void;
  destroy(): void;
  props: TippyProps;
  state: {
    isVisible: boolean;
    isMounted: boolean;
  };
}

Для расширения можно добавить собственные методы через декораторы или TypeScript interface merging:

interface ExtendedInstance extends Instance {
  toggleVisibility(): void;
}

const instance: ExtendedInstance = tippy('#btn', { content: 'Привет' }) as ExtendedInstance;

instance.toggleVisibility = function() {
  if (this.state.isVisible) this.hide();
  else this.show();
};

Это позволяет создавать переиспользуемые расширения функционала без изменения исходного Tippy.js.


Расширение через плагины

Tippy.js поддерживает плагины, которые могут добавлять новые свойства и события. Для TypeScript важно определить интерфейс плагина:

interface TippyPlugin {
  name: string;
  defaultValue?: any;
  fn?: (instance: Instance) => {
    onCreate?: () => void;
    onDestroy?: () => void;
    onShow?: () => void;
  };
}

Пример плагина для подсветки тултипа:

const highlightPlugin: TippyPlugin = {
  name: 'highlightPlugin',
  fn(instance) {
    return {
      onShow() {
        const el = instance.popper;
        el.style.backgroundColor = instance.props.highlightColor || '#ffd';
      },
      onHide() {
        instance.popper.style.backgroundColor = '';
      },
    };
  },
};

Подключение плагина:

tippy('.highlight', {
  content: 'С подсветкой',
  highlightColor: '#ff0',
  plugins: [highlightPlugin],
});

Интерфейсы для кастомных тем и анимаций

Tippy.js позволяет создавать кастомные темы и анимации, что требует расширения интерфейсов CSS-свойств:

interface ThemeStyles {
  [themeName: string]: {
    arrow?: string;
    popper?: string;
    animationDuration?: number;
  };
}

const themes: ThemeStyles = {
  bright: {
    arrow: '2px solid yellow',
    popper: 'background-color: #fffacd; color: #333;',
    animationDuration: 300,
  },
};

При создании тултипа можно передавать тему с расширенными стилями:

tippy('.bright', {
  content: 'Яркий тултип',
  theme: 'bright',
});

Использование interface merging в TypeScript

TypeScript позволяет расширять существующие интерфейсы без создания нового имени:

declare module 'tippy.js' {
  interface TippyProps {
    customClass?: string;
    trackingId?: string;
  }
}

После этого любые тултипы могут использовать customClass и trackingId:

tippy('.track', {
  content: 'С трекингом',
  customClass: 'tooltip-tracking',
  trackingId: 'tooltip_01',
});

Это удобно для интеграции тултипов в корпоративные приложения с аналитикой и кастомными стилями.


Вывод

Расширение интерфейсов в Tippy.js позволяет:

  • Добавлять новые свойства в TippyProps и Instance.
  • Создавать кастомные плагины с новыми методами и событиями.
  • Интегрировать тултипы с анимациями, стилями и аналитикой.
  • Использовать TypeScript interface merging для безопасной типизации без модификации библиотеки.

Такой подход делает Tippy.js модульным и легко настраиваемым для сложных и уникальных пользовательских интерфейсов.