API Reference - @weavix/sdk-react

Components

TrackerPluginProvider

Провайдер для инициализации плагина Tracker. Оборачивает приложение и управляет жизненным циклом плагина. Предоставляет тему, язык и контекст слота через контекст React.

Props: TrackerPluginProviderProps

Features

  • Автоматическая инициализация плагина
  • Управление состояниями загрузки и ошибок
  • Предоставление контекста через React Context API
  • Автоматическое уведомление хоста о готовности плагина
  • Защита от двойной инициализации в React StrictMode

Example (базовое использование)

import { TrackerPluginProvider } from '@weavix/sdk-react';
import { createRoot } from 'react-dom/client';
import { App } from './App';

const root = createRoot(document.getElementById('root')!);

root.render(
  <TrackerPluginProvider>
    <App />
  </TrackerPluginProvider>,
);

Example (с кастомными опциями)

import { TrackerPluginProvider } from '@weavix/sdk-react';
import { Loader } from './components/Loader';
import { ErrorScreen } from './components/ErrorScreen';

root.render(
  <TrackerPluginProvider
    autoResize={false}
    fallback={<Loader />}
    errorFallback={(error) => <ErrorScreen error={error} />}
    autoNotifyReady={false}
  >
    <App />
  </TrackerPluginProvider>,
);

Example (отключение автоматического уведомления)

import { TrackerPluginProvider, hostApi } from '@weavix/sdk-react';

function App() {
  useEffect(() => {
    // Выполняем дополнительную инициализацию, затем уведомляем хост
    initializeApp().then(() => {
      hostApi.notifyReady()
    });
  }, []);

  return <div>My Plugin</div>;
}

root.render(
  <TrackerPluginProvider autoNotifyReady={false}>
    <App />
  </TrackerPluginProvider>,
);

Hooks

useTrackerPluginContext

Хук для получения темы, языка и контекста слота из TrackerPluginProvider. Поддерживает несколько перегрузок в зависимости от level и generic-параметра TSlot.

Type Signature

// level: 'basic' — базовый контекст (только entityId и entityMeta), тип slotContext сужается по проверке slot
function useTrackerPluginContext(level: 'basic'): {
    [K in keyof SlotContextMap]: BasicTrackerPluginContextValue<K>;
}[keyof SlotContextMap];

// level: 'full' — полный контекст с живыми данными сущности
function useTrackerPluginContext(level: 'full'): {
    [K in keyof SlotContextMap]: FullTrackerPluginContextValue<K>;
}[keyof SlotContextMap];

// С generic TSlot и level: 'basic' — типизированный базовый контекст для конкретного слота
function useTrackerPluginContext<TSlot extends keyof SlotContextMap>(
    level: 'basic',
): BasicTrackerPluginContextValue<TSlot>;

// С generic TSlot и level: 'full' — типизированный полный контекст для конкретного слота
function useTrackerPluginContext<TSlot extends keyof SlotContextMap>(
    level: 'full',
): FullTrackerPluginContextValue<TSlot>;

Parameters

  • level'basic' | 'full' (обязательный) — уровень контекста слота. Должен совпадать со значением contextLevel, указанным для слота в manifest.json. Подробнее — в разделе Уровни контекста слота.

Type Parameters

  • TSlot — тип слота (опционально). С generic — slotContext типизирован под этот слот. Без generic — можно сужать по slot === 'issue.action' и т.д.

Returns

BasicTrackerPluginContextValue<TSlot> или FullTrackerPluginContextValue<TSlot> в зависимости от level, либо union по всем слотам.

Throws

Example (basic контекст)

import { useTrackerPluginContext } from '@weavix/sdk-react';

function MyComponent() {
  const { theme, language, slotContext } = useTrackerPluginContext('basic');
  // slotContext.entityId — идентификатор текущей сущности
  // slotContext.entityMeta — дополнительные базовые метаданные (опционально)

  return (
    <div className={theme}>
      <p>Language: {language}</p>
      <p>Entity ID: {slotContext.entityId}</p>
    </div>
  );
}

Example (basic — слот известен)

const { slotContext } = useTrackerPluginContext<'issue.action'>('basic');
slotContext.entityId; // идентификатор тикета
slotContext.entityMeta; // дополнительные метаданные

Example (несколько слотов — сужение по slot)

const { slot, slotContext } = useTrackerPluginContext('basic');
if (slot === 'issue.action') {
  slotContext.entityId; // здесь slotContext типизирован под слот issue.action
}

Example (full контекст с типизацией слота)

import { useTrackerPluginContext } from '@weavix/sdk-react';

function IssuePlugin() {
  // В manifest.json для слота: contextLevel: "full"
  const { theme, language, slotContext } = useTrackerPluginContext<'issue.action'>('full');
  return (
    <div>
      <h1>Issue: {slotContext.key}</h1>
      <p>Version: {slotContext.version}</p>
      <p>Theme: {theme}</p>
    </div>
  );
}

useLocalizedString

Хук для получения локализованной строки на основе текущего языка из контекста TrackerPluginProvider.

Type Signature

function useLocalizedString(fallbackLanguage?: string): (value: LocalizedString) => string;

Parameters

  • fallbackLanguage - string (опционально, по умолчанию 'en') - резервный язык, если основной не найден

Returns

Функция для локализации строк (value: LocalizedString) => string.

Example (базовое использование)

import { useLocalizedString } from '@weavix/sdk-react';

function MyComponent() {
  const localize = useLocalizedString();

  const field = {
    name: { ru: 'Имя', en: 'Name' },
    description: { ru: 'Описание', en: 'Description' },
  };

  return (
    <div>
      <h1>{localize(field.name)}</h1>
      <p>{localize(field.description)}</p>
    </div>
  );
}

Example (с резервным языком)

import { useLocalizedString } from '@weavix/sdk-react';

function MyComponent() {
  // Если перевод на текущем языке не найден, используется русский
  const localize = useLocalizedString('ru');

  const name = { en: 'Name' }; // нет русского перевода

  return <div>{localize(name)}</div>; // вернет 'Name'
}

Example (работа с полями задачи)

import {
  useLocalizedString,
  useTrackerPluginContext,
} from '@weavix/sdk-react';
import { trackerApi } from '@weavix/sdk-react';

function FieldsList() {
  const localize = useLocalizedString();
  const { slotContext } = useTrackerPluginContext<'issue.action'>();
  const [fields, setFields] = useState([]);

  useEffect(() => {
    trackerApi.v3.get['/fields/...']({ ... }).then(setFields);
  }, []);

  return (
    <ul>
      {fields.map((field) => (
        <li key={field.id}>
          <strong>{localize(field.name)}</strong>
          {field.description && <p>{localize(field.description)}</p>}
        </li>
      ))}
    </ul>
  );
}

useToaster

Хук для показа toast-уведомлений в хост-приложении. Возвращает объект с методом add.

Permission

В manifest.json нужно запросить tracker:ui:toaster:

{
    "permissions": {
        "ui": ["toaster"]
    }
}
import { useToaster } from '@weavix/sdk-react';

function MyComponent() {
  const toaster = useToaster();

  const handleSave = async () => {
    await saveData();
    toaster.add({
      title: 'Сохранено',
      theme: 'success',
    });
  };

  const handleDelete = async () => {
    await deleteItem(id);
    toaster.add({
      title: 'Удалено',
      theme: 'info',
      content: 'QUEUE-123',
      actions: [
        {
          label: 'Отменить',
          onClick: () => restoreItem(id),
        },
      ],
    });
  };

  return (
    <div>
      <button onClick={handleSave}>Сохранить</button>
      <button onClick={handleDelete}>Удалить</button>
    </div>
  );
}

Полный список параметров add(options) — в core.

useConfirm

Плагин может показать модальный диалог подтверждения. Диалог рендерится на стороне трекера, а не внутри iframe, поэтому перекрывает всё приложение и фокусирует пользователя на принятии решения.

Permission

В manifest.json нужно запросить tracker:ui:confirm:

{
    "permissions": {
        "ui": ["confirm"]
    }
}
import { useConfirm } from '@weavix/sdk-react';

function DeleteButton() {
    const confirm = useConfirm();

    const handleClick = async () => {
        const { confirmed } = await confirm.show({
            title: 'Удаление',
            message: 'Уверены что хотите удалить? Действие необратимо.',
            textButtonApply: 'Удалить',
            textButtonCancel: 'Отмена',
            theme: 'danger',
        });

        if (confirmed) {
            // выполняем действие
        }
    };

    return <button onClick={handleClick}>Удалить</button>;
}

Полный список параметров — в core.

Types

TrackerPluginProviderProps

Свойства компонента TrackerPluginProvider.

interface TrackerPluginProviderProps {
  /** Дочерние элементы */
  children: ReactNode;

  /**
   * Автоматически изменять размер контейнера плагина при изменении содержимого
   * @default true
   */
  autoResize?: boolean;

  /**
   * Компонент для отображения во время инициализации
   * @default <PluginLoader />
   */
  fallback?: ReactNode;

  /**
   * Компонент для отображения при ошибке инициализации
   * @default <PluginError error={error} />
   */
  errorFallback?: (error: Error) => ReactNode;

  /**
   * Автоматически уведомить хост о готовности плагина после инициализации
   * @default true
   */
  autoNotifyReady?: boolean;
}

Properties

Свойство

Тип

Обязательное

По умолчанию

Описание

children

ReactNode

Да

Дочерние компоненты, которые будут отрендерены после успешной инициализации

autoResize

boolean

Нет

true

Автоматически изменять размер контейнера плагина при изменении содержимого. Включает отслеживание изменений DOM и автоматическую отправку новой высоты хосту

fallback

ReactNode

Нет

Встроенный компонент <PluginLoader />

Компонент, отображаемый во время инициализации плагина

errorFallback

(error: Error) =>
  ReactNode

Нет

Встроенный компонент

<PluginError
error={error} />

Функция, возвращающая компонент для отображения при ошибке инициализации

autoNotifyReady

boolean

Нет

true

Автоматически уведомлять хост о готовности плагина после инициализации

Примеры использования свойств — в разделе Components выше.

Элементы с относительной высотой

Если вы используете элементы с относительной высотой (vh, % и т.п.), то автоматическое изменение размеров (autoResize) может вести себя неожиданно.
Если же вы все-таки хотите использовать компоненты с относительной высотой, то выключите автоматическое изменение размеров.

TrackerPluginContextValue

Значение контекста, предоставляемое TrackerPluginProvider. Тип slotContext зависит от запрошенного уровня контекста (level).

BasicTrackerPluginContextValue

Возвращается при level: 'basic'. slotContext содержит только идентификатор сущности и базовые метаданные.

interface BasicTrackerPluginContextValue<TSlot extends keyof SlotContextMap = keyof SlotContextMap> {
  theme: Theme;
  language: string;
  /** Имя слота, в котором открыт плагин */
  slot: TSlot;
  /** Базовый контекст слота */
  slotContext: {
    /** Идентификатор текущей сущности */
    entityId: string;
    /** Дополнительная базовая информация.
     *  Например, для комментария содержит идентификатор родительского тикета. */
    entityMeta?: Record<string, string>;
  };
}

FullTrackerPluginContextValue

Возвращается при level: 'full'. slotContext содержит полные данные сущности (формат совпадает с типами публичного API).

interface FullTrackerPluginContextValue<TSlot extends keyof SlotContextMap = keyof SlotContextMap> {
  theme: Theme;
  language: string;
  /** Имя слота, в котором открыт плагин */
  slot: TSlot;
  /** Полный контекст слота (зависит от типа слота) */
  slotContext: SlotContextMap[TSlot];
}

Properties (общие для обоих типов)

Свойство

Тип

Описание

Theme ('light' | 'light-hc'
  | 'dark' | 'dark-hc' | 'system')

string

TSlot (ключ из SlotContextMap)

{ entityId: string;
  entityMeta?: Record<string, string> }

при level: 'basic',
SlotContextMap[TSlot] при level: 'full'

Example (basic)

const { theme, language, slotContext } = useTrackerPluginContext<'issue.action'>('basic');
const isDark = theme === 'dark' || theme === 'dark-hc';
console.log(slotContext.entityId); // 'abc123'
console.log(slotContext.entityMeta); // { issueId: 'QUEUE-123' } — для комментария

Example (full)

// В manifest.json для слота: contextLevel: "full"
const { slotContext } = useTrackerPluginContext<'issue.action'>('full');
console.log(slotContext.key); // 'QUEUE-123'
console.log(slotContext.version); // 42

Публичное API

Пакет @weavix/sdk-react реэкспортирует hostApi, trackerApi, storageApi и типы из @weavix/sdk-core.

  • hostApi — работа с хостом: инициализация, тема, язык, контекст слота, размер окна, notifyReady(). Подробнее в API Reference core.
  • trackerApi — вызовы Tracker Public API через типизированное API v3: trackerApi.v3.get, trackerApi.v3.post, trackerApi.v3.put, trackerApi.v3.patch, trackerApi.v3.delete. Ключи — пути эндпоинтов с автоподсказкой и JSDoc из @weavix/tracker-api-types. Описание методов и форматов: Common format.
  • storageApi — JSON-хранилище плагина уровня организации. Подробнее: Хранилище данных.

Пример

import { trackerApi } from '@weavix/sdk-react';

const issue = await trackerApi.v3.get['/issues/{id}']({
  pathParams: { id: 'KEY-1' },
  queryParams: { expand: ['COMMENTS'] },
});

Тема, язык и контекст слота доступны через useTrackerPluginContext. Инициализация и уведомление хоста — через hostApi или внутри TrackerPluginProvider. Вызовы эндпоинтов Tracker — через trackerApi.v3.

Полная документация по API (типы, коды ошибок, утилиты):

API Reference — @weavix/sdk-core

Утилиты

getLocalizedString

Получает локализованную строку на основе языка. Полезно для локализации вне React-компонентов или когда нужен прямой контроль над языком.

Type Signature

function getLocalizedString(
  value: LocalizedString,
  language: string,
  fallbackLanguage?: string,
): string;

Parameters

  • value - LocalizedString - локализованная строка (может быть строкой или объектом с переводами)
  • language - string - код языка ('ru' или 'en')
  • fallbackLanguage - string (опционально, по умолчанию 'en') - резервный язык, если основной не найден

Returns

string - локализованная строка на указанном языке.

Example (базовое использование)

import { getLocalizedString } from '@weavix/sdk-react';
import type { LocalizedString } from '@weavix/sdk-react';

function getFieldName(name: LocalizedString, language: string): string {
  return getLocalizedString(name, language);
}
// language можно получить из useTrackerPluginContext() в компоненте

const name = { ru: 'Название', en: 'Summary' };
const localizedName = getFieldName(name, 'ru');
console.log(localizedName); // 'Название'

Example (с резервным языком)

import { getLocalizedString } from '@weavix/sdk-react';

// Если перевод на русский отсутствует, используется английский
const partial = { en: 'Name' };
const name = getLocalizedString(partial, 'ru', 'en');
console.log(name); // 'Name'

// Если передана простая строка, она возвращается как есть
const simple = 'Simple string';
const result = getLocalizedString(simple, 'ru');
console.log(result); // 'Simple string'

Example (в обработчике событий)

import {
  getLocalizedString,
  useTrackerPluginContext,
} from '@weavix/sdk-react';
import type { LocalizedString } from '@weavix/sdk-react';

type FieldWithName = { id: string; name: LocalizedString };

function FieldSelector({ fields }: { fields: FieldWithName[] }) {
  const { language } = useTrackerPluginContext();
  const handleFieldSelect = (field: FieldWithName) => {
    const localizedName = getLocalizedString(field.name, language);
    alert(`Выбрано поле: ${localizedName}`);
  };

  return (
    <ul>
      {fields.map((field) => (
        <li key={field.id} onClick={() => handleFieldSelect(field)}>
          {field.id}
        </li>
      ))}
    </ul>
  );
}

Примечание

В React-компонентах предпочтительнее использовать хук useLocalizedString, который автоматически получает язык из контекста:

import { useLocalizedString } from '@weavix/sdk-react';

function MyComponent() {
  const localize = useLocalizedString();

  const field = { name: { ru: 'Название', en: 'Title' } };
  return <div>{localize(field.name)}</div>;
}
Предыдущая