API Reference - @weavix/sdk-react

Components

TrackerPluginProvider

A provider for initializing the Tracker plugin. Wraps the application and manages the plugin's lifecycle. Provides the theme, language, and slot context via React context.

Props: TrackerPluginProviderProps

Features

  • Automatic plugin initialization
  • Loading and error state management
  • Provides context via the React Context API
  • Automatically notifies the host when the plugin is ready
  • Protection from double initialization in React StrictMode

Example (basic usage)

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 (with custom options)

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 (disabling automatic notification)

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

function App() {
  useEffect(() => {
    // Perform additional initialization, then notify the host
    initializeApp().then(() => {
      hostApi.notifyReady()
    });
  }, []);

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

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

Hooks

useTrackerPluginContext

A hook for getting the theme, language, and slot context from TrackerPluginProvider. Supports several overloads depending on level and the generic parameter TSlot.

Type Signature

// level: 'basic' — basic context (entityId and entityMeta only), the slotContext type is narrowed by checking slot
function useTrackerPluginContext(level: 'basic'): {
    [K in keyof SlotContextMap]: BasicTrackerPluginContextValue<K>;
}[keyof SlotContextMap];

// level: 'full' — full context with live entity data
function useTrackerPluginContext(level: 'full'): {
    [K in keyof SlotContextMap]: FullTrackerPluginContextValue<K>;
}[keyof SlotContextMap];

// With generic TSlot and level: 'basic' — typed basic context for a specific slot
function useTrackerPluginContext<TSlot extends keyof SlotContextMap>(
    level: 'basic',
): BasicTrackerPluginContextValue<TSlot>;

// With generic TSlot and level: 'full' — typed full context for a specific slot
function useTrackerPluginContext<TSlot extends keyof SlotContextMap>(
    level: 'full',
): FullTrackerPluginContextValue<TSlot>;

Parameters

  • level'basic' | 'full' (required) — the slot context level. Must match the contextLevel value specified for the slot in manifest.json. For more details, see Slot context levels.

Type Parameters

  • TSlot — the slot type (optional). With the generic — slotContext is typed for this slot. Without the generic — you can narrow it with slot === 'issue.action', and so on.

Returns

BasicTrackerPluginContextValue<TSlot> or FullTrackerPluginContextValue<TSlot> depending on level, or a union across all slots.

Throws

Example (basic context)

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

function MyComponent() {
  const { theme, language, slotContext } = useTrackerPluginContext('basic');
  // slotContext.entityId — identifier of the current entity
  // slotContext.entityMeta — additional basic metadata (optional)

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

Example (basic — slot is known)

const { slotContext } = useTrackerPluginContext<'issue.action'>('basic');
slotContext.entityId; // issue identifier
slotContext.entityMeta; // additional metadata

Example (multiple slots — narrowing by slot)

const { slot, slotContext } = useTrackerPluginContext('basic');
if (slot === 'issue.action') {
  slotContext.entityId; // here slotContext is typed for the issue.action slot
}

Example (full context with slot typing)

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

function IssuePlugin() {
  // In manifest.json for the slot: 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

A hook for getting a localized string based on the current language from the TrackerPluginProvider context.

Type Signature

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

Parameters

  • fallbackLanguage - string (optional, defaults to 'en') - the fallback language if the main one isn't found

Returns

A function for localizing strings, (value: LocalizedString) => string.

Example (basic usage)

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 (with a fallback language)

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

function MyComponent() {
  // If no translation is found for the current language, Russian is used
  const localize = useLocalizedString('ru');

  const name = { en: 'Name' }; // no Russian translation

  return <div>{localize(name)}</div>; // returns 'Name'
}

Example (working with issue fields)

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

A hook for showing toast notifications in the host application. Returns an object with an add method.

Permission

The tracker:ui:toaster permission must be requested in manifest.json:

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

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

  const handleSave = async () => {
    await saveData();
    toaster.add({
      title: 'Saved',
      theme: 'success',
    });
  };

  const handleDelete = async () => {
    await deleteItem(id);
    toaster.add({
      title: 'Deleted',
      theme: 'info',
      content: 'QUEUE-123',
      actions: [
        {
          label: 'Undo',
          onClick: () => restoreItem(id),
        },
      ],
    });
  };

  return (
    <div>
      <button onClick={handleSave}>Save</button>
      <button onClick={handleDelete}>Delete</button>
    </div>
  );
}

The full list of add(options) parameters is in core.

useConfirm

A plugin can show a modal confirmation dialog. The dialog is rendered on the Tracker side, not inside the iframe, so it overlays the entire application and focuses the user on making a decision.

Permission

The tracker:ui:confirm permission must be requested in manifest.json:

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

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

    const handleClick = async () => {
        const { confirmed } = await confirm.show({
            title: 'Delete',
            message: 'Are you sure you want to delete this? This action cannot be undone.',
            textButtonApply: 'Delete',
            textButtonCancel: 'Cancel',
            theme: 'danger',
        });

        if (confirmed) {
            // perform the action
        }
    };

    return <button onClick={handleClick}>Delete</button>;
}

The full list of parameters is in core.

Types

TrackerPluginProviderProps

Props of the TrackerPluginProvider component.

interface TrackerPluginProviderProps {
  /** Child elements */
  children: ReactNode;

  /**
   * Automatically resize the plugin container when its content changes
   * @default true
   */
  autoResize?: boolean;

  /**
   * Component to display during initialization
   * @default <PluginLoader />
   */
  fallback?: ReactNode;

  /**
   * Component to display on an initialization error
   * @default <PluginError error={error} />
   */
  errorFallback?: (error: Error) => ReactNode;

  /**
   * Automatically notify the host that the plugin is ready after initialization
   * @default true
   */
  autoNotifyReady?: boolean;
}

Properties

Property

Type

Required

Default

Description

children

ReactNode

Yes

Child components rendered after successful initialization

autoResize

boolean

No

true

Automatically resize the plugin container when its content changes. Enables DOM change tracking and automatically sends the new height to the host

fallback

ReactNode

No

The built-in <PluginLoader /> component

Component shown while the plugin is initializing

errorFallback

(error: Error) =>
  ReactNode

No

The built-in component

<PluginError
error={error} />

A function that returns a component to show on an initialization error

autoNotifyReady

boolean

No

true

Automatically notify the host that the plugin is ready after initialization

Usage examples for the properties are in the Components section above.

Elements with relative height

If you use elements with relative height (vh, %, and so on), automatic resizing (autoResize) may behave unexpectedly.
If you still want to use components with relative height, disable automatic resizing.

TrackerPluginContextValue

The context value provided by TrackerPluginProvider. The slotContext type depends on the requested context level (level).

BasicTrackerPluginContextValue

Returned when level: 'basic'. slotContext contains only the entity identifier and basic metadata.

interface BasicTrackerPluginContextValue<TSlot extends keyof SlotContextMap = keyof SlotContextMap> {
  theme: Theme;
  language: string;
  /** Name of the slot the plugin is opened in */
  slot: TSlot;
  /** Basic slot context */
  slotContext: {
    /** Identifier of the current entity */
    entityId: string;
    /** Additional basic information.
     *  For example, for a comment, it contains the parent issue's identifier. */
    entityMeta?: Record<string, string>;
  };
}

FullTrackerPluginContextValue

Returned when level: 'full'. slotContext contains the full entity data (the format matches the public API types).

interface FullTrackerPluginContextValue<TSlot extends keyof SlotContextMap = keyof SlotContextMap> {
  theme: Theme;
  language: string;
  /** Name of the slot the plugin is opened in */
  slot: TSlot;
  /** Full slot context (depends on the slot type) */
  slotContext: SlotContextMap[TSlot];
}

Properties (common to both types)

Property

Type

Description

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

string

TSlot (a key from SlotContextMap)

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

at level: 'basic',
SlotContextMap[TSlot] at 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' } — for a comment

Example (full)

// In manifest.json for the slot: contextLevel: "full"
const { slotContext } = useTrackerPluginContext<'issue.action'>('full');
console.log(slotContext.key); // 'QUEUE-123'
console.log(slotContext.version); // 42

Public API

The @weavix/sdk-react package re-exports hostApi, trackerApi, storageApi, and types from @weavix/sdk-core.

  • hostApi — interacting with the host: initialization, theme, language, slot context, window size, notifyReady(). For more details, see API Reference core.
  • trackerApi — calls to the Tracker Public API through the typed v3 API: trackerApi.v3.get, trackerApi.v3.post, trackerApi.v3.put, trackerApi.v3.patch, trackerApi.v3.delete. The keys are endpoint paths with autocomplete and JSDoc from @weavix/tracker-api-types. Description of methods and formats: Common format.
  • storageApi — the plugin's organization-level JSON storage. For more details, see Data storage.

Example

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

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

The theme, language, and slot context are available through useTrackerPluginContext. Initialization and notifying the host are done through hostApi, or inside TrackerPluginProvider. Tracker endpoint calls are made through trackerApi.v3.

Full API documentation (types, error codes, utilities):

API Reference — @weavix/sdk-core

Utilities

getLocalizedString

Gets a localized string based on the language. Useful for localization outside React components, or when you need direct control over the language.

Type Signature

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

Parameters

  • value - LocalizedString - the localized string (can be a string or an object with translations)
  • language - string - the language code ('ru' or 'en')
  • fallbackLanguage - string (optional, defaults to 'en') - the fallback language if the main one isn't found

Returns

string - the localized string in the specified language.

Example (basic usage)

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 can be obtained from useTrackerPluginContext() in the component

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

Example (with a fallback language)

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

// If the Russian translation is missing, English is used
const partial = { en: 'Name' };
const name = getLocalizedString(partial, 'ru', 'en');
console.log(name); // 'Name'

// If a plain string is passed, it's returned as is
const simple = 'Simple string';
const result = getLocalizedString(simple, 'ru');
console.log(result); // 'Simple string'

Example (in an event handler)

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(`Selected field: ${localizedName}`);
  };

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

Note

In React components, it's preferable to use the useLocalizedString hook, which automatically gets the language from the context:

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

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

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