@weavix/tracker-plugin-sdk-react 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +31 -0
- package/API_REFERENCE.md +649 -0
- package/README.md +201 -0
- package/dist/index.mjs +669 -0
- package/dist/index.mjs.map +1 -0
- package/dist/tracker-react-external/src/__tests__/setup.d.ts +1 -0
- package/dist/tracker-react-external/src/__tests__/setup.d.ts.map +1 -0
- package/dist/tracker-react-external/src/components/TrackerPluginProvider.d.ts +91 -0
- package/dist/tracker-react-external/src/components/TrackerPluginProvider.d.ts.map +1 -0
- package/dist/tracker-react-external/src/index.d.ts +9 -0
- package/dist/tracker-react-external/src/index.d.ts.map +1 -0
- package/package.json +44 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# @weavix/tracker-plugin-sdk-react — agents
|
|
2
|
+
|
|
3
|
+
**Пакет:** React (Weavix / npm) + реэкспорт core.
|
|
4
|
+
|
|
5
|
+
## Импорты
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import {
|
|
9
|
+
TrackerPluginProvider,
|
|
10
|
+
useTrackerPluginContext,
|
|
11
|
+
useToaster,
|
|
12
|
+
useConfirm,
|
|
13
|
+
hostApi,
|
|
14
|
+
trackerApi,
|
|
15
|
+
} from '@weavix/tracker-plugin-sdk-react';
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Правила
|
|
19
|
+
|
|
20
|
+
- **contextLevel** `basic` / `full` — см. [COOKBOOK](../../docs/agent/COOKBOOK.md).
|
|
21
|
+
- **hostApi** + **trackerApi.v3** — см. [core AGENTS](../tracker-plugin-external/AGENTS.md).
|
|
22
|
+
|
|
23
|
+
## Документация
|
|
24
|
+
|
|
25
|
+
| Файл | Назначение |
|
|
26
|
+
|------|------------|
|
|
27
|
+
| [../../AGENTS.md](../../AGENTS.md) | Общий вход |
|
|
28
|
+
| [../../docs/agent/COOKBOOK.md](../../docs/agent/COOKBOOK.md) | Рецепты |
|
|
29
|
+
| [README.md](./README.md) | Быстрый старт |
|
|
30
|
+
| [API_REFERENCE.md](./API_REFERENCE.md) | Provider, хуки |
|
|
31
|
+
| [../tracker-plugin-external/API_REFERENCE.md](../tracker-plugin-external/API_REFERENCE.md) | hostApi, uiApi, v3 |
|
package/API_REFERENCE.md
ADDED
|
@@ -0,0 +1,649 @@
|
|
|
1
|
+
# API Reference - @weavix/tracker-plugin-sdk-react
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
|
|
5
|
+
- [Components](#components)
|
|
6
|
+
- [TrackerPluginProvider](#trackerpluginprovider)
|
|
7
|
+
- [Hooks](#hooks)
|
|
8
|
+
- [useTrackerPluginContext](#usetrackerplugincontext)
|
|
9
|
+
- [useLocalizedString](#uselocalizedstring)
|
|
10
|
+
- [Types](#types)
|
|
11
|
+
- [TrackerPluginProviderProps](#trackerpluginproviderprops)
|
|
12
|
+
- [TrackerPluginContextValue](#trackerplugincontextvalue)
|
|
13
|
+
- [BasicTrackerPluginContextValue](#basictrackerplugincontextvalue)
|
|
14
|
+
- [FullTrackerPluginContextValue](#fulltrackerplugincontextvalue)
|
|
15
|
+
- [Публичное API](#публичное-api) — hostApi, trackerApi (реэкспорт из core)
|
|
16
|
+
- [Утилиты](#утилиты)
|
|
17
|
+
- [getLocalizedString](#getlocalizedstring)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Components
|
|
22
|
+
|
|
23
|
+
### TrackerPluginProvider
|
|
24
|
+
|
|
25
|
+
Провайдер для инициализации плагина Tracker. Оборачивает приложение и управляет жизненным циклом плагина. Предоставляет тему, язык и контекст слота через контекст React.
|
|
26
|
+
|
|
27
|
+
**Props:** [`TrackerPluginProviderProps`](#trackerpluginproviderprops)
|
|
28
|
+
|
|
29
|
+
**Features:**
|
|
30
|
+
|
|
31
|
+
- Автоматическая инициализация плагина
|
|
32
|
+
- Управление состояниями загрузки и ошибок
|
|
33
|
+
- Предоставление контекста через React Context API
|
|
34
|
+
- Автоматическое уведомление хоста о готовности плагина
|
|
35
|
+
- Защита от двойной инициализации в React StrictMode
|
|
36
|
+
|
|
37
|
+
**Example (базовое использование):**
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import { TrackerPluginProvider } from '@weavix/tracker-plugin-sdk-react';
|
|
41
|
+
import { createRoot } from 'react-dom/client';
|
|
42
|
+
import { App } from './App';
|
|
43
|
+
|
|
44
|
+
const root = createRoot(document.getElementById('root')!);
|
|
45
|
+
|
|
46
|
+
root.render(
|
|
47
|
+
<TrackerPluginProvider>
|
|
48
|
+
<App />
|
|
49
|
+
</TrackerPluginProvider>,
|
|
50
|
+
);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Example (с кастомными опциями):**
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
import { TrackerPluginProvider } from '@weavix/tracker-plugin-sdk-react';
|
|
57
|
+
import { Loader } from './components/Loader';
|
|
58
|
+
import { ErrorScreen } from './components/ErrorScreen';
|
|
59
|
+
|
|
60
|
+
root.render(
|
|
61
|
+
<TrackerPluginProvider
|
|
62
|
+
autoResize={false}
|
|
63
|
+
fallback={<Loader />}
|
|
64
|
+
errorFallback={(error) => <ErrorScreen error={error} />}
|
|
65
|
+
autoNotifyReady={false}
|
|
66
|
+
>
|
|
67
|
+
<App />
|
|
68
|
+
</TrackerPluginProvider>,
|
|
69
|
+
);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Example (отключение автоматического уведомления):**
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
import { TrackerPluginProvider, hostApi } from '@weavix/tracker-plugin-sdk-react';
|
|
76
|
+
|
|
77
|
+
function App() {
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
// Выполняем дополнительную инициализацию, затем уведомляем хост
|
|
80
|
+
initializeApp().then(() => {
|
|
81
|
+
hostApi.notifyReady()
|
|
82
|
+
});
|
|
83
|
+
}, []);
|
|
84
|
+
|
|
85
|
+
return <div>My Plugin</div>;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
root.render(
|
|
89
|
+
<TrackerPluginProvider autoNotifyReady={false}>
|
|
90
|
+
<App />
|
|
91
|
+
</TrackerPluginProvider>,
|
|
92
|
+
);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Hooks
|
|
98
|
+
|
|
99
|
+
### useTrackerPluginContext
|
|
100
|
+
|
|
101
|
+
Хук для получения темы, языка и контекста слота из [`TrackerPluginProvider`](#trackerpluginprovider).
|
|
102
|
+
|
|
103
|
+
Поддерживает два уровня контекста, управляемых полем `contextLevel` в манифесте плагина:
|
|
104
|
+
|
|
105
|
+
- **`'basic'`** (по умолчанию) — `slotContext` содержит только `{ entityId, entityMeta? }`. Данные берутся из параметров iframe без postMessage-запроса к хосту.
|
|
106
|
+
- **`'full'`** — `slotContext` содержит полный объект слота (Issue и т.д.). Требует `contextLevel: "full"` в манифесте.
|
|
107
|
+
|
|
108
|
+
**Type Signature:**
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
// Без аргумента или с 'basic' — slotContext: BasicContext | undefined
|
|
112
|
+
function useTrackerPluginContext(): BasicTrackerPluginContextValue;
|
|
113
|
+
function useTrackerPluginContext(level: 'basic'): BasicTrackerPluginContextValue;
|
|
114
|
+
|
|
115
|
+
// С 'full' — slotContext: SlotContextMap[TSlot] | undefined
|
|
116
|
+
function useTrackerPluginContext(level: 'full'): FullTrackerPluginContextValue;
|
|
117
|
+
|
|
118
|
+
// С generic — типизированный контекст для конкретного слота
|
|
119
|
+
function useTrackerPluginContext<TSlot extends keyof SlotContextMap>(level?: 'basic'): BasicTrackerPluginContextValue<TSlot>;
|
|
120
|
+
function useTrackerPluginContext<TSlot extends keyof SlotContextMap>(level: 'full'): FullTrackerPluginContextValue<TSlot>;
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Parameters:**
|
|
124
|
+
|
|
125
|
+
- `level` — `'basic' | 'full'` (опционально, по умолчанию `'basic'`). Уровень запрашиваемого контекста.
|
|
126
|
+
|
|
127
|
+
**Type Parameters:**
|
|
128
|
+
|
|
129
|
+
- `TSlot` — тип слота (опционально). С generic — `slotContext` типизирован под этот слот.
|
|
130
|
+
|
|
131
|
+
**Returns:** [`BasicTrackerPluginContextValue`](#basictrackerplugincontextvalue) или [`FullTrackerPluginContextValue`](#fulltrackerplugincontextvalue)
|
|
132
|
+
|
|
133
|
+
**Throws:**
|
|
134
|
+
|
|
135
|
+
- `Error` — если используется вне [`TrackerPluginProvider`](#trackerpluginprovider)
|
|
136
|
+
- `Error` — если код запрашивает `'full'` контекст, но манифест объявляет `'basic'` (runtime security guard)
|
|
137
|
+
|
|
138
|
+
**Example (базовый контекст — только entityId и entityMeta):**
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
import { useTrackerPluginContext } from '@weavix/tracker-plugin-sdk-react';
|
|
142
|
+
|
|
143
|
+
function MyPlugin() {
|
|
144
|
+
// По умолчанию — basic контекст
|
|
145
|
+
const { slotContext } = useTrackerPluginContext();
|
|
146
|
+
// slotContext: { entityId: string; entityMeta?: Record<string, string> } | undefined
|
|
147
|
+
|
|
148
|
+
return <div>Entity: {slotContext?.entityId}</div>;
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Example (полный контекст — требует contextLevel: "full" в манифесте):**
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
import { useTrackerPluginContext } from '@weavix/tracker-plugin-sdk-react';
|
|
156
|
+
|
|
157
|
+
function IssuePlugin() {
|
|
158
|
+
const { theme, language, slotContext } = useTrackerPluginContext('full');
|
|
159
|
+
// slotContext: Issue | undefined (для слота issue.action)
|
|
160
|
+
|
|
161
|
+
return (
|
|
162
|
+
<div>
|
|
163
|
+
<h1>Issue: {slotContext?.key}</h1>
|
|
164
|
+
<p>Version: {slotContext?.version}</p>
|
|
165
|
+
<p>Theme: {theme}</p>
|
|
166
|
+
</div>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**Example (полный контекст с типизацией слота):**
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
const { slotContext } = useTrackerPluginContext<'issue.action'>('full');
|
|
175
|
+
slotContext?.key; // тип контекста — Issue (из @weavix/tracker-core)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**Example (несколько слотов — сужение по slot):**
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
const { slot, slotContext } = useTrackerPluginContext('full');
|
|
182
|
+
if (slot === 'issue.action') {
|
|
183
|
+
slotContext?.key; // здесь slotContext типизирован под слот issue.action
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
### useLocalizedString
|
|
190
|
+
|
|
191
|
+
Хук для получения локализованной строки на основе текущего языка из контекста [`TrackerPluginProvider`](#trackerpluginprovider).
|
|
192
|
+
|
|
193
|
+
**Type Signature:**
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
function useLocalizedString(fallbackLanguage?: string): (value: LocalizedString) => string;
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
**Parameters:**
|
|
200
|
+
|
|
201
|
+
- `fallbackLanguage` - `string` (опционально, по умолчанию 'en') - резервный язык, если основной не найден
|
|
202
|
+
|
|
203
|
+
**Returns:** Функция для локализации строк `(value: LocalizedString) => string`
|
|
204
|
+
|
|
205
|
+
**Example (базовое использование):**
|
|
206
|
+
|
|
207
|
+
```tsx
|
|
208
|
+
import { useLocalizedString } from '@weavix/tracker-plugin-sdk-react';
|
|
209
|
+
|
|
210
|
+
function MyComponent() {
|
|
211
|
+
const localize = useLocalizedString();
|
|
212
|
+
|
|
213
|
+
const field = {
|
|
214
|
+
name: { ru: 'Имя', en: 'Name' },
|
|
215
|
+
description: { ru: 'Описание', en: 'Description' },
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
return (
|
|
219
|
+
<div>
|
|
220
|
+
<h1>{localize(field.name)}</h1>
|
|
221
|
+
<p>{localize(field.description)}</p>
|
|
222
|
+
</div>
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**Example (с резервным языком):**
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
import { useLocalizedString } from '@weavix/tracker-plugin-sdk-react';
|
|
231
|
+
|
|
232
|
+
function MyComponent() {
|
|
233
|
+
// Если перевод на текущем языке не найден, используется русский
|
|
234
|
+
const localize = useLocalizedString('ru');
|
|
235
|
+
|
|
236
|
+
const name = { en: 'Name' }; // нет русского перевода
|
|
237
|
+
|
|
238
|
+
return <div>{localize(name)}</div>; // вернет 'Name'
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
**Example (работа с полями задачи):**
|
|
243
|
+
|
|
244
|
+
```tsx
|
|
245
|
+
import {
|
|
246
|
+
useLocalizedString,
|
|
247
|
+
useTrackerPluginContext,
|
|
248
|
+
} from '@weavix/tracker-plugin-sdk-react';
|
|
249
|
+
import { trackerApi } from '@weavix/tracker-plugin-sdk-react';
|
|
250
|
+
|
|
251
|
+
function FieldsList() {
|
|
252
|
+
const localize = useLocalizedString();
|
|
253
|
+
const { slotContext } = useTrackerPluginContext<'issue.action'>();
|
|
254
|
+
const [fields, setFields] = useState([]);
|
|
255
|
+
|
|
256
|
+
useEffect(() => {
|
|
257
|
+
trackerApi.v3.get['/fields/...']({ ... }).then(setFields);
|
|
258
|
+
}, []);
|
|
259
|
+
|
|
260
|
+
return (
|
|
261
|
+
<ul>
|
|
262
|
+
{fields.map((field) => (
|
|
263
|
+
<li key={field.id}>
|
|
264
|
+
<strong>{localize(field.name)}</strong>
|
|
265
|
+
{field.description && <p>{localize(field.description)}</p>}
|
|
266
|
+
</li>
|
|
267
|
+
))}
|
|
268
|
+
</ul>
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Types
|
|
276
|
+
|
|
277
|
+
### TrackerPluginProviderProps
|
|
278
|
+
|
|
279
|
+
Свойства компонента [`TrackerPluginProvider`](#trackerpluginprovider).
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
interface TrackerPluginProviderProps {
|
|
283
|
+
/** Дочерние элементы */
|
|
284
|
+
children: ReactNode;
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Автоматически изменять размер контейнера плагина при изменении содержимого
|
|
288
|
+
* @default true
|
|
289
|
+
*/
|
|
290
|
+
autoResize?: boolean;
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Компонент для отображения во время инициализации
|
|
294
|
+
* @default <PluginLoader />
|
|
295
|
+
*/
|
|
296
|
+
fallback?: ReactNode;
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Компонент для отображения при ошибке инициализации
|
|
300
|
+
* @default <PluginError error={error} />
|
|
301
|
+
*/
|
|
302
|
+
errorFallback?: (error: Error) => ReactNode;
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Автоматически уведомить хост о готовности плагина после инициализации
|
|
306
|
+
* @default true
|
|
307
|
+
*/
|
|
308
|
+
autoNotifyReady?: boolean;
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
**Properties:**
|
|
313
|
+
|
|
314
|
+
#### `children`
|
|
315
|
+
|
|
316
|
+
- **Type:** `ReactNode`
|
|
317
|
+
- **Required:** Yes
|
|
318
|
+
- **Description:** Дочерние компоненты, которые будут отрендерены после успешной инициализации
|
|
319
|
+
|
|
320
|
+
#### `autoResize`
|
|
321
|
+
|
|
322
|
+
- **Type:** `boolean`
|
|
323
|
+
- **Required:** No
|
|
324
|
+
- **Description:** Автоматически изменять размер контейнера плагина при изменении содержимого. Включает отслеживание изменений DOM и автоматическую отправку новой высоты хосту.
|
|
325
|
+
- **Default:** `true`
|
|
326
|
+
|
|
327
|
+
**Example:**
|
|
328
|
+
|
|
329
|
+
```tsx
|
|
330
|
+
<TrackerPluginProvider autoResize={false}>
|
|
331
|
+
<App />
|
|
332
|
+
</TrackerPluginProvider>
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
**Note:** Отключайте autoResize, если вы управляете размером контейнера вручную (через доступный в конфигурации API).
|
|
336
|
+
|
|
337
|
+
#### `fallback`
|
|
338
|
+
|
|
339
|
+
- **Type:** `ReactNode`
|
|
340
|
+
- **Required:** No
|
|
341
|
+
- **Description:** Компонент, отображаемый во время инициализации плагина
|
|
342
|
+
- **Default:** Встроенный компонент `<PluginLoader />`
|
|
343
|
+
|
|
344
|
+
**Example:**
|
|
345
|
+
|
|
346
|
+
```tsx
|
|
347
|
+
<TrackerPluginProvider fallback={<div>Loading...</div>}>
|
|
348
|
+
<App />
|
|
349
|
+
</TrackerPluginProvider>
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
#### `errorFallback`
|
|
353
|
+
|
|
354
|
+
- **Type:** `(error: Error) => ReactNode`
|
|
355
|
+
- **Required:** No
|
|
356
|
+
- **Description:** Функция, возвращающая компонент для отображения при ошибке инициализации
|
|
357
|
+
- **Default:** Встроенный компонент `<PluginError error={error} />`
|
|
358
|
+
|
|
359
|
+
**Example:**
|
|
360
|
+
|
|
361
|
+
```tsx
|
|
362
|
+
<TrackerPluginProvider
|
|
363
|
+
errorFallback={(error) => (
|
|
364
|
+
<div>
|
|
365
|
+
<h1>Error!</h1>
|
|
366
|
+
<p>{error.message}</p>
|
|
367
|
+
</div>
|
|
368
|
+
)}
|
|
369
|
+
>
|
|
370
|
+
<App />
|
|
371
|
+
</TrackerPluginProvider>
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
#### `autoNotifyReady`
|
|
375
|
+
|
|
376
|
+
- **Type:** `boolean`
|
|
377
|
+
- **Required:** No
|
|
378
|
+
- **Description:** Автоматически уведомлять хост о готовности плагина после инициализации
|
|
379
|
+
- **Default:** `true`
|
|
380
|
+
|
|
381
|
+
**Example:**
|
|
382
|
+
|
|
383
|
+
```tsx
|
|
384
|
+
<TrackerPluginProvider autoNotifyReady={false}>
|
|
385
|
+
<App />
|
|
386
|
+
</TrackerPluginProvider>
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
### TrackerPluginContextValue
|
|
392
|
+
|
|
393
|
+
Union-тип: [`BasicTrackerPluginContextValue`](#basictrackerplugincontextvalue) | [`FullTrackerPluginContextValue`](#fulltrackerplugincontextvalue).
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
type TrackerPluginContextValue<TSlot extends keyof SlotContextMap = keyof SlotContextMap> =
|
|
397
|
+
| BasicTrackerPluginContextValue<TSlot>
|
|
398
|
+
| FullTrackerPluginContextValue<TSlot>;
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
### BasicTrackerPluginContextValue
|
|
404
|
+
|
|
405
|
+
Значение контекста при `contextLevel = 'basic'`. Возвращается хуком [`useTrackerPluginContext()`](#usetrackerplugincontext) или `useTrackerPluginContext('basic')`.
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
interface BasicTrackerPluginContextValue<TSlot extends keyof SlotContextMap = keyof SlotContextMap> {
|
|
409
|
+
theme: Theme | undefined;
|
|
410
|
+
language: string | undefined;
|
|
411
|
+
service: string;
|
|
412
|
+
userId?: string;
|
|
413
|
+
isYateam?: boolean;
|
|
414
|
+
origin: string;
|
|
415
|
+
/** Имя слота, в котором открыт плагин */
|
|
416
|
+
slot: TSlot;
|
|
417
|
+
innerUrl: string;
|
|
418
|
+
queryParams: Record<string, string>;
|
|
419
|
+
/** Контекст страницы — только entityId и entityMeta при basic уровне */
|
|
420
|
+
slotContext: BasicContext | undefined;
|
|
421
|
+
registerHandler: RegisterHandlerFunction<TSlot>;
|
|
422
|
+
/** Уровень контекста — всегда 'basic' */
|
|
423
|
+
contextLevel: 'basic';
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
#### `slotContext` (basic)
|
|
428
|
+
|
|
429
|
+
- **Type:** `BasicContext | undefined`
|
|
430
|
+
- **Description:** Содержит только `entityId` и опциональный `entityMeta`, переданные хостом в параметрах iframe. Доступен без postMessage-запроса.
|
|
431
|
+
|
|
432
|
+
```typescript
|
|
433
|
+
type BasicContext = {
|
|
434
|
+
entityId: string;
|
|
435
|
+
entityMeta?: Record<string, string>;
|
|
436
|
+
};
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
**Example:**
|
|
440
|
+
|
|
441
|
+
```tsx
|
|
442
|
+
const { slotContext } = useTrackerPluginContext(); // basic по умолчанию
|
|
443
|
+
console.log(slotContext?.entityId); // 'QUEUE-123'
|
|
444
|
+
console.log(slotContext?.entityMeta); // { key: 'QUEUE-123' } или undefined
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
449
|
+
### FullTrackerPluginContextValue
|
|
450
|
+
|
|
451
|
+
Значение контекста при `contextLevel = 'full'`. Возвращается хуком [`useTrackerPluginContext('full')`](#usetrackerplugincontext). Требует `contextLevel: "full"` в манифесте плагина.
|
|
452
|
+
|
|
453
|
+
```typescript
|
|
454
|
+
interface FullTrackerPluginContextValue<TSlot extends keyof SlotContextMap = keyof SlotContextMap> {
|
|
455
|
+
theme: Theme | undefined;
|
|
456
|
+
language: string | undefined;
|
|
457
|
+
service: string;
|
|
458
|
+
userId?: string;
|
|
459
|
+
isYateam?: boolean;
|
|
460
|
+
origin: string;
|
|
461
|
+
/** Имя слота, в котором открыт плагин */
|
|
462
|
+
slot: TSlot;
|
|
463
|
+
innerUrl: string;
|
|
464
|
+
queryParams: Record<string, string>;
|
|
465
|
+
/** Полный контекст слота (Issue, TriggerContext и т.д.) */
|
|
466
|
+
slotContext: SlotContextMap[TSlot] | undefined;
|
|
467
|
+
registerHandler: RegisterHandlerFunction<TSlot>;
|
|
468
|
+
/** Уровень контекста — всегда 'full' */
|
|
469
|
+
contextLevel: 'full';
|
|
470
|
+
}
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
#### `slotContext` (full)
|
|
474
|
+
|
|
475
|
+
- **Type:** `SlotContextMap[TSlot] | undefined`
|
|
476
|
+
- **Description:** Полный контекст слота, полученный через postMessage (`context.get`). Для `'issue.action'` — тип `Issue` из **`@weavix/tracker-core`**.
|
|
477
|
+
|
|
478
|
+
**Example:**
|
|
479
|
+
|
|
480
|
+
```tsx
|
|
481
|
+
const { slotContext } = useTrackerPluginContext<'issue.action'>('full');
|
|
482
|
+
console.log(slotContext?.key); // 'QUEUE-123'
|
|
483
|
+
console.log(slotContext?.version); // 42
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
#### `theme`
|
|
487
|
+
|
|
488
|
+
- **Type:** `Theme | undefined` (`'light' | 'light-hc' | 'dark' | 'dark-hc' | 'system'`)
|
|
489
|
+
- **Description:** Текущая тема оформления хоста
|
|
490
|
+
|
|
491
|
+
**Example:**
|
|
492
|
+
|
|
493
|
+
```tsx
|
|
494
|
+
const { theme } = useTrackerPluginContext();
|
|
495
|
+
const isDark = theme === 'dark' || theme === 'dark-hc';
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
#### `language`
|
|
499
|
+
|
|
500
|
+
- **Type:** `string | undefined`
|
|
501
|
+
- **Description:** Код текущего языка хоста (например, 'ru', 'en')
|
|
502
|
+
|
|
503
|
+
**Example:**
|
|
504
|
+
|
|
505
|
+
```tsx
|
|
506
|
+
const { language } = useTrackerPluginContext();
|
|
507
|
+
const greeting = language === 'ru' ? 'Привет' : 'Hello';
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
#### `slot`
|
|
511
|
+
|
|
512
|
+
- **Type:** `TSlot` (ключ из `SlotContextMap`)
|
|
513
|
+
- **Description:** Имя слота, в котором открыт плагин (например, `'issue.action'`, `'navigation'`)
|
|
514
|
+
|
|
515
|
+
#### `contextLevel`
|
|
516
|
+
|
|
517
|
+
- **Type:** `'basic' | 'full'`
|
|
518
|
+
- **Description:** Уровень контекста, объявленный в манифесте плагина. Определяет тип `slotContext`.
|
|
519
|
+
|
|
520
|
+
---
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
## Публичное API
|
|
524
|
+
|
|
525
|
+
Пакет `@weavix/tracker-plugin-sdk-react` реэкспортирует **hostApi**, **trackerApi** и типы из `@weavix/tracker-plugin-sdk`.
|
|
526
|
+
|
|
527
|
+
- **hostApi** — работа с хостом: инициализация, тема, язык, контекст слота, размер окна, `notifyReady()`. Подробнее в [API Reference tracker-core](../tracker-plugin-external/API_REFERENCE.md#hostapi-hostapi).
|
|
528
|
+
- **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](https://docs.yandex-team.ru/tracker/common-format).
|
|
529
|
+
|
|
530
|
+
**Пример:**
|
|
531
|
+
|
|
532
|
+
```ts
|
|
533
|
+
import { trackerApi } from '@weavix/tracker-plugin-sdk-react';
|
|
534
|
+
|
|
535
|
+
const issue = await trackerApi.v3.get['/issues/{id}']({
|
|
536
|
+
pathParams: { id: 'KEY-1' },
|
|
537
|
+
queryParams: { expand: ['COMMENTS'] },
|
|
538
|
+
});
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
Тема, язык и контекст слота доступны через [`useTrackerPluginContext`](#usetrackerplugincontext). Инициализация и уведомление хоста — через **hostApi** (или внутри `TrackerPluginProvider`). Вызовы эндпоинтов Tracker — через **trackerApi.v3**.
|
|
542
|
+
|
|
543
|
+
**Полная документация по API (типы, коды ошибок, утилиты):**
|
|
544
|
+
|
|
545
|
+
📖 [API Reference — @weavix/tracker-plugin-sdk](../tracker-plugin-external/API_REFERENCE.md)
|
|
546
|
+
|
|
547
|
+
---
|
|
548
|
+
|
|
549
|
+
## Утилиты
|
|
550
|
+
|
|
551
|
+
### getLocalizedString
|
|
552
|
+
|
|
553
|
+
Получает локализованную строку на основе языка. Полезно для локализации вне React-компонентов или когда нужен прямой контроль над языком.
|
|
554
|
+
|
|
555
|
+
**Type Signature:**
|
|
556
|
+
|
|
557
|
+
```typescript
|
|
558
|
+
function getLocalizedString(
|
|
559
|
+
value: LocalizedString,
|
|
560
|
+
language: string,
|
|
561
|
+
fallbackLanguage?: string,
|
|
562
|
+
): string;
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
**Parameters:**
|
|
566
|
+
|
|
567
|
+
- `value` - `LocalizedString` - локализованная строка (может быть строкой или объектом с переводами)
|
|
568
|
+
- `language` - `string` - код языка ('ru' или 'en')
|
|
569
|
+
- `fallbackLanguage` - `string` (опционально, по умолчанию 'en') - резервный язык, если основной не найден
|
|
570
|
+
|
|
571
|
+
**Returns:** `string` - локализованная строка на указанном языке
|
|
572
|
+
|
|
573
|
+
**Example (базовое использование):**
|
|
574
|
+
|
|
575
|
+
```tsx
|
|
576
|
+
import { getLocalizedString } from '@weavix/tracker-plugin-sdk-react';
|
|
577
|
+
import type { LocalizedString } from '@weavix/tracker-plugin-sdk-react';
|
|
578
|
+
|
|
579
|
+
function getFieldName(name: LocalizedString, language: string): string {
|
|
580
|
+
return getLocalizedString(name, language);
|
|
581
|
+
}
|
|
582
|
+
// language можно получить из useTrackerPluginContext() в компоненте
|
|
583
|
+
|
|
584
|
+
const name = { ru: 'Название', en: 'Summary' };
|
|
585
|
+
const localizedName = getFieldName(name, 'ru');
|
|
586
|
+
console.log(localizedName); // 'Название'
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
**Example (с резервным языком):**
|
|
590
|
+
|
|
591
|
+
```tsx
|
|
592
|
+
import { getLocalizedString } from '@weavix/tracker-plugin-sdk-react';
|
|
593
|
+
|
|
594
|
+
// Если перевод на русский отсутствует, используется английский
|
|
595
|
+
const partial = { en: 'Name' };
|
|
596
|
+
const name = getLocalizedString(partial, 'ru', 'en');
|
|
597
|
+
console.log(name); // 'Name'
|
|
598
|
+
|
|
599
|
+
// Если передана простая строка, она возвращается как есть
|
|
600
|
+
const simple = 'Simple string';
|
|
601
|
+
const result = getLocalizedString(simple, 'ru');
|
|
602
|
+
console.log(result); // 'Simple string'
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
**Example (в обработчике событий):**
|
|
606
|
+
|
|
607
|
+
```tsx
|
|
608
|
+
import {
|
|
609
|
+
getLocalizedString,
|
|
610
|
+
useTrackerPluginContext,
|
|
611
|
+
} from '@weavix/tracker-plugin-sdk-react';
|
|
612
|
+
import type { LocalizedString } from '@weavix/tracker-plugin-sdk-react';
|
|
613
|
+
|
|
614
|
+
type FieldWithName = { id: string; name: LocalizedString };
|
|
615
|
+
|
|
616
|
+
function FieldSelector({ fields }: { fields: FieldWithName[] }) {
|
|
617
|
+
const { language } = useTrackerPluginContext();
|
|
618
|
+
const handleFieldSelect = (field: FieldWithName) => {
|
|
619
|
+
const localizedName = getLocalizedString(field.name, language);
|
|
620
|
+
alert(`Выбрано поле: ${localizedName}`);
|
|
621
|
+
};
|
|
622
|
+
|
|
623
|
+
return (
|
|
624
|
+
<ul>
|
|
625
|
+
{fields.map((field) => (
|
|
626
|
+
<li key={field.id} onClick={() => handleFieldSelect(field)}>
|
|
627
|
+
{field.id}
|
|
628
|
+
</li>
|
|
629
|
+
))}
|
|
630
|
+
</ul>
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
**Примечание:** В React-компонентах предпочтительнее использовать хук [`useLocalizedString`](#uselocalizedstring), который автоматически получает язык из контекста:
|
|
636
|
+
|
|
637
|
+
```tsx
|
|
638
|
+
import { useLocalizedString } from '@weavix/tracker-plugin-sdk-react';
|
|
639
|
+
|
|
640
|
+
function MyComponent() {
|
|
641
|
+
const localize = useLocalizedString();
|
|
642
|
+
|
|
643
|
+
const field = { name: { ru: 'Название', en: 'Title' } };
|
|
644
|
+
return <div>{localize(field.name)}</div>;
|
|
645
|
+
}
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
---
|
|
649
|
+
|