@foxglove/extension 2.22.0 → 2.24.0
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/package.json +1 -1
- package/src/index.ts +622 -90
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Immutable } from "./immutable";
|
|
|
2
2
|
|
|
3
3
|
export type { Immutable } from "./immutable";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
/** Valid types for parameter data (such as rosparams) */
|
|
6
6
|
export type ParameterValue =
|
|
7
7
|
| undefined
|
|
8
8
|
| boolean
|
|
@@ -13,7 +13,7 @@ export type ParameterValue =
|
|
|
13
13
|
| ParameterValue[]
|
|
14
14
|
| { [key: string]: ParameterValue };
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
/** Valid types for [variables](https://docs.foxglove.dev/docs/visualization/variables) */
|
|
17
17
|
export type VariableValue =
|
|
18
18
|
| undefined
|
|
19
19
|
| boolean
|
|
@@ -24,16 +24,23 @@ export type VariableValue =
|
|
|
24
24
|
|
|
25
25
|
export type VariableStruct = { [key: string]: VariableValue };
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
/** Valid types for application settings */
|
|
28
28
|
export type AppSettingValue = string | number | boolean | undefined;
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
/**
|
|
31
|
+
* A timestamp with nanosecond precision.
|
|
32
|
+
*
|
|
33
|
+
* The timestamp is often nanoseconds since the UNIX epoch, but may be
|
|
34
|
+
* relative to another event such as system boot time or simulation start
|
|
35
|
+
* time depending on the context.
|
|
36
|
+
*/
|
|
37
|
+
export type Time = {
|
|
31
38
|
sec: number;
|
|
32
39
|
nsec: number;
|
|
33
|
-
}
|
|
40
|
+
};
|
|
34
41
|
|
|
35
42
|
/**
|
|
36
|
-
* A
|
|
43
|
+
* A Topic is a named channel of messages.
|
|
37
44
|
*/
|
|
38
45
|
export type Topic = {
|
|
39
46
|
/**
|
|
@@ -56,11 +63,16 @@ export type Topic = {
|
|
|
56
63
|
/**
|
|
57
64
|
* Lists any additional schema names available for subscribers on the topic. When subscribing to
|
|
58
65
|
* a topic, the panel can request messages be automatically converted from schemaName into one
|
|
59
|
-
* of the convertibleTo schemas using the convertTo option.
|
|
66
|
+
* of the convertibleTo schemas using the {@link Subscription.convertTo} option.
|
|
60
67
|
*/
|
|
61
68
|
convertibleTo?: readonly string[];
|
|
62
69
|
};
|
|
63
70
|
|
|
71
|
+
/**
|
|
72
|
+
* A single subscription passed to {@link PanelExtensionContext.subscribe}.
|
|
73
|
+
*
|
|
74
|
+
* @category Custom panels
|
|
75
|
+
*/
|
|
64
76
|
export type Subscription = {
|
|
65
77
|
topic: string;
|
|
66
78
|
|
|
@@ -77,12 +89,16 @@ export type Subscription = {
|
|
|
77
89
|
* messages for the topic. The default behavior is to only load messages for the current frame.
|
|
78
90
|
*
|
|
79
91
|
* **Only** topics with `preload: true` are available in the `allFrames` render state.
|
|
92
|
+
*
|
|
93
|
+
* @deprecated Please use {@link PanelExtensionContext.subscribeMessageRange} instead.
|
|
80
94
|
*/
|
|
81
95
|
preload?: boolean;
|
|
82
96
|
};
|
|
83
97
|
|
|
84
98
|
/**
|
|
85
|
-
* A
|
|
99
|
+
* A MessageEvent represents a single message along with metadata about the message.
|
|
100
|
+
*
|
|
101
|
+
* Remember to import MessageEvent from `@foxglove/extension`. This is not the same as the DOM [MessageEvent](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent) class.
|
|
86
102
|
*/
|
|
87
103
|
export type MessageEvent<T = unknown> = {
|
|
88
104
|
/** The topic name this message was received on, i.e. "/some/topic" */
|
|
@@ -117,14 +133,39 @@ export type MessageEvent<T = unknown> = {
|
|
|
117
133
|
|
|
118
134
|
/**
|
|
119
135
|
* When subscribing to a topic using the `convertTo` option, the message event `message`
|
|
120
|
-
* contains the converted message and the originalMessageEvent field contains the original
|
|
136
|
+
* contains the converted message and the `originalMessageEvent` field contains the original
|
|
121
137
|
* un-converted message event.
|
|
122
138
|
*/
|
|
123
139
|
originalMessageEvent?: MessageEvent;
|
|
124
140
|
};
|
|
125
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Actions the panel may perform related to the user's current layout via {@link PanelExtensionContext.layout | context.layout}.
|
|
144
|
+
*
|
|
145
|
+
* @category Custom panels
|
|
146
|
+
*/
|
|
126
147
|
export interface LayoutActions {
|
|
127
|
-
/**
|
|
148
|
+
/**
|
|
149
|
+
* Use `context.layout.addPanel` to add a panel adjacent to the current panel in the layout.
|
|
150
|
+
*
|
|
151
|
+
* The value of `position` must be set to `"sibling"`.
|
|
152
|
+
*
|
|
153
|
+
* The value of `type` can refer to a panel from a custom extension as `extensionname.panelname`,
|
|
154
|
+
* where `extensionname` is the extension name from `package.json` and `panelname` is the name
|
|
155
|
+
* provided when the extension registers a panel.
|
|
156
|
+
*
|
|
157
|
+
* `getState` is set to a function that returns the state (also known as panel settings) for the
|
|
158
|
+
* new panel, or return `undefined` to use the new panel's default settings.
|
|
159
|
+
*
|
|
160
|
+
* ```ts
|
|
161
|
+
* // Add new panel
|
|
162
|
+
* context.layout.addPanel({
|
|
163
|
+
* position: "sibling",
|
|
164
|
+
* type: "MyExtension.MyPanel",
|
|
165
|
+
* getState: () => ({}),
|
|
166
|
+
* });
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
128
169
|
addPanel(params: {
|
|
129
170
|
/**
|
|
130
171
|
* Where to position the panel. Currently, only "sibling" is supported which indicates the
|
|
@@ -156,6 +197,19 @@ export interface LayoutActions {
|
|
|
156
197
|
}): void;
|
|
157
198
|
}
|
|
158
199
|
|
|
200
|
+
/**
|
|
201
|
+
* RenderState is the information passed to your panel's
|
|
202
|
+
* {@link PanelExtensionContext.onRender | onRender} function.
|
|
203
|
+
*
|
|
204
|
+
* To receive updates for a particular part of RenderState, you must first call
|
|
205
|
+
* {@link PanelExtensionContext.watch | watch} with the field name. For example, call
|
|
206
|
+
* `watch("currentTime")` to receive updates for `currentTime`.
|
|
207
|
+
*
|
|
208
|
+
* If a field is missing from RenderState, either the value has not changed since the last call to
|
|
209
|
+
* `onRender`, or you did not `watch` the field.
|
|
210
|
+
*
|
|
211
|
+
* @category Custom panels
|
|
212
|
+
*/
|
|
159
213
|
export type RenderState = {
|
|
160
214
|
/**
|
|
161
215
|
* The latest messages for the current render frame. These are new messages since the last render frame.
|
|
@@ -171,6 +225,8 @@ export type RenderState = {
|
|
|
171
225
|
|
|
172
226
|
/**
|
|
173
227
|
* All available messages. Best-effort list of all available messages.
|
|
228
|
+
*
|
|
229
|
+
* @deprecated Please use {@link PanelExtensionContext.subscribeMessageRange} instead.
|
|
174
230
|
*/
|
|
175
231
|
allFrames?: MessageEvent[];
|
|
176
232
|
|
|
@@ -231,11 +287,16 @@ export type RenderState = {
|
|
|
231
287
|
/** The color scheme currently in use throughout the app. */
|
|
232
288
|
colorScheme?: "dark" | "light";
|
|
233
289
|
|
|
234
|
-
/** Application settings. This will only contain subscribed
|
|
290
|
+
/** Application settings. This will only contain keys/values that were subscribed to using {@link @PanelExtensionContext.subscribeAppSettings} */
|
|
235
291
|
appSettings?: Map<string, AppSettingValue>;
|
|
236
292
|
};
|
|
237
293
|
|
|
238
|
-
|
|
294
|
+
/**
|
|
295
|
+
* This type represents the arguments you pass to {@link PanelExtensionContext.subscribeMessageRange}.
|
|
296
|
+
*
|
|
297
|
+
* @category Custom panels
|
|
298
|
+
*/
|
|
299
|
+
export type SubscribeMessageRangeArgs = {
|
|
239
300
|
/**
|
|
240
301
|
* Topic to be subscribed to.
|
|
241
302
|
*/
|
|
@@ -251,7 +312,7 @@ type SubscribeMessageRangeArgs = {
|
|
|
251
312
|
*/
|
|
252
313
|
convertTo?: string;
|
|
253
314
|
/**
|
|
254
|
-
* `
|
|
315
|
+
* `onNewRangeIterator` is a function that receives an async iterable when there is message data available on
|
|
255
316
|
* the subscription.
|
|
256
317
|
*
|
|
257
318
|
* To read messages, your function should iterate through the provided async iterable. Each item
|
|
@@ -260,25 +321,47 @@ type SubscribeMessageRangeArgs = {
|
|
|
260
321
|
* finish.
|
|
261
322
|
*
|
|
262
323
|
* ```typescript
|
|
263
|
-
* async function
|
|
324
|
+
* async function onNewRangeIterator(batchIterator) {
|
|
264
325
|
* for await (const batch of batchIterator) {
|
|
265
326
|
* //...
|
|
266
327
|
* }
|
|
267
328
|
* }
|
|
268
329
|
* ```
|
|
269
330
|
*
|
|
270
|
-
* `
|
|
331
|
+
* `onNewRangeIterator` is called again when the upstream topic data changes. I.E subscribing to a
|
|
271
332
|
* user-script output topic and the user script changes, or subscribing to an aliased topic and
|
|
272
333
|
* the alias changes. When topic data changes, the previous iterator will end, and its data is no
|
|
273
|
-
* longer valid. When `
|
|
334
|
+
* longer valid. When `onNewRangeIterator` is called, you should discard previously received data.
|
|
274
335
|
*
|
|
275
|
-
* If your `
|
|
276
|
-
* more messages until `
|
|
336
|
+
* If your `onNewRangeIterator` function throws an error, the iterator will end and you will not receive any
|
|
337
|
+
* more messages until `onNewRangeIterator` is called again. Your error will appear in the problems sidebar
|
|
277
338
|
* for user visibility.
|
|
278
339
|
*/
|
|
279
|
-
|
|
340
|
+
onNewRangeIterator: (batchIterator: AsyncIterable<Immutable<MessageEvent[]>>) => Promise<void>;
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* @deprecated This method has been renamed. Use `onNewRangeIterator`.
|
|
344
|
+
*/
|
|
345
|
+
onReset?: (batchIterator: AsyncIterable<Immutable<MessageEvent[]>>) => Promise<void>;
|
|
280
346
|
};
|
|
281
347
|
|
|
348
|
+
/**
|
|
349
|
+
* The `PanelExtensionContext` exposes properties and methods for writing a custom panel. The
|
|
350
|
+
* context has methods to subscribe for messages, receive updates, configure your panel's settings,
|
|
351
|
+
* and render your panel to the UI.
|
|
352
|
+
*
|
|
353
|
+
* The {@link ExtensionPanelRegistration.initPanel | initPanel} function used in
|
|
354
|
+
* {@link ExtensionContext.registerPanel | registerPanel} accepts a {@link PanelExtensionContext}
|
|
355
|
+
* argument. This argument contains properties and methods for accessing panel data and rendering UI
|
|
356
|
+
* updates. The `initPanel` function also returns an optional cleanup function to run when the
|
|
357
|
+
* extension `panelElement` unmounts.
|
|
358
|
+
*
|
|
359
|
+
* See the [Creating a custom
|
|
360
|
+
* panel](https://docs.foxglove.dev/docs/visualization/extensions/guides/create-custom-panel) guide
|
|
361
|
+
* for more details.
|
|
362
|
+
*
|
|
363
|
+
* @category Custom panels
|
|
364
|
+
*/
|
|
282
365
|
export type PanelExtensionContext = {
|
|
283
366
|
/**
|
|
284
367
|
* The root element for the panel. Add your panel elements as children under this element.
|
|
@@ -290,7 +373,7 @@ export type PanelExtensionContext = {
|
|
|
290
373
|
*/
|
|
291
374
|
readonly initialState: unknown;
|
|
292
375
|
|
|
293
|
-
/** Actions the panel may perform related to the user's current layout. */
|
|
376
|
+
/** Actions the panel may perform related to the user's current layout. See {@link LayoutActions} for details. */
|
|
294
377
|
readonly layout: LayoutActions;
|
|
295
378
|
|
|
296
379
|
/**
|
|
@@ -304,103 +387,285 @@ export type PanelExtensionContext = {
|
|
|
304
387
|
/**
|
|
305
388
|
* Subscribe to updates on this field within the render state. Render will only be invoked when
|
|
306
389
|
* this field changes.
|
|
390
|
+
*
|
|
391
|
+
* Use `context.watch` to indicate which fields in {@link RenderState} (e.g. `currentFrame`,
|
|
392
|
+
* `currentTime`, `previewTime`, `parameters`, `topics`) should trigger panel re-renders when
|
|
393
|
+
* their contained values change.
|
|
394
|
+
*
|
|
395
|
+
* ```ts
|
|
396
|
+
* context.watch("topics");
|
|
397
|
+
* context.watch("currentFrame");
|
|
398
|
+
* context.watch("parameters");
|
|
399
|
+
* context.watch("currentTime");
|
|
400
|
+
* ```
|
|
401
|
+
*/
|
|
402
|
+
watch(field: keyof RenderState): void;
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Subscribe to updates on this field within the render state. Render will only be invoked when
|
|
406
|
+
* this field changes.
|
|
407
|
+
*
|
|
408
|
+
* @deprecated Calling `watch` with `allFrames` is deprecated. Use {@link PanelExtensionContext.subscribeMessageRange} instead.
|
|
307
409
|
*/
|
|
308
|
-
watch
|
|
410
|
+
watch(field: "allFrames"): void;
|
|
309
411
|
|
|
310
412
|
/**
|
|
311
|
-
*
|
|
312
|
-
*
|
|
413
|
+
* Use `context.saveState` to save an arbitrary object as persisted panel state (also known as
|
|
414
|
+
* panel settings) in the current layout. You can view the current panel state using
|
|
415
|
+
* [Import/export settings](https://docs.foxglove.dev/docs/visualization/panels/introduction#importexport-settings).
|
|
416
|
+
*
|
|
417
|
+
* ```ts
|
|
418
|
+
* context.initialState = undefined; // your panel's initial state
|
|
313
419
|
*
|
|
314
|
-
*
|
|
420
|
+
* context.saveState({ myNum: 2, myBool: false, myStr: "abc" });
|
|
421
|
+
* ```
|
|
422
|
+
*
|
|
423
|
+
* @param state The state to save. This value should be JSON serializable.
|
|
315
424
|
*/
|
|
316
|
-
saveState
|
|
425
|
+
saveState(state: Partial<unknown>): void;
|
|
317
426
|
|
|
318
427
|
/**
|
|
319
|
-
*
|
|
428
|
+
* Use `context.setParameter` to set a parameter `name` to any valid `value` (i.e. primitives, dates, `Uint8Array`s, and arrays or objects containing these values).
|
|
429
|
+
*
|
|
430
|
+
* ```ts
|
|
431
|
+
* context.setParameter("/param1", "value1");
|
|
432
|
+
* ```
|
|
320
433
|
*
|
|
321
434
|
* @param name The name of the parameter to set.
|
|
322
435
|
* @param value The new value of the parameter.
|
|
323
436
|
*/
|
|
324
|
-
setParameter
|
|
437
|
+
setParameter(name: string, value: ParameterValue): void;
|
|
325
438
|
|
|
326
439
|
/**
|
|
327
440
|
* Set the transient state shared by panels of the same type as the caller of this function.
|
|
328
441
|
* This will not be persisted in the layout.
|
|
329
442
|
*/
|
|
330
|
-
setSharedPanelState
|
|
443
|
+
setSharedPanelState(state: undefined | Record<string, unknown>): void;
|
|
331
444
|
|
|
332
445
|
/**
|
|
333
|
-
*
|
|
446
|
+
* Use `context.setVariable` to set a
|
|
447
|
+
* [variable](https://docs.foxglove.dev/docs/visualization/variables) `name` to any valid variable
|
|
448
|
+
* `value`.
|
|
449
|
+
*
|
|
450
|
+
* ```ts
|
|
451
|
+
* context.setVariable("myVar", 55);
|
|
452
|
+
*
|
|
453
|
+
* context.onRender = (renderState: RenderState, done) => {
|
|
454
|
+
* // Read variable values from the renderState
|
|
455
|
+
* const variableValues = renderState.variables;
|
|
456
|
+
* const myVarValue = variableValues.myVar;
|
|
457
|
+
*
|
|
458
|
+
* // Call done when you've rendered all the UI for this renderState. If your UI framework delays rendering, call done when rendering has actaully happened.
|
|
459
|
+
* done();
|
|
460
|
+
* };
|
|
461
|
+
* ```
|
|
334
462
|
*
|
|
335
463
|
* @param name The name of the variable to set.
|
|
336
464
|
* @param value The new value of the variable.
|
|
337
465
|
*/
|
|
338
|
-
setVariable
|
|
466
|
+
setVariable(name: string, value: VariableValue): void;
|
|
339
467
|
|
|
340
468
|
/**
|
|
341
469
|
* Set the active preview time. Setting the preview time to undefined clears the preview time.
|
|
342
470
|
*/
|
|
343
|
-
setPreviewTime
|
|
471
|
+
setPreviewTime(time: number | undefined): void;
|
|
344
472
|
|
|
345
473
|
/**
|
|
346
474
|
* Seek playback to the given time. Behaves as if the user had clicked the playback bar
|
|
347
475
|
* to seek.
|
|
348
476
|
*
|
|
349
477
|
* Clients can pass a number or alternatively a Time object for greater precision.
|
|
350
|
-
*/
|
|
351
|
-
seekPlayback?: (time: number | Time) => void;
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* Subscribe to an array of topic names.
|
|
355
|
-
*
|
|
356
|
-
* Subscribe will update the current subscriptions to the list of topic names. Passing an empty
|
|
357
|
-
* array will unsubscribe from all topics.
|
|
358
|
-
*
|
|
359
|
-
* Calling subscribe with an empty array of topics is analagous to unsubscribeAll.
|
|
360
478
|
*
|
|
361
|
-
*
|
|
479
|
+
* This property may be `undefined` if the current data source does not support seeking.
|
|
362
480
|
*/
|
|
363
|
-
|
|
481
|
+
seekPlayback?(time: number | Time): void;
|
|
364
482
|
|
|
365
483
|
/**
|
|
366
|
-
*
|
|
484
|
+
* Use `context.subscribe` to indicate the topics your panel wants to receive messages for. The
|
|
485
|
+
* messages are provided during render in {@link RenderState.currentFrame}.
|
|
367
486
|
*
|
|
368
|
-
*
|
|
487
|
+
* @remarks
|
|
488
|
+
*
|
|
489
|
+
* This method will update the current subscriptions to the new list of Subscriptions and
|
|
369
490
|
* unsubscribe from any previously subscribed topics no longer in the Subscription list. Passing
|
|
370
491
|
* an empty array will unsubscribe from all topics.
|
|
371
492
|
*
|
|
372
|
-
*
|
|
493
|
+
* ```ts
|
|
494
|
+
* context.subscribe([{ topic: "/some/topic" }, { topic: "/another/topic" }]);
|
|
495
|
+
* ```
|
|
496
|
+
*
|
|
497
|
+
* `context.subscribe([])` will unsubscribe from all topics, and is equivalent to
|
|
498
|
+
* `unsubscribeAll`.
|
|
499
|
+
*
|
|
500
|
+
* #### Range loading
|
|
501
|
+
*
|
|
502
|
+
* Most panels display data from the current frame; examples of built-in panels that display the
|
|
503
|
+
* current frame are 3D, Image, and Raw Message, however some panels can display data for multiple
|
|
504
|
+
* messages or even the entire dataset duration (Plot, Map, State Transitions).
|
|
505
|
+
*
|
|
506
|
+
* Subscriptions will provide only the messages for the current frame. If your panel would like to
|
|
507
|
+
* process all the available messages on a topic, use
|
|
508
|
+
* {@link @PanelExtensionContext.subscribeMessageRange | subscribeMessageRange} instead.
|
|
509
|
+
*
|
|
510
|
+
* > NOTE: Message range loading is done on a best-effort basis. If your range-loaded messages
|
|
511
|
+
* > exceed available memory limits for the browser or desktop app, then the data may not
|
|
512
|
+
* > represent the full dataset range. Range loading results in more data transfer and memory use
|
|
513
|
+
* > and is recommended only for panels which require access to the entire dataset.
|
|
514
|
+
*
|
|
515
|
+
* #### Message converters
|
|
516
|
+
*
|
|
517
|
+
* Message converters can convert messages from one schema to another – for example, a user might
|
|
518
|
+
* convert custom GPS message into
|
|
519
|
+
* [`foxglove.LocationFix`](https://docs.foxglove.dev/docs/visualization/message-schemas/location-fix)
|
|
520
|
+
* messages for visualization in the [Map
|
|
521
|
+
* panel](https://docs.foxglove.dev/docs/visualization/panels/map). Users may have one or more
|
|
522
|
+
* message converters registered.
|
|
523
|
+
*
|
|
524
|
+
* If your panel expects messages with specific schema names, you can leverage registered message
|
|
525
|
+
* converters to convert from one schema to another.
|
|
526
|
+
*
|
|
527
|
+
* Specify the `convertTo` option to enable message conversion on a topic. When conversion is
|
|
528
|
+
* enabled for a subscription, the {@link MessageEvent}s will contain `message` entries with the
|
|
529
|
+
* converted message rather than the original message on the topic. The original message is
|
|
530
|
+
* available in the `originalMessageEvent` field in the message event.
|
|
531
|
+
*
|
|
532
|
+
* ```ts
|
|
533
|
+
* context.subscribe([{ topic: "/some/topic", convertTo: "foxglove.LocationFix" }]);
|
|
534
|
+
* ```
|
|
535
|
+
*
|
|
536
|
+
* The {@link Topic.convertibleTo | convertibleTo} field within {@link RenderState.topics} will
|
|
537
|
+
* contain the names of schemas you can convert this topic into.
|
|
373
538
|
*/
|
|
374
539
|
subscribe(subscriptions: Subscription[]): void;
|
|
375
540
|
|
|
541
|
+
/**
|
|
542
|
+
* @deprecated Use `subscribe` with an array of Subscription objects instead.
|
|
543
|
+
*/
|
|
544
|
+
subscribe(topics: string[]): void;
|
|
545
|
+
|
|
376
546
|
/**
|
|
377
547
|
* Unsubscribe from all topics.
|
|
378
548
|
*
|
|
379
|
-
* Note: This is analagous to calling subscribe([]) with an empty array of topics.
|
|
549
|
+
* Note: This is analagous to calling `subscribe([])` with an empty array of topics.
|
|
380
550
|
*/
|
|
381
551
|
unsubscribeAll(): void;
|
|
382
552
|
|
|
383
553
|
/**
|
|
384
|
-
* Subscribe to any changes in application settings for an array of setting
|
|
554
|
+
* Subscribe to any changes in application settings for an array of setting keys.
|
|
555
|
+
*
|
|
556
|
+
* The keys and their corresponding values are not currently documented and are subject to change.
|
|
385
557
|
*/
|
|
386
558
|
subscribeAppSettings(settings: string[]): void;
|
|
387
559
|
|
|
388
560
|
/**
|
|
389
|
-
*
|
|
561
|
+
* Use `context.advertise` to indicate an intent to publish a specific datatype on a topic. A
|
|
562
|
+
* panel must call `context.advertise` before being able to publish on the topic
|
|
563
|
+
* (`context.publish`). Options are specific to the data source - some make use of options; others
|
|
564
|
+
* do not.
|
|
565
|
+
*
|
|
566
|
+
* This property may be `undefined` if the current data source does not support publishing.
|
|
567
|
+
*
|
|
568
|
+
* ```ts
|
|
569
|
+
* context.advertise("/my_image_topic", "sensor_msgs/Image");
|
|
570
|
+
* ```
|
|
571
|
+
*
|
|
572
|
+
* `options` are specific to each data source - see documentation below for supported data
|
|
573
|
+
* sources.
|
|
390
574
|
*
|
|
391
575
|
* @param topic The topic on which the extension will publish messages.
|
|
392
576
|
* @param schemaName The name of the schema that the published messages will conform to.
|
|
393
577
|
* @param options Options passed to the current data source for additional configuration.
|
|
578
|
+
*
|
|
579
|
+
* @remarks
|
|
580
|
+
*
|
|
581
|
+
* #### [Native (ROS 1)](https://docs.foxglove.dev/docs/connecting-to-data/frameworks/ros1#native)
|
|
582
|
+
*
|
|
583
|
+
* | field | type | description |
|
|
584
|
+
* | --------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
585
|
+
* | datatypes | `Map<string, T>` | JavaScript map of datatype names and [`MessageDefinition`](https://github.com/foxglove/message-definition/blob/main/src/types.ts#L185) definitions for a given topic |
|
|
586
|
+
*
|
|
587
|
+
* Common datatype definitions are available in the `@foxglove/rosmsg-msgs-common` package.
|
|
588
|
+
*
|
|
589
|
+
* ```ts
|
|
590
|
+
* import { ros1 } from "@foxglove/rosmsg-msgs-common";
|
|
591
|
+
*
|
|
592
|
+
* context.advertise?.(currentTopic, "sensor_msgs/Joy", {
|
|
593
|
+
* datatypes: new Map([
|
|
594
|
+
* ["std_msgs/Header", ros1["std_msgs/Header"]],
|
|
595
|
+
* ["std_msgs/Float32", ros1["std_msgs/Float32"]],
|
|
596
|
+
* ["std_msgs/Int32", ros1["std_msgs/Int32"]],
|
|
597
|
+
* ["sensor_msgs/Joy", ros1["sensor_msgs/Joy"]],
|
|
598
|
+
* ]),
|
|
599
|
+
* });
|
|
600
|
+
* ```
|
|
601
|
+
*
|
|
602
|
+
* #### [Foxglove WebSocket](https://docs.foxglove.dev/docs/connecting-to-data/frameworks/custom#foxglove-websocket)
|
|
603
|
+
*
|
|
604
|
+
* `options` depend on the server implementation.
|
|
605
|
+
*
|
|
606
|
+
* ##### [Foxglove Bridge](https://docs.foxglove.dev/docs/connecting-to-data/ros-foxglove-bridge)
|
|
607
|
+
*
|
|
608
|
+
* When using the Foxglove Bridge with ROS data, use `context.dataSourceProfile` to determine the
|
|
609
|
+
* ROS version.
|
|
610
|
+
*
|
|
611
|
+
* For ROS 1 data, pass datatypes the same way you would for a [native ROS 1](#native-ros-1)
|
|
612
|
+
* connection.
|
|
613
|
+
*
|
|
614
|
+
* For ROS 2 data, pass datatypes using the following fields:
|
|
615
|
+
*
|
|
616
|
+
* | field | type | description |
|
|
617
|
+
* | --------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
618
|
+
* | datatypes | `Map<string, T>` | JavaScript map of datatype names and [`MessageDefinition`](https://github.com/foxglove/message-definition/blob/main/src/types.ts#L185) definitions for a given topic |
|
|
619
|
+
*
|
|
620
|
+
* Common datatype definitions are available in the `@foxglove/rosmsg-msgs-common` package.
|
|
621
|
+
*
|
|
622
|
+
* ```ts
|
|
623
|
+
* import { ros2humble as ros2 } from "@foxglove/rosmsg-msgs-common";
|
|
624
|
+
* // For Galactic and lower, use:
|
|
625
|
+
* // import { ros2galactic as ros2 } from "@foxglove/rosmsg-msgs-common";
|
|
626
|
+
* ```
|
|
627
|
+
*
|
|
628
|
+
* ```ts
|
|
629
|
+
* context.advertise?.(currentTopic, "sensor_msgs/Joy", {
|
|
630
|
+
* datatypes: new Map([
|
|
631
|
+
* ["std_msgs/Header", ros2["std_msgs/Header"]],
|
|
632
|
+
* ["std_msgs/Float32", ros2["std_msgs/Float32"]],
|
|
633
|
+
* ["std_msgs/Int32", ros2["std_msgs/Int32"]],
|
|
634
|
+
* ["sensor_msgs/Joy", ros2["sensor_msgs/Joy"]],
|
|
635
|
+
* ]),
|
|
636
|
+
* });
|
|
637
|
+
* ```
|
|
638
|
+
*
|
|
639
|
+
* #### Rosbridge ([ROS 1](https://docs.foxglove.dev/docs/connecting-to-data/frameworks/ros1#rosbridge), [ROS 2](https://docs.foxglove.dev/docs/connecting-to-data/frameworks/ros2#rosbridge))
|
|
640
|
+
*
|
|
641
|
+
* No `options` required. Simply publish a JSON message with fields conforming to the advertised
|
|
642
|
+
* datatype, and the bridge node will serialize it according to the datatype.
|
|
394
643
|
*/
|
|
395
644
|
advertise?(topic: string, schemaName: string, options?: Record<string, unknown>): void;
|
|
396
645
|
|
|
397
646
|
/**
|
|
398
647
|
* Indicate that you no longer want to advertise on this topic.
|
|
648
|
+
*
|
|
649
|
+
* ```ts
|
|
650
|
+
* context.unadvertise("/my_image_topic");
|
|
651
|
+
* ```
|
|
652
|
+
*
|
|
653
|
+
* This property may be `undefined` if the current data source does not support publishing.
|
|
399
654
|
*/
|
|
400
655
|
unadvertise?(topic: string): void;
|
|
401
656
|
|
|
402
657
|
/**
|
|
403
|
-
*
|
|
658
|
+
* Use `context.publish` to publish a message on a previously advertised topic. (You must first
|
|
659
|
+
* call {@link PanelExtensionContext.advertise | advertise} to advertise the topic before
|
|
660
|
+
* publishing.) If the topic is not advertised or otherwise malformed, the function will throw an
|
|
661
|
+
* error.
|
|
662
|
+
*
|
|
663
|
+
* ```ts
|
|
664
|
+
* context.advertise("/my_color_topic", "std_msgs/ColorRGBA");
|
|
665
|
+
* context.publish("/my_color_topic", { r: 0, g: 1, b: 0, a: 1 });
|
|
666
|
+
* ```
|
|
667
|
+
*
|
|
668
|
+
* This property may be `undefined` if the current data source does not support publishing.
|
|
404
669
|
*
|
|
405
670
|
* @param topic The name of the topic to publish the message on
|
|
406
671
|
* @param message The message to publish
|
|
@@ -408,7 +673,13 @@ export type PanelExtensionContext = {
|
|
|
408
673
|
publish?(topic: string, message: unknown): void;
|
|
409
674
|
|
|
410
675
|
/**
|
|
411
|
-
*
|
|
676
|
+
* Use `context.callService` to make a service call to the specified `service` with a request payload.
|
|
677
|
+
*
|
|
678
|
+
* ```ts
|
|
679
|
+
* context.callService("my_service", { foo: "bar" });
|
|
680
|
+
* ```
|
|
681
|
+
*
|
|
682
|
+
* This property may be `undefined` if the current data source does not support services.
|
|
412
683
|
*
|
|
413
684
|
* @param service The name of the service to call
|
|
414
685
|
* @param request The request payload for the service call
|
|
@@ -417,68 +688,215 @@ export type PanelExtensionContext = {
|
|
|
417
688
|
callService?(service: string, request: unknown): Promise<unknown>;
|
|
418
689
|
|
|
419
690
|
/**
|
|
420
|
-
*
|
|
421
|
-
*
|
|
691
|
+
* Set this property to a function during your panel's
|
|
692
|
+
* {@link ExtensionPanelRegistration.initPanel | initialization}.
|
|
693
|
+
*
|
|
694
|
+
* Foxglove will run `context.onRender` whenever your panel needs to re-render during playback.
|
|
695
|
+
* The function accepts `renderState` and a `done` callback as its arguments. Render events occur
|
|
696
|
+
* frequently (60hz, 30hz, etc).
|
|
422
697
|
*
|
|
423
|
-
*
|
|
698
|
+
* **Note**: Your `onRender` function **must** call `done` after rendering to indicate that the
|
|
699
|
+
* panel is ready to render the next set of data. The exact placement of this `done` invocation
|
|
700
|
+
* will vary between frameworks and different extensions' logic.
|
|
701
|
+
*
|
|
702
|
+
* ```ts
|
|
703
|
+
* context.onRender = (renderState, done) => {
|
|
704
|
+
* // Render your UI updates with fields from RenderState
|
|
705
|
+
*
|
|
706
|
+
* // Call done when you've rendered all the UI for this renderState.
|
|
707
|
+
* // If your UI framework delays rendering, call done when rendering has actually happened.
|
|
708
|
+
* done();
|
|
709
|
+
* };
|
|
710
|
+
* ```
|
|
424
711
|
*/
|
|
425
712
|
onRender?: (renderState: Immutable<RenderState>, done: () => void) => void;
|
|
426
713
|
|
|
427
714
|
/**
|
|
428
|
-
*
|
|
429
|
-
*
|
|
715
|
+
* Call the `updatePanelSettingsEditor` method on your panel's {@link PanelExtensionContext}
|
|
716
|
+
* instance to define or update its settings.
|
|
717
|
+
*
|
|
718
|
+
* ```ts
|
|
719
|
+
* const panelSettings: SettingsTree = {
|
|
720
|
+
* nodes: { ... },
|
|
721
|
+
* actionHandler: (action: SettingsTreeAction) => { ... }
|
|
722
|
+
* };
|
|
723
|
+
*
|
|
724
|
+
* context.updatePanelSettingsEditor(panelSettings);
|
|
725
|
+
* ```
|
|
726
|
+
*
|
|
727
|
+
* The `settings` argument must be a valid {@link SettingsTree} and include 2 mandatory properties
|
|
728
|
+
* – `nodes` and `actionHandler`:
|
|
729
|
+
*
|
|
730
|
+
* - `nodes` - Hierarchical structure where each node can contain input fields, display fields, or
|
|
731
|
+
* even other nodes
|
|
732
|
+
* - `actionHandler` - Function that is invoked when the user interacts with the settings UI;
|
|
733
|
+
* contains logic to process the interactions and update the panel or settings tree
|
|
734
|
+
*
|
|
735
|
+
* It can also include the following optional properties:
|
|
736
|
+
*
|
|
737
|
+
* - `enableFilter` – Whether the settings should show the filter control
|
|
738
|
+
* - `focusedPath` – Node to scroll to (transient one-time effect)
|
|
739
|
+
*
|
|
740
|
+
* The example tree below has a `title` text input field inside a `General` section along with an
|
|
741
|
+
* `actionHandler` to respond to updates for the `title` field.
|
|
742
|
+
*
|
|
743
|
+
* ```ts
|
|
744
|
+
* const panelSettings: SettingsTree = {
|
|
745
|
+
* nodes: {
|
|
746
|
+
* general: {
|
|
747
|
+
* label: "General",
|
|
748
|
+
* fields: {
|
|
749
|
+
* title: "{
|
|
750
|
+
* label: "Title",
|
|
751
|
+
* input: "string",
|
|
752
|
+
* // `panelTitle` refers to a value in your extension panel's config
|
|
753
|
+
* value: panelTitle,
|
|
754
|
+
* },
|
|
755
|
+
* },
|
|
756
|
+
* },
|
|
757
|
+
* },
|
|
758
|
+
* actionHandler: (action: SettingsTreeAction) => {
|
|
759
|
+
* switch (action.action) {
|
|
760
|
+
* case "perform-node-action":
|
|
761
|
+
* // Handle user-defined actions for nodes in the settings tree
|
|
762
|
+
* break;
|
|
763
|
+
* case "update":
|
|
764
|
+
* if (action.payload.path[0] === "general" && action.payload.path[1] === "title") {
|
|
765
|
+
* // Read action.payload.value for the new panel title value
|
|
766
|
+
* panelTitle = action.payload.value;
|
|
767
|
+
*
|
|
768
|
+
* // Update your panel's state accordingly
|
|
769
|
+
* }
|
|
770
|
+
* break;
|
|
771
|
+
* }
|
|
772
|
+
* },
|
|
773
|
+
* }
|
|
774
|
+
*
|
|
775
|
+
* context.updatePanelSettingsEditor(panelSettings);
|
|
776
|
+
* ```
|
|
777
|
+
*
|
|
778
|
+
* #### `SettingsTreeAction`
|
|
779
|
+
*
|
|
780
|
+
* A {@link SettingsTreeAction} describes how the settings UI should update when a user interacts
|
|
781
|
+
* with its fields.
|
|
782
|
+
*
|
|
783
|
+
* Each `SettingsTreeAction` has a `payload` with a `path` to the settings field to update (e.g.
|
|
784
|
+
* `["general", "title"]`).
|
|
785
|
+
*
|
|
786
|
+
* The `update` action corresponds to a user setting a new value for a field (e.g. "My new
|
|
787
|
+
* title").
|
|
788
|
+
*
|
|
789
|
+
* #### Special node properties
|
|
790
|
+
*
|
|
791
|
+
* There are two special {@link SettingsTreeNode} properties, `label` and `visibility`. The value
|
|
792
|
+
* you specify for `label` will control the label displayed in the settings editor. If you set the
|
|
793
|
+
* `renamable` node property to `true`, the user can edit the node `label` – you will receive a
|
|
794
|
+
* `SettingsTreeAction` of `update` with a path ending in `label`.
|
|
795
|
+
*
|
|
796
|
+
* In addition, if you specify a boolean value for `visibility` of the node then the settings
|
|
797
|
+
* editor will provide a button to toggle the visibility of the node and you will receive an
|
|
798
|
+
* `update` action with `visibility` as the final element in the path.
|
|
799
|
+
*
|
|
800
|
+
* For an example of how to use these special properties, check out the [panel settings example
|
|
801
|
+
* extension](https://github.com/foxglove/create-foxglove-extension/tree/main/examples/panel-settings).
|
|
802
|
+
*
|
|
803
|
+
* #### Input types
|
|
804
|
+
*
|
|
805
|
+
* In addition to the `string` input type in the example above, the panel API provides a wide
|
|
806
|
+
* array of types for your extension panel input fields.
|
|
807
|
+
*
|
|
808
|
+
* Each input type has different properties that you can configure:
|
|
809
|
+
*
|
|
810
|
+
* - `autocomplete`
|
|
811
|
+
* - `boolean`
|
|
812
|
+
* - `rgb`
|
|
813
|
+
* - `rgba`
|
|
814
|
+
* - `gradient`
|
|
815
|
+
* - `messagepath`
|
|
816
|
+
* - `select`
|
|
817
|
+
* - `string`
|
|
818
|
+
* - `toggle`
|
|
819
|
+
* - `vec3`
|
|
820
|
+
* - `vec2`
|
|
430
821
|
*/
|
|
431
822
|
updatePanelSettingsEditor(settings: Immutable<SettingsTree>): void;
|
|
432
823
|
|
|
433
824
|
/**
|
|
434
|
-
*
|
|
435
|
-
*
|
|
825
|
+
* Use `context.setDefaultPanelTitle` to override a panel's default title. Users can always
|
|
826
|
+
* override the default title by editing it manually. If no override or default title is set, the
|
|
827
|
+
* panel will simply display its type (e.g. "Image").
|
|
828
|
+
*
|
|
829
|
+
* ```ts
|
|
830
|
+
* // Override the default panel title
|
|
831
|
+
* context.setDefaultPanelTitle(`Plot of ${config.topicName}`);
|
|
832
|
+
* ```
|
|
436
833
|
*/
|
|
437
834
|
setDefaultPanelTitle(defaultTitle: string | undefined): void;
|
|
438
835
|
/**
|
|
439
|
-
* NOTE: UNSTABLE API SUBJECT TO CHANGE
|
|
440
|
-
*
|
|
441
836
|
* Subscribe to receive the entire time range of messages for a given topic for the current data source.
|
|
442
837
|
*
|
|
443
|
-
* See
|
|
838
|
+
* See {@link SubscribeMessageRangeArgs} for more information on behavior.
|
|
444
839
|
*
|
|
445
|
-
* Note: This will not read messages for live sources, like
|
|
446
|
-
* native. For those messages you will still need to use `context.subscribe()` and
|
|
447
|
-
* watch("currentFrame")
|
|
840
|
+
* Note: This will not read messages for live sources, like foxglove_bridge, rosbridge, or ROS 1
|
|
841
|
+
* native connections. For those messages you will still need to use `context.subscribe()` and
|
|
842
|
+
* `watch("currentFrame")`.
|
|
448
843
|
*
|
|
449
844
|
* @returns A function that will unsubscribe from the topic, cancel the active async iterator,
|
|
450
|
-
* and prevent
|
|
845
|
+
* and prevent {@link SubscribeMessageRangeArgs.onNewRangeIterator | onNewRangeIterator} from being called again.
|
|
846
|
+
*/
|
|
847
|
+
subscribeMessageRange?: (args: SubscribeMessageRangeArgs) => () => void;
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* @deprecated Renamed to `subscribeMessageRange`. Please use that method instead.
|
|
451
851
|
*/
|
|
452
852
|
UNSTABLE_subscribeMessageRange?: (args: SubscribeMessageRangeArgs) => () => void;
|
|
453
853
|
};
|
|
454
854
|
|
|
855
|
+
/**
|
|
856
|
+
* This type represents the arguments you pass to {@link ExtensionContext.registerPanel}.
|
|
857
|
+
*
|
|
858
|
+
* @category Custom panels
|
|
859
|
+
*/
|
|
455
860
|
export type ExtensionPanelRegistration = {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
861
|
+
/**
|
|
862
|
+
* Unique name of the panel within your extension
|
|
863
|
+
*
|
|
864
|
+
* NOTE: Panel names within your extension must be unique. The panel name identifies this panel
|
|
865
|
+
* within a layout. Changing the panel name will cause layouts using the old name unable to load
|
|
866
|
+
* your panel.
|
|
867
|
+
*/
|
|
461
868
|
name: string;
|
|
462
869
|
|
|
463
870
|
/**
|
|
464
871
|
* This function is invoked when your panel is initialized
|
|
465
|
-
*
|
|
872
|
+
*
|
|
873
|
+
* @returns (optional) A function which will be called when the panel is removed or replaced.
|
|
874
|
+
* Perform any cleanup logic here to gracefully tear down your panel.
|
|
466
875
|
*/
|
|
467
876
|
initPanel: (context: PanelExtensionContext) => void | (() => void);
|
|
468
877
|
};
|
|
469
878
|
|
|
879
|
+
/**
|
|
880
|
+
* This type represents the arguments you pass to {@link ExtensionContext.registerMessageConverter}.
|
|
881
|
+
*
|
|
882
|
+
* @category Message converters
|
|
883
|
+
*/
|
|
470
884
|
export type RegisterMessageConverterArgs<Src> = {
|
|
471
885
|
fromSchemaName: string;
|
|
472
886
|
toSchemaName: string;
|
|
473
887
|
converter: (msg: Src, event: Immutable<MessageEvent<Src>>) => unknown;
|
|
474
888
|
};
|
|
475
889
|
|
|
476
|
-
|
|
477
|
-
type
|
|
890
|
+
/** @category Topic aliases */
|
|
891
|
+
export type BaseTopic = { name: string; schemaName?: string };
|
|
892
|
+
/** @category Topic aliases */
|
|
893
|
+
export type TopicAlias = { name: string; sourceTopicName: string };
|
|
478
894
|
|
|
479
895
|
/**
|
|
480
|
-
*
|
|
481
|
-
* a list of aliased topics.
|
|
896
|
+
* A TopicAliasFunction takes a list of data source topics and variables and outputs
|
|
897
|
+
* a list of aliased topics. Register this function using {@link ExtensionContext.registerTopicAliases}.
|
|
898
|
+
*
|
|
899
|
+
* @category Topic aliases
|
|
482
900
|
*/
|
|
483
901
|
export type TopicAliasFunction = (
|
|
484
902
|
args: Immutable<{
|
|
@@ -487,41 +905,116 @@ export type TopicAliasFunction = (
|
|
|
487
905
|
}>,
|
|
488
906
|
) => TopicAlias[];
|
|
489
907
|
|
|
908
|
+
/**
|
|
909
|
+
* The {@link ExtensionModule.activate | activate} function's first argument is an
|
|
910
|
+
* `ExtensionContext` — this context allows you to extend Foxglove for your custom workflows.
|
|
911
|
+
*
|
|
912
|
+
* ```typescript
|
|
913
|
+
* export function activate(extensionContext: ExtensionContext) {
|
|
914
|
+
* // ... call methods on the extensionContext to extend Foxglove
|
|
915
|
+
* }
|
|
916
|
+
* ```
|
|
917
|
+
*
|
|
918
|
+
* @category Entry point
|
|
919
|
+
*/
|
|
490
920
|
export interface ExtensionContext {
|
|
491
|
-
/**
|
|
921
|
+
/**
|
|
922
|
+
* @deprecated This field is no longer used.
|
|
923
|
+
* @hidden
|
|
924
|
+
*/
|
|
492
925
|
readonly mode: "production" | "development" | "test";
|
|
493
926
|
|
|
927
|
+
/**
|
|
928
|
+
* `registerPanel` adds a new panel to the Foxglove interface. To register a panel you provide a
|
|
929
|
+
* `name` and an `initPanel` function.
|
|
930
|
+
*
|
|
931
|
+
* The `initPanel` function accepts a {@link PanelExtensionContext} argument, which contains
|
|
932
|
+
* properties and methods for accessing panel data and rendering UI updates. It also returns an
|
|
933
|
+
* optional cleanup function to run when the extension `panelElement` unmounts.
|
|
934
|
+
*
|
|
935
|
+
* See the [Creating a custom
|
|
936
|
+
* panel](https://docs.foxglove.dev/docs/visualization/extensions/guides/create-custom-panel)
|
|
937
|
+
* guide for more details.
|
|
938
|
+
*/
|
|
494
939
|
registerPanel(params: ExtensionPanelRegistration): void;
|
|
495
940
|
|
|
496
941
|
/**
|
|
497
|
-
*
|
|
942
|
+
* `registerMessageConverter` registers a function to convert messages from one schema to another.
|
|
943
|
+
*
|
|
944
|
+
* Message converters allow you to leverage Foxglove's built-in visualization panels by
|
|
945
|
+
* transforming messages to adhere to Foxglove-supported schemas — for example, you can convert
|
|
946
|
+
* your custom GPS messages to
|
|
947
|
+
* [`foxglove.LocationFix`](https://docs.foxglove.dev/docs/visualization/message-schemas/location-fix)
|
|
948
|
+
* messages for visualization in the [Map
|
|
949
|
+
* panel](https://docs.foxglove.dev/docs/visualization/panels/map).
|
|
498
950
|
*
|
|
499
|
-
*
|
|
500
|
-
*
|
|
501
|
-
*
|
|
951
|
+
* Whenever a panel subscribes to a topic with the
|
|
952
|
+
* [`convertTo`](https://docs.foxglove.dev/docs/visualization/extensions/api/panel#message-converters)
|
|
953
|
+
* option, the converter function runs on the original message and outputs the converted message,
|
|
954
|
+
* which it then provides it to the panel. If the function returns `undefined`, the output is
|
|
955
|
+
* ignored, and no message is provided to the panel. This is useful if you want to selectively
|
|
956
|
+
* output converted messages depending on the input messages' contents.
|
|
502
957
|
*
|
|
503
|
-
*
|
|
504
|
-
* message
|
|
505
|
-
*
|
|
958
|
+
* See the [Creating a message
|
|
959
|
+
* converter](https://docs.foxglove.dev/docs/visualization/extensions/guides/create-message-converter)
|
|
960
|
+
* guide for more details.
|
|
961
|
+
|
|
506
962
|
*/
|
|
507
963
|
registerMessageConverter<Src>(args: RegisterMessageConverterArgs<Src>): void;
|
|
508
964
|
|
|
509
965
|
/**
|
|
510
|
-
*
|
|
511
|
-
*
|
|
512
|
-
*
|
|
966
|
+
* `registerTopicAliases` registers a function to compute topic aliases. The provided alias
|
|
967
|
+
* function should accept an argument with two fields – `topics` with the data source's original
|
|
968
|
+
* topics and `globalVariables` with the current layout's variables – and return a list of aliased
|
|
969
|
+
* topics.
|
|
970
|
+
*
|
|
971
|
+
* Your alias function runs whenever there are changes to the data source topics or variables. Any
|
|
972
|
+
* aliases it returns are added to the data source topics (replacing any previously returned
|
|
973
|
+
* aliases) and available for subscribing or use within message paths as if they were real topics.
|
|
513
974
|
*/
|
|
514
975
|
registerTopicAliases(aliasFunction: TopicAliasFunction): void;
|
|
515
976
|
}
|
|
516
977
|
|
|
978
|
+
/**
|
|
979
|
+
* @inline
|
|
980
|
+
* @hidden
|
|
981
|
+
*/
|
|
517
982
|
export type ExtensionActivate = (extensionContext: ExtensionContext) => void;
|
|
518
983
|
|
|
519
|
-
|
|
520
|
-
|
|
984
|
+
/**
|
|
985
|
+
* ExtensionModule describes the interface your extension module must export. This typically corresponds to your `index.ts` file.
|
|
986
|
+
*
|
|
987
|
+
* You may use either a `default` export or named export syntax:
|
|
988
|
+
*
|
|
989
|
+
* ```typescript
|
|
990
|
+
* export function activate(context: ExtensionContext) {
|
|
991
|
+
* // ... call methods on the extensionContext to extend Foxglove
|
|
992
|
+
* }
|
|
993
|
+
* ```
|
|
994
|
+
*
|
|
995
|
+
* ```typescript
|
|
996
|
+
* function activate(context: ExtensionContext) {
|
|
997
|
+
* // ... call methods on the extensionContext to extend Foxglove
|
|
998
|
+
* }
|
|
999
|
+
* export default { activate };
|
|
1000
|
+
* ```
|
|
1001
|
+
*
|
|
1002
|
+
* @category Entry point
|
|
1003
|
+
*/
|
|
521
1004
|
export interface ExtensionModule {
|
|
1005
|
+
/**
|
|
1006
|
+
* This function will be called when your extension is loaded. In this function, you can register
|
|
1007
|
+
* your custom panels or other types of extension features.
|
|
1008
|
+
*/
|
|
522
1009
|
activate: ExtensionActivate;
|
|
523
1010
|
}
|
|
524
1011
|
|
|
1012
|
+
/**
|
|
1013
|
+
* Icons that can be displayed in the settings tree. Most icon names come from the Material Design
|
|
1014
|
+
* icon set, but the exact icons displayed may change in the future.
|
|
1015
|
+
*
|
|
1016
|
+
* @category Custom panels
|
|
1017
|
+
*/
|
|
525
1018
|
export type SettingsIcon =
|
|
526
1019
|
| "Add"
|
|
527
1020
|
| "Addchart"
|
|
@@ -566,6 +1059,8 @@ export type SettingsIcon =
|
|
|
566
1059
|
/**
|
|
567
1060
|
* A settings tree field specifies the input type and the value of a field
|
|
568
1061
|
* in the settings editor.
|
|
1062
|
+
*
|
|
1063
|
+
* @category Custom panels
|
|
569
1064
|
*/
|
|
570
1065
|
export type SettingsTreeFieldValue =
|
|
571
1066
|
| {
|
|
@@ -678,6 +1173,12 @@ export type SettingsTreeFieldValue =
|
|
|
678
1173
|
min?: number;
|
|
679
1174
|
};
|
|
680
1175
|
|
|
1176
|
+
/**
|
|
1177
|
+
* A settings tree field specifies the input type and the value of a field
|
|
1178
|
+
* in the settings editor.
|
|
1179
|
+
*
|
|
1180
|
+
* @category Custom panels
|
|
1181
|
+
*/
|
|
681
1182
|
export type SettingsTreeField = SettingsTreeFieldValue & {
|
|
682
1183
|
/**
|
|
683
1184
|
* True if the field is disabled.
|
|
@@ -705,10 +1206,21 @@ export type SettingsTreeField = SettingsTreeFieldValue & {
|
|
|
705
1206
|
error?: string;
|
|
706
1207
|
};
|
|
707
1208
|
|
|
1209
|
+
/**
|
|
1210
|
+
* @category Custom panels
|
|
1211
|
+
*/
|
|
708
1212
|
export type SettingsTreeFields = Record<string, undefined | SettingsTreeField>;
|
|
709
1213
|
|
|
1214
|
+
/**
|
|
1215
|
+
* @category Custom panels
|
|
1216
|
+
*/
|
|
710
1217
|
export type SettingsTreeChildren = Record<string, undefined | SettingsTreeNode>;
|
|
711
1218
|
|
|
1219
|
+
/**
|
|
1220
|
+
* An action included in the action menu for a settings node.
|
|
1221
|
+
*
|
|
1222
|
+
* @category Custom panels
|
|
1223
|
+
*/
|
|
712
1224
|
export type SettingsTreeNodeActionItem = {
|
|
713
1225
|
type: "action";
|
|
714
1226
|
|
|
@@ -735,13 +1247,23 @@ export type SettingsTreeNodeActionItem = {
|
|
|
735
1247
|
display?: "menu" | "inline";
|
|
736
1248
|
};
|
|
737
1249
|
|
|
1250
|
+
/**
|
|
1251
|
+
* @category Custom panels
|
|
1252
|
+
*/
|
|
738
1253
|
export type SettingsTreeNodeActionDivider = { type: "divider" };
|
|
739
1254
|
|
|
740
1255
|
/**
|
|
741
1256
|
* An action included in the action menu for a settings node.
|
|
1257
|
+
*
|
|
1258
|
+
* @category Custom panels
|
|
742
1259
|
*/
|
|
743
1260
|
export type SettingsTreeNodeAction = SettingsTreeNodeActionItem | SettingsTreeNodeActionDivider;
|
|
744
1261
|
|
|
1262
|
+
/**
|
|
1263
|
+
* A node represents a single item or group of items in the settings tree.
|
|
1264
|
+
*
|
|
1265
|
+
* @category Custom panels
|
|
1266
|
+
*/
|
|
745
1267
|
export type SettingsTreeNode = {
|
|
746
1268
|
/**
|
|
747
1269
|
* An array of actions that can be performed on this node.
|
|
@@ -816,6 +1338,8 @@ type DistributivePick<T, K extends keyof T> = T extends unknown ? Pick<T, K> : n
|
|
|
816
1338
|
/**
|
|
817
1339
|
* Represents actions that can be dispatched to source of the SettingsTree to implement
|
|
818
1340
|
* edits and updates.
|
|
1341
|
+
*
|
|
1342
|
+
* @category Custom panels
|
|
819
1343
|
*/
|
|
820
1344
|
export type SettingsTreeAction =
|
|
821
1345
|
| {
|
|
@@ -830,6 +1354,10 @@ export type SettingsTreeAction =
|
|
|
830
1354
|
payload: { id: string; path: readonly string[] };
|
|
831
1355
|
};
|
|
832
1356
|
|
|
1357
|
+
/**
|
|
1358
|
+
* @inline
|
|
1359
|
+
* @hidden
|
|
1360
|
+
*/
|
|
833
1361
|
export type SettingsTreeNodes = Record<string, undefined | SettingsTreeNode>;
|
|
834
1362
|
|
|
835
1363
|
/**
|
|
@@ -841,6 +1369,7 @@ export type SettingsTreeNodes = Record<string, undefined | SettingsTreeNode>;
|
|
|
841
1369
|
*
|
|
842
1370
|
* For example, for the following tree:
|
|
843
1371
|
*
|
|
1372
|
+
* ```json
|
|
844
1373
|
* root: {
|
|
845
1374
|
* children: {
|
|
846
1375
|
* a: {
|
|
@@ -858,12 +1387,15 @@ export type SettingsTreeNodes = Record<string, undefined | SettingsTreeNode>;
|
|
|
858
1387
|
* },
|
|
859
1388
|
* },
|
|
860
1389
|
* },
|
|
1390
|
+
* ```
|
|
861
1391
|
*
|
|
862
|
-
* the path to the node at b would be ["a", "b"] and the path to the toggleMe
|
|
863
|
-
* field would be ["a", "b", "toggleMe"]
|
|
1392
|
+
* the path to the node at b would be `["a", "b"]` and the path to the toggleMe
|
|
1393
|
+
* field would be `["a", "b", "toggleMe"]`. These paths are used in the
|
|
864
1394
|
* actionHandler, which responds to updates to values in the tree, and also in
|
|
865
1395
|
* the focusedPath, which is used to focus the editor UI at a particular node
|
|
866
1396
|
* in the tree.
|
|
1397
|
+
*
|
|
1398
|
+
* @category Custom panels
|
|
867
1399
|
*/
|
|
868
1400
|
export type SettingsTree = {
|
|
869
1401
|
/**
|