@weavix/tracker-plugin-sdk-react 0.0.33 → 0.0.34

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.
Files changed (2) hide show
  1. package/README.md +325 -97
  2. package/package.json +6 -6
package/README.md CHANGED
@@ -2,200 +2,428 @@
2
2
 
3
3
  React SDK for Tracker plugins (Weavix / npm).
4
4
 
5
- Для удобства написания плагинов:
5
+ Provides `TrackerPluginProvider`, typed `useTrackerPluginContext`, hooks for theme, language, and UI operations. Re-exports `trackerApi`, `hostApi`, `storageApi`, and `uiApi` from [`@weavix/tracker-plugin-sdk`](https://www.npmjs.com/package/@weavix/tracker-plugin-sdk).
6
6
 
7
- Этот пакет предоставляет `TrackerPluginProvider`, хуки, а также реэкспортирует `trackerApi` и `hostApi` из core.
8
-
9
- > **Для агентов и AI:** [AGENTS.md](./AGENTS.md) → [COOKBOOK](../../docs/agent/COOKBOOK.md). Core API: [tracker-plugin-external](../tracker-plugin-external/README.md).
10
-
11
- ## Установка
7
+ ## Installation
12
8
 
13
9
  ```bash
14
10
  npm install @weavix/tracker-plugin-sdk-react
15
11
  ```
16
12
 
17
- ## Использование
18
-
19
- ### Инициализация плагина
13
+ Peer dependencies: `react >= 18.0.0`, `react-dom >= 18.0.0`.
20
14
 
21
- Оберните приложение в `TrackerPluginProvider` в корне. Компонент управляет инициализацией, состояниями загрузки и ошибок, а также уведомляет хост о готовности плагина.
15
+ ## Quick start
22
16
 
23
17
  ```tsx
24
- import { TrackerPluginProvider } from '@weavix/tracker-plugin-sdk-react';
25
18
  import { createRoot } from 'react-dom/client';
26
- import { App } from './App';
19
+ import { TrackerPluginProvider, useTrackerPluginContext } from '@weavix/tracker-plugin-sdk-react';
27
20
 
28
- const root = createRoot(document.getElementById('root')!);
21
+ function App() {
22
+ const { theme, language, slot, slotContext } = useTrackerPluginContext();
29
23
 
30
- root.render(
24
+ return (
25
+ <div data-theme={theme}>
26
+ Slot: {slot}, language: {language}, entityId: {slotContext?.entityId}
27
+ </div>
28
+ );
29
+ }
30
+
31
+ createRoot(document.getElementById('root')!).render(
31
32
  <TrackerPluginProvider>
32
33
  <App />
33
- </TrackerPluginProvider>,
34
+ </TrackerPluginProvider>
35
+ );
36
+ ```
37
+
38
+ ---
39
+
40
+ ## TrackerPluginProvider
41
+
42
+ Root plugin component. Initialises the bridge, fetches initial values (theme, language, context, userId, orgId), notifies the host that the plugin is ready, and provides context to all child components.
43
+
44
+ A typed wrapper over `PluginProvider` from `@weavix/sdk-react`: adds Tracker-typed `registerHandler` based on `SlotContextMap`.
45
+
46
+ ```tsx
47
+ import { TrackerPluginProvider, PluginLoader } from '@weavix/tracker-plugin-sdk-react';
48
+
49
+ root.render(
50
+ <TrackerPluginProvider
51
+ autoResize={true}
52
+ autoNotifyReady={true}
53
+ fallback={<PluginLoader />}
54
+ errorFallback={(error) => <div>Error: {error.message}</div>}
55
+ >
56
+ <App />
57
+ </TrackerPluginProvider>
58
+ );
59
+ ```
60
+
61
+ ### Props
62
+
63
+ | Prop | Type | Default | Description |
64
+ |------|------|---------|-------------|
65
+ | `autoResize` | `boolean` | `true` | Automatically resize the iframe height when content changes |
66
+ | `autoNotifyReady` | `boolean` | `true` | Send `plugin.ready` to the host after initialisation |
67
+ | `fallback` | `ReactNode` | `undefined` | What to show during initialisation |
68
+ | `errorFallback` | `(error: Error) => ReactNode` | `<PluginError />` | What to show on initialisation error |
69
+ | `children` | `ReactNode` | — | Plugin content |
70
+
71
+ **Behaviour:**
72
+ - Intercepts clicks on external links and calls `uiApi.navigate`.
73
+ - Protected against double-initialisation in React StrictMode.
74
+ - Wraps the application in an `ErrorBoundary`.
75
+
76
+ ### Manual `notifyReady`
77
+
78
+ ```tsx
79
+ import { TrackerPluginProvider, hostApi } from '@weavix/tracker-plugin-sdk-react';
80
+
81
+ function App() {
82
+ useEffect(() => {
83
+ initializeApp().then(() => {
84
+ hostApi.notifyReady();
85
+ });
86
+ }, []);
87
+
88
+ return <div>My Plugin</div>;
89
+ }
90
+
91
+ root.render(
92
+ <TrackerPluginProvider autoNotifyReady={false}>
93
+ <App />
94
+ </TrackerPluginProvider>
34
95
  );
35
96
  ```
36
97
 
37
- ### Получение темы, языка и контекста слота (basic)
98
+ ---
38
99
 
39
- По умолчанию в манифесте `contextLevel: "basic"` (или поле не задано) — в `slotContext` только `entityId` и опционально `entityMeta`.
100
+ ## useTrackerPluginContext(level?)
101
+
102
+ Main hook for accessing host data. Typed for Tracker — `slotContext` has type `SlotContextMap[TSlot]`. All values are reactive.
40
103
 
41
104
  ```tsx
42
105
  import { useTrackerPluginContext } from '@weavix/tracker-plugin-sdk-react';
43
106
 
44
- function MyComponent() {
107
+ function App() {
108
+ // basic (default) — slotContext: { entityId, entityMeta? }
45
109
  const { theme, language, slot, slotContext } = useTrackerPluginContext();
46
110
 
47
111
  return (
48
112
  <div className={theme}>
49
- <p>Язык: {language}</p>
50
- <p>Слот: {slot}</p>
51
- <p>Сущность: {slotContext?.entityId}</p>
113
+ <p>Language: {language}</p>
114
+ <p>Slot: {slot}</p>
115
+ <p>Entity: {slotContext?.entityId}</p>
52
116
  </div>
53
117
  );
54
118
  }
55
119
  ```
56
120
 
57
- ### Полный контекст слота (Issue)
121
+ ### Full slot context
58
122
 
59
- Требуется `"contextLevel": "full"` в манифесте плагина.
123
+ Requires `contextLevel: "full"` in the plugin manifest.
60
124
 
61
125
  ```tsx
62
126
  import { useTrackerPluginContext } from '@weavix/tracker-plugin-sdk-react';
63
127
 
64
128
  function IssuePlugin() {
65
129
  const { slotContext } = useTrackerPluginContext<'issue.action'>('full');
130
+ // slotContext: Issue | undefined
66
131
 
67
132
  return (
68
133
  <div>
69
- <h1>Задача: {slotContext?.key}</h1>
70
- <p>Версия: {slotContext?.version}</p>
134
+ <h1>Issue: {slotContext?.key}</h1>
135
+ <p>Status: {slotContext?.status?.key}</p>
136
+ <p>Version: {slotContext?.version}</p>
71
137
  </div>
72
138
  );
73
139
  }
74
140
  ```
75
141
 
76
- Тип `Issue` в контексте слота — из **`@weavix/tracker-core`** (реэкспорт из core). Типы ответов **`trackerApi.v3`** — из **`@weavix/tracker-api-types`**.
142
+ ### contextLevel in the manifest
77
143
 
78
- ### Локализация
144
+ | Manifest | `useTrackerPluginContext()` | `useTrackerPluginContext('full')` |
145
+ |----------|---------------------------|----------------------------------|
146
+ | `contextLevel: "basic"` (default) | `slotContext: BasicContext \| undefined` | **runtime error** |
147
+ | `contextLevel: "full"` | `slotContext: BasicContext \| undefined` | `slotContext: SlotContextMap[TSlot] \| undefined` |
79
148
 
80
- ```tsx
81
- import { useLocalizedString } from '@weavix/tracker-plugin-sdk-react';
149
+ ### Return value
82
150
 
83
- function MyComponent() {
84
- const localize = useLocalizedString();
151
+ **`BasicTrackerPluginContextValue<TSlot>`** (`level: 'basic'`):
85
152
 
86
- const field = {
87
- name: { ru: 'Название', en: 'Summary' },
88
- };
153
+ | Field | Type | Description |
154
+ |-------|------|-------------|
155
+ | `theme` | `Theme \| undefined` | Current theme (`'light'`, `'dark'`, `'light-hc'`, `'dark-hc'`, `'system'`) |
156
+ | `language` | `string \| undefined` | Current language (`'ru'`, `'en'`, ...) |
157
+ | `slot` | `TSlot` | Current slot name |
158
+ | `service` | `string` | Service identifier |
159
+ | `origin` | `string` | Host origin |
160
+ | `innerUrl` | `string` | Plugin URL |
161
+ | `queryParams` | `Record<string, string>` | Plugin query parameters |
162
+ | `userId` | `string \| undefined` | Current user ID |
163
+ | `orgId` | `string \| undefined` | Organisation ID |
164
+ | `isYateam` | `boolean \| undefined` | Yandex-Team environment flag |
165
+ | `isOrbita` | `boolean \| undefined` | Orbita flag |
166
+ | `contextLevel` | `'basic'` | Context level from the manifest |
167
+ | `slotContext` | `BasicContext \| undefined` | `{ entityId, entityMeta? }` |
168
+ | `registerHandler` | `RegisterHandlerFunction<TSlot>` | Register a Tracker-typed handler for host RPC |
169
+
170
+ **`FullTrackerPluginContextValue<TSlot>`** (`level: 'full'`): same fields, but `slotContext: SlotContextMap[TSlot] | undefined`.
171
+
172
+ ### registerHandler
89
173
 
90
- return <h1>{localize(field.name)}</h1>;
174
+ Registers a Tracker-typed handler for incoming host RPC requests.
175
+
176
+ ```tsx
177
+ function App() {
178
+ const { registerHandler } = useTrackerPluginContext<'issue.action'>();
179
+
180
+ useEffect(() => {
181
+ // For 'getData', the handler type is derived from GetDataResultMap[TSlot]
182
+ registerHandler('getData', () => ({
183
+ key: 'QUEUE-1',
184
+ summary: 'Data from plugin',
185
+ }));
186
+ }, [registerHandler]);
187
+
188
+ return <div>...</div>;
91
189
  }
92
190
  ```
93
191
 
94
- ### Кастомные состояния загрузки и ошибок
192
+ ---
193
+
194
+ ## Hooks
195
+
196
+ ### `useTheme()`
95
197
 
96
198
  ```tsx
97
- import { TrackerPluginProvider } from '@weavix/tracker-plugin-sdk-react';
199
+ import { useTheme } from '@weavix/tracker-plugin-sdk-react';
98
200
 
99
- root.render(
100
- <TrackerPluginProvider
101
- autoResize={false}
102
- fallback={<div>Загрузка...</div>}
103
- errorFallback={(error) => <div>Ошибка: {error.message}</div>}
104
- autoNotifyReady={false}
105
- >
106
- <App />
107
- </TrackerPluginProvider>,
108
- );
201
+ const theme = useTheme(); // 'light' | 'dark' | 'light-hc' | 'dark-hc' | 'system' | undefined
109
202
  ```
110
203
 
111
- ### Ручной вызов `notifyReady`
204
+ ### `useLanguage()`
112
205
 
113
206
  ```tsx
114
- import { TrackerPluginProvider, hostApi } from '@weavix/tracker-plugin-sdk-react';
115
- import { useEffect } from 'react';
207
+ import { useLanguage } from '@weavix/tracker-plugin-sdk-react';
116
208
 
117
- function App() {
118
- useEffect(() => {
119
- initializeApp().then(() => {
120
- hostApi.notifyReady();
209
+ const language = useLanguage(); // 'ru' | 'en' | ... | undefined
210
+ ```
211
+
212
+ ### `useToaster()`
213
+
214
+ Show toast notifications in the host application.
215
+
216
+ > **Permission:** Requires `"toaster"` in `permissions.ui` of the plugin manifest.
217
+
218
+ ```tsx
219
+ import { useToaster } from '@weavix/tracker-plugin-sdk-react';
220
+
221
+ function SaveButton() {
222
+ const toaster = useToaster();
223
+
224
+ const handleSave = async () => {
225
+ await save();
226
+ toaster.add({ title: 'Saved', theme: 'success' });
227
+ };
228
+
229
+ return <button onClick={handleSave}>Save</button>;
230
+ }
231
+ ```
232
+
233
+ Returns `{ add: (options: ToastOptions) => Promise<{ name: string }> }`.
234
+
235
+ **`ToastOptions`:**
236
+
237
+ | Parameter | Type | Default | Description |
238
+ |-----------|------|---------|-------------|
239
+ | `title` | `string` | — | Toast title (required, max 200 chars) |
240
+ | `name` | `string` | auto | Unique key for deduplication |
241
+ | `theme` | `'success' \| 'danger' \| 'warning' \| 'info'` | `'info'` | Theme |
242
+ | `content` | `string` | — | Body text (max 500 chars) |
243
+ | `autoHiding` | `number` | `5000` | Display time in ms (1000–30000) |
244
+ | `isClosable` | `boolean` | `true` | Show close button |
245
+ | `actions` | `ToastAction[]` | — | Action buttons (max 2): `{ label: string; onClick: () => void }` |
246
+
247
+ ### `useConfirm()`
248
+
249
+ Show a confirmation dialog.
250
+
251
+ > **Permission:** Requires `"confirm"` in `permissions.ui` of the plugin manifest.
252
+
253
+ ```tsx
254
+ import { useConfirm } from '@weavix/tracker-plugin-sdk-react';
255
+
256
+ function DeleteButton() {
257
+ const confirm = useConfirm();
258
+
259
+ const handleDelete = async () => {
260
+ const { confirmed } = await confirm.show({
261
+ title: 'Delete issue?',
262
+ message: 'This action cannot be undone.',
263
+ theme: 'danger',
121
264
  });
122
- }, []);
265
+ if (confirmed) {
266
+ await deleteItem();
267
+ }
268
+ };
123
269
 
124
- return <div>My Plugin</div>;
270
+ return <button onClick={handleDelete}>Delete</button>;
125
271
  }
272
+ ```
273
+
274
+ Returns `{ show: (options: ConfirmOptions) => Promise<ConfirmResult> }`.
275
+
276
+ **`ConfirmOptions`:**
277
+
278
+ | Parameter | Type | Default | Description |
279
+ |-----------|------|---------|-------------|
280
+ | `message` | `string` | — | Dialog body text (required) |
281
+ | `title` | `string` | — | Dialog title |
282
+ | `textButtonApply` | `string` | — | Confirm button label |
283
+ | `textButtonCancel` | `string` | — | Cancel button label |
284
+ | `theme` | `'normal' \| 'danger'` | `'normal'` | Confirm button theme |
285
+
286
+ ### `useLocalizedString(fallbackLanguage?)`
287
+
288
+ Returns a resolver function that resolves a `LocalizedString` based on the current host language.
289
+
290
+ ```tsx
291
+ import { useLocalizedString } from '@weavix/tracker-plugin-sdk-react';
292
+
293
+ function Label({ text }: { text: { ru: string; en: string } }) {
294
+ const t = useLocalizedString();
295
+ return <span>{t(text)}</span>;
296
+ }
297
+ ```
298
+
299
+ ### `useIsOrbita()`
300
+
301
+ ```tsx
302
+ import { useIsOrbita } from '@weavix/tracker-plugin-sdk-react';
303
+
304
+ const isOrbita = useIsOrbita(); // boolean | undefined
305
+ ```
306
+
307
+ ---
308
+
309
+ ## Components
310
+
311
+ ### `PluginLoader`
312
+
313
+ Built-in loading indicator to display during initialisation.
314
+
315
+ ```tsx
316
+ import { TrackerPluginProvider, PluginLoader } from '@weavix/tracker-plugin-sdk-react';
126
317
 
127
318
  root.render(
128
- <TrackerPluginProvider autoNotifyReady={false}>
319
+ <TrackerPluginProvider fallback={<PluginLoader />}>
129
320
  <App />
130
- </TrackerPluginProvider>,
321
+ </TrackerPluginProvider>
131
322
  );
132
323
  ```
133
324
 
134
- ## Компоненты
325
+ No props.
135
326
 
136
- ### `TrackerPluginProvider`
327
+ ### `PluginError`
137
328
 
138
- Оборачивает приложение и управляет жизненным циклом плагина.
329
+ Built-in component for displaying an initialisation error.
139
330
 
140
- **Props:**
331
+ ```tsx
332
+ import { PluginError } from '@weavix/tracker-plugin-sdk-react';
141
333
 
142
- | Prop | Тип | По умолчанию | Описание |
143
- | ----------------- | ----------------------------- | ------------------ | --------------------------------------------------------------- |
144
- | `autoResize` | `boolean` | `true` | Автоматически изменять размер контейнера при изменении контента |
145
- | `fallback` | `ReactNode` | `<PluginLoader />` | Отображается во время инициализации |
146
- | `errorFallback` | `(error: Error) => ReactNode` | `<PluginError />` | Отображается при ошибке инициализации |
147
- | `autoNotifyReady` | `boolean` | `true` | Автоматически уведомлять хост о готовности плагина |
334
+ <TrackerPluginProvider errorFallback={(error) => <PluginError error={error} />}>
335
+ <App />
336
+ </TrackerPluginProvider>
337
+ ```
148
338
 
149
- ## Хуки
339
+ | Prop | Type | Description |
340
+ |------|------|-------------|
341
+ | `error` | `Error` | Error to display |
150
342
 
151
- ### `useTrackerPluginContext<TSlot>(level?)`
343
+ ---
152
344
 
153
- Возвращает тему, язык, имя слота и контекст слота.
345
+ ## Common patterns
154
346
 
155
- - **`level: 'basic'`** (по умолчанию) — `slotContext`: `{ entityId, entityMeta? }`
156
- - **`level: 'full'`** — полный контекст слота (`Issue` для `issue.action`); нужен `contextLevel: "full"` в манифесте
347
+ ### Theme-aware rendering
157
348
 
158
- **Возвращает:** `{ theme, language, slot, slotContext, registerHandler }`
349
+ ```tsx
350
+ function App() {
351
+ const theme = useTheme();
352
+ return (
353
+ <div className={`app app--${theme ?? 'light'}`}>
354
+ ...
355
+ </div>
356
+ );
357
+ }
358
+ ```
159
359
 
160
- Подробнее: [API Reference — useTrackerPluginContext](./API_REFERENCE.md#usetrackerplugincontext).
360
+ ### Localised strings
161
361
 
162
- ### `useToaster()`
362
+ ```tsx
363
+ const LABELS = {
364
+ save: { ru: 'Сохранить', en: 'Save' },
365
+ cancel: { ru: 'Отмена', en: 'Cancel' },
366
+ };
163
367
 
164
- Хук для показа toast-уведомлений в хост-приложении.
368
+ function Form() {
369
+ const t = useLocalizedString();
370
+ return (
371
+ <form>
372
+ <button type="submit">{t(LABELS.save)}</button>
373
+ <button type="button">{t(LABELS.cancel)}</button>
374
+ </form>
375
+ );
376
+ }
377
+ ```
165
378
 
166
- > **Permission:** `"toaster"` в `permissions.ui` манифеста.
379
+ ### Reading the current issue (full context)
167
380
 
168
381
  ```tsx
169
- import { useToaster } from '@weavix/tracker-plugin-sdk-react';
382
+ function IssueActions() {
383
+ const { slotContext: issue } = useTrackerPluginContext<'issue.action'>('full');
384
+ // issue: Issue | undefined
170
385
 
171
- function MyComponent() {
172
- const toaster = useToaster();
386
+ if (!issue) return null;
173
387
 
174
- const handleSave = async () => {
175
- await saveData();
176
- toaster.add({ title: 'Сохранено', theme: 'success' });
177
- };
178
-
179
- return <button onClick={handleSave}>Сохранить</button>;
388
+ return (
389
+ <div>
390
+ <h2>{issue.key}: {issue.summary}</h2>
391
+ <p>Queue: {issue.queue?.key}</p>
392
+ <p>Assignee: {issue.assignee?.login}</p>
393
+ </div>
394
+ );
180
395
  }
181
396
  ```
182
397
 
183
- Параметры `add(options)` в [README tracker-core](../tracker-plugin-external/README.md#тосты-toast-notifications).
398
+ ### Calling the Tracker API
184
399
 
185
- ### `useLocalizedString(fallbackLanguage?)`
400
+ ```tsx
401
+ import { trackerApi } from '@weavix/tracker-plugin-sdk-react';
186
402
 
187
- Возвращает `(value: LocalizedString) => string` для текущего языка из контекста.
403
+ function IssueList() {
404
+ const [issues, setIssues] = useState([]);
188
405
 
189
- ## Полная документация
406
+ useEffect(() => {
407
+ trackerApi.v3.post['/v2/issues/_search']({
408
+ bodyParams: { filter: { queue: 'MYQUEUE' } },
409
+ }).then(({ data }) => setIssues(data));
410
+ }, []);
190
411
 
191
- 📖 [AGENTS.md](./AGENTS.md) вход для агентов.
412
+ return <ul>{issues.map(i => <li key={i.id}>{i.summary}</li>)}</ul>;
413
+ }
414
+ ```
192
415
 
193
- 📖 [COOKBOOK](../../docs/agent/COOKBOOK.md) — рецепты.
416
+ ---
194
417
 
195
- 📖 [API Reference](./API_REFERENCE.md) — Provider, хуки, contextLevel.
418
+ ## Related packages
196
419
 
197
- 📖 [README tracker-core](../tracker-plugin-external/README.md) `trackerApi`, `hostApi`, типы, ошибки.
420
+ | Package | Purpose |
421
+ |---------|---------|
422
+ | [`@weavix/tracker-plugin-sdk`](https://www.npmjs.com/package/@weavix/tracker-plugin-sdk) | Core SDK: `trackerApi`, `hostApi`, `storageApi` |
423
+ | [`@weavix/tracker-api-types`](https://www.npmjs.com/package/@weavix/tracker-api-types) | Tracker Public API v3 types |
424
+ | [`@weavix/sdk-react`](https://www.npmjs.com/package/@weavix/sdk-react) | Base React wrapper |
425
+ | [`@weavix/sdk-core`](https://www.npmjs.com/package/@weavix/sdk-core) | Base runtime |
198
426
 
199
- ## Лицензия
427
+ ## License
200
428
 
201
- UNLICENSED
429
+ SEE LICENSE IN LICENSE
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weavix/tracker-plugin-sdk-react",
3
- "version": "0.0.33",
3
+ "version": "0.0.34",
4
4
  "exports": {
5
5
  ".": {
6
6
  "types": "./dist/index.d.ts",
@@ -23,14 +23,14 @@
23
23
  "access": "public"
24
24
  },
25
25
  "dependencies": {
26
- "@weavix/tracker-plugin-sdk": "^0.0.33",
27
- "@weavix/sdk-core": "^0.0.35",
28
- "@weavix/sdk-react": "^0.0.35",
29
- "@weavix/tracker-core": "^0.0.33"
26
+ "@weavix/tracker-plugin-sdk": "^0.0.34",
27
+ "@weavix/sdk-core": "^0.0.39",
28
+ "@weavix/sdk-react": "^0.0.39",
29
+ "@weavix/tracker-core": "^0.0.34"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "react": "^18.0.0",
33
- "@weavix/tracker-core": "^0.0.33"
33
+ "@weavix/tracker-core": "^0.0.34"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@testing-library/jest-dom": "*",