@foxglove/extension 2.24.0 → 2.25.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/experimental.ts +135 -0
- package/src/index.ts +2 -1422
- package/src/stable.ts +1428 -0
package/src/index.ts
CHANGED
|
@@ -1,1423 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export * from "./stable";
|
|
3
2
|
export type { Immutable } from "./immutable";
|
|
4
|
-
|
|
5
|
-
/** Valid types for parameter data (such as rosparams) */
|
|
6
|
-
export type ParameterValue =
|
|
7
|
-
| undefined
|
|
8
|
-
| boolean
|
|
9
|
-
| number
|
|
10
|
-
| string
|
|
11
|
-
| Date
|
|
12
|
-
| Uint8Array
|
|
13
|
-
| ParameterValue[]
|
|
14
|
-
| { [key: string]: ParameterValue };
|
|
15
|
-
|
|
16
|
-
/** Valid types for [variables](https://docs.foxglove.dev/docs/visualization/variables) */
|
|
17
|
-
export type VariableValue =
|
|
18
|
-
| undefined
|
|
19
|
-
| boolean
|
|
20
|
-
| number
|
|
21
|
-
| string
|
|
22
|
-
| VariableValue[]
|
|
23
|
-
| { [key: string]: VariableValue };
|
|
24
|
-
|
|
25
|
-
export type VariableStruct = { [key: string]: VariableValue };
|
|
26
|
-
|
|
27
|
-
/** Valid types for application settings */
|
|
28
|
-
export type AppSettingValue = string | number | boolean | undefined;
|
|
29
|
-
|
|
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 = {
|
|
38
|
-
sec: number;
|
|
39
|
-
nsec: number;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* A Topic is a named channel of messages.
|
|
44
|
-
*/
|
|
45
|
-
export type Topic = {
|
|
46
|
-
/**
|
|
47
|
-
* topic name i.e. "/some/topic"
|
|
48
|
-
*/
|
|
49
|
-
name: string;
|
|
50
|
-
/**
|
|
51
|
-
* @deprecated Renamed to `schemaName`. `datatype` will be removed in a future release.
|
|
52
|
-
*/
|
|
53
|
-
datatype: string;
|
|
54
|
-
/**
|
|
55
|
-
* The schema name is an identifier for the types of messages on this topic. Typically this is the
|
|
56
|
-
* fully-qualified name of the message schema. The fully-qualified name depends on the data source
|
|
57
|
-
* and data loaded by the data source.
|
|
58
|
-
*
|
|
59
|
-
* i.e. `package.Message` in protobuf-like serialization or `pkg/Msg` in ROS systems.
|
|
60
|
-
*/
|
|
61
|
-
schemaName: string;
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Lists any additional schema names available for subscribers on the topic. When subscribing to
|
|
65
|
-
* a topic, the panel can request messages be automatically converted from schemaName into one
|
|
66
|
-
* of the convertibleTo schemas using the {@link Subscription.convertTo} option.
|
|
67
|
-
*/
|
|
68
|
-
convertibleTo?: readonly string[];
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* A single subscription passed to {@link PanelExtensionContext.subscribe}.
|
|
73
|
-
*
|
|
74
|
-
* @category Custom panels
|
|
75
|
-
*/
|
|
76
|
-
export type Subscription = {
|
|
77
|
-
topic: string;
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* If a topic has additional schema names, specifying a schema name will convert messages on that
|
|
81
|
-
* topic to the convertTo schema using a registered message converter. MessageEvents for the
|
|
82
|
-
* subscription will contain the converted message and an originalMessageEvent field with the
|
|
83
|
-
* original message event.
|
|
84
|
-
*/
|
|
85
|
-
convertTo?: string;
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Setting preload to _true_ hints to the data source that it should attempt to load all available
|
|
89
|
-
* messages for the topic. The default behavior is to only load messages for the current frame.
|
|
90
|
-
*
|
|
91
|
-
* **Only** topics with `preload: true` are available in the `allFrames` render state.
|
|
92
|
-
*
|
|
93
|
-
* @deprecated Please use {@link PanelExtensionContext.subscribeMessageRange} instead.
|
|
94
|
-
*/
|
|
95
|
-
preload?: boolean;
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
/**
|
|
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.
|
|
102
|
-
*/
|
|
103
|
-
export type MessageEvent<T = unknown> = {
|
|
104
|
-
/** The topic name this message was received on, i.e. "/some/topic" */
|
|
105
|
-
topic: string;
|
|
106
|
-
/**
|
|
107
|
-
* The schema name is an identifier for the schema of the message within the message event.
|
|
108
|
-
*/
|
|
109
|
-
schemaName: string;
|
|
110
|
-
/**
|
|
111
|
-
* The time in nanoseconds this message was received. This may be set by the
|
|
112
|
-
* local system clock or the data source, depending on the data source used
|
|
113
|
-
* and whether time is simulated via a /clock topic or similar mechanism.
|
|
114
|
-
* The timestamp is often nanoseconds since the UNIX epoch, but may be
|
|
115
|
-
* relative to another event such as system boot time or simulation start
|
|
116
|
-
* time depending on the context.
|
|
117
|
-
*/
|
|
118
|
-
receiveTime: Time;
|
|
119
|
-
/**
|
|
120
|
-
* The time in nanoseconds this message was originally published. This is
|
|
121
|
-
* only available for some data sources. The timestamp is often nanoseconds
|
|
122
|
-
* since the UNIX epoch, but may be relative to another event such as system
|
|
123
|
-
* boot time or simulation start time depending on the context.
|
|
124
|
-
*/
|
|
125
|
-
publishTime?: Time;
|
|
126
|
-
/** The deserialized message as a JavaScript object. */
|
|
127
|
-
message: T;
|
|
128
|
-
/**
|
|
129
|
-
* The approximate size of this message event in its deserialized form. This can be
|
|
130
|
-
* useful for statistics tracking and cache eviction.
|
|
131
|
-
*/
|
|
132
|
-
sizeInBytes: number;
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* When subscribing to a topic using the `convertTo` option, the message event `message`
|
|
136
|
-
* contains the converted message and the `originalMessageEvent` field contains the original
|
|
137
|
-
* un-converted message event.
|
|
138
|
-
*/
|
|
139
|
-
originalMessageEvent?: MessageEvent;
|
|
140
|
-
};
|
|
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
|
-
*/
|
|
147
|
-
export interface LayoutActions {
|
|
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
|
-
*/
|
|
169
|
-
addPanel(params: {
|
|
170
|
-
/**
|
|
171
|
-
* Where to position the panel. Currently, only "sibling" is supported which indicates the
|
|
172
|
-
* new panel will be adjacent to the calling panel.
|
|
173
|
-
*/
|
|
174
|
-
position: "sibling";
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* The type of panel to open. For extension panels, this `"extensionName.panelName"` where
|
|
178
|
-
* extensionName is the `name` field from the extension's package.json, and panelName is the
|
|
179
|
-
* name provided to `registerPanel()`.
|
|
180
|
-
*/
|
|
181
|
-
type: string;
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Whether to update an existing sibling panel of the same type, if it already exists. If false
|
|
185
|
-
* or omitted, a new panel will always be added.
|
|
186
|
-
*
|
|
187
|
-
* @deprecated This parameter is only supported for built-in panels at this time.
|
|
188
|
-
*/
|
|
189
|
-
updateIfExists?: boolean;
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* A function that returns the state for the new panel. If updating an existing panel, the
|
|
193
|
-
* existing state will be passed in.
|
|
194
|
-
* @see `updateIfExists`
|
|
195
|
-
*/
|
|
196
|
-
getState(existingState?: unknown): unknown;
|
|
197
|
-
}): void;
|
|
198
|
-
}
|
|
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
|
-
*/
|
|
213
|
-
export type RenderState = {
|
|
214
|
-
/**
|
|
215
|
-
* The latest messages for the current render frame. These are new messages since the last render frame.
|
|
216
|
-
*/
|
|
217
|
-
currentFrame?: MessageEvent[];
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* True if the data source performed a seek. This indicates that some data may have been skipped
|
|
221
|
-
* (never appeared in the `currentFrame`), so panels should clear out any stale state to avoid
|
|
222
|
-
* displaying incorrect data.
|
|
223
|
-
*/
|
|
224
|
-
didSeek?: boolean;
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* All available messages. Best-effort list of all available messages.
|
|
228
|
-
*
|
|
229
|
-
* @deprecated Please use {@link PanelExtensionContext.subscribeMessageRange} instead.
|
|
230
|
-
*/
|
|
231
|
-
allFrames?: MessageEvent[];
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Map of current parameter values. Parameters are key/value pairs associated with the data
|
|
235
|
-
* source, and may not be available for all data sources. For example, ROS 1 live connections
|
|
236
|
-
* support parameters through the Parameter Server <http://wiki.ros.org/Parameter%20Server>.
|
|
237
|
-
*/
|
|
238
|
-
parameters?: Map<string, ParameterValue>;
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* Transient panel state shared between panels of the same type. This can be any data a
|
|
242
|
-
* panel author wishes to share between panels.
|
|
243
|
-
*/
|
|
244
|
-
sharedPanelState?: Record<string, unknown>;
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Map of current Studio variables. Variables are key/value pairs that are globally accessible
|
|
248
|
-
* to panels and scripts in the current layout. See
|
|
249
|
-
* <https://docs.foxglove.dev/docs/visualization/variables> for more information.
|
|
250
|
-
*/
|
|
251
|
-
variables?: Map<string, VariableValue>;
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* List of available topics. This list includes subscribed and unsubscribed topics.
|
|
255
|
-
*/
|
|
256
|
-
topics?: Topic[];
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* A timestamp value indicating the current playback time.
|
|
260
|
-
*/
|
|
261
|
-
currentTime?: Time;
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* The start timestamp of the playback range for the current data source. For offline files it
|
|
265
|
-
* is expected to be present. For live connections, the start time may or may not be present
|
|
266
|
-
* depending on the data source.
|
|
267
|
-
*/
|
|
268
|
-
startTime?: Time;
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* The end timestamp of the playback range for the current data source. For offline files it
|
|
272
|
-
* is expected to be present. For live connections, the end time may or may not be present
|
|
273
|
-
* depending on the data source.
|
|
274
|
-
*/
|
|
275
|
-
endTime?: Time;
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* A seconds value indicating a preview time. The preview time is set when a user hovers
|
|
279
|
-
* over the seek bar or when a panel sets the preview time explicitly. The preview time
|
|
280
|
-
* is a seconds value within the playback range.
|
|
281
|
-
*
|
|
282
|
-
* i.e. A plot panel may set the preview time when a user is hovering over the plot to signal
|
|
283
|
-
* to other panels where the user is currently hovering and allow them to render accordingly.
|
|
284
|
-
*/
|
|
285
|
-
previewTime?: number | undefined;
|
|
286
|
-
|
|
287
|
-
/** The color scheme currently in use throughout the app. */
|
|
288
|
-
colorScheme?: "dark" | "light";
|
|
289
|
-
|
|
290
|
-
/** Application settings. This will only contain keys/values that were subscribed to using {@link @PanelExtensionContext.subscribeAppSettings} */
|
|
291
|
-
appSettings?: Map<string, AppSettingValue>;
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* This type represents the arguments you pass to {@link PanelExtensionContext.subscribeMessageRange}.
|
|
296
|
-
*
|
|
297
|
-
* @category Custom panels
|
|
298
|
-
*/
|
|
299
|
-
export type SubscribeMessageRangeArgs = {
|
|
300
|
-
/**
|
|
301
|
-
* Topic to be subscribed to.
|
|
302
|
-
*/
|
|
303
|
-
topic: string;
|
|
304
|
-
/**
|
|
305
|
-
* Convert messages to this schema before delivering to the subscriber.
|
|
306
|
-
*
|
|
307
|
-
* MessageEvents for the subscription will contain the converted message and an
|
|
308
|
-
* `originalMessageEvent` field with the original message event. If no `convertTo` schema is
|
|
309
|
-
* specified, then no message converters will be used. If no message converter exists for
|
|
310
|
-
* converting the original schema to the `convertTo` schema, then no messages are delivered for
|
|
311
|
-
* this subscription.
|
|
312
|
-
*/
|
|
313
|
-
convertTo?: string;
|
|
314
|
-
/**
|
|
315
|
-
* `onNewRangeIterator` is a function that receives an async iterable when there is message data available on
|
|
316
|
-
* the subscription.
|
|
317
|
-
*
|
|
318
|
-
* To read messages, your function should iterate through the provided async iterable. Each item
|
|
319
|
-
* of the iterable is a batch of message events for the subscription's topic. These batches and
|
|
320
|
-
* messages are in _log time_ order. When there are no more messages to read the iterator will
|
|
321
|
-
* finish.
|
|
322
|
-
*
|
|
323
|
-
* ```typescript
|
|
324
|
-
* async function onNewRangeIterator(batchIterator) {
|
|
325
|
-
* for await (const batch of batchIterator) {
|
|
326
|
-
* //...
|
|
327
|
-
* }
|
|
328
|
-
* }
|
|
329
|
-
* ```
|
|
330
|
-
*
|
|
331
|
-
* `onNewRangeIterator` is called again when the upstream topic data changes. I.E subscribing to a
|
|
332
|
-
* user-script output topic and the user script changes, or subscribing to an aliased topic and
|
|
333
|
-
* the alias changes. When topic data changes, the previous iterator will end, and its data is no
|
|
334
|
-
* longer valid. When `onNewRangeIterator` is called, you should discard previously received data.
|
|
335
|
-
*
|
|
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
|
|
338
|
-
* for user visibility.
|
|
339
|
-
*/
|
|
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>;
|
|
346
|
-
};
|
|
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
|
-
*/
|
|
365
|
-
export type PanelExtensionContext = {
|
|
366
|
-
/**
|
|
367
|
-
* The root element for the panel. Add your panel elements as children under this element.
|
|
368
|
-
*/
|
|
369
|
-
readonly panelElement: HTMLDivElement;
|
|
370
|
-
|
|
371
|
-
/**
|
|
372
|
-
* Initial panel state
|
|
373
|
-
*/
|
|
374
|
-
readonly initialState: unknown;
|
|
375
|
-
|
|
376
|
-
/** Actions the panel may perform related to the user's current layout. See {@link LayoutActions} for details. */
|
|
377
|
-
readonly layout: LayoutActions;
|
|
378
|
-
|
|
379
|
-
/**
|
|
380
|
-
* Identifies the semantics of the data being played back, such as which topics or parameters
|
|
381
|
-
* are semantically meaningful or normalization conventions to use. This typically maps to a
|
|
382
|
-
* shorthand identifier for a robotics framework such as "ros1", "ros2", or "ulog". See the MCAP
|
|
383
|
-
* profiles concept at <https://github.com/foxglove/mcap/blob/main/docs/specification/appendix.md#well-known-profiles>.
|
|
384
|
-
*/
|
|
385
|
-
readonly dataSourceProfile?: string;
|
|
386
|
-
|
|
387
|
-
/**
|
|
388
|
-
* Subscribe to updates on this field within the render state. Render will only be invoked when
|
|
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.
|
|
409
|
-
*/
|
|
410
|
-
watch(field: "allFrames"): void;
|
|
411
|
-
|
|
412
|
-
/**
|
|
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
|
|
419
|
-
*
|
|
420
|
-
* context.saveState({ myNum: 2, myBool: false, myStr: "abc" });
|
|
421
|
-
* ```
|
|
422
|
-
*
|
|
423
|
-
* @param state The state to save. This value should be JSON serializable.
|
|
424
|
-
*/
|
|
425
|
-
saveState(state: Partial<unknown>): void;
|
|
426
|
-
|
|
427
|
-
/**
|
|
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
|
-
* ```
|
|
433
|
-
*
|
|
434
|
-
* @param name The name of the parameter to set.
|
|
435
|
-
* @param value The new value of the parameter.
|
|
436
|
-
*/
|
|
437
|
-
setParameter(name: string, value: ParameterValue): void;
|
|
438
|
-
|
|
439
|
-
/**
|
|
440
|
-
* Set the transient state shared by panels of the same type as the caller of this function.
|
|
441
|
-
* This will not be persisted in the layout.
|
|
442
|
-
*/
|
|
443
|
-
setSharedPanelState(state: undefined | Record<string, unknown>): void;
|
|
444
|
-
|
|
445
|
-
/**
|
|
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
|
-
* ```
|
|
462
|
-
*
|
|
463
|
-
* @param name The name of the variable to set.
|
|
464
|
-
* @param value The new value of the variable.
|
|
465
|
-
*/
|
|
466
|
-
setVariable(name: string, value: VariableValue): void;
|
|
467
|
-
|
|
468
|
-
/**
|
|
469
|
-
* Set the active preview time. Setting the preview time to undefined clears the preview time.
|
|
470
|
-
*/
|
|
471
|
-
setPreviewTime(time: number | undefined): void;
|
|
472
|
-
|
|
473
|
-
/**
|
|
474
|
-
* Seek playback to the given time. Behaves as if the user had clicked the playback bar
|
|
475
|
-
* to seek.
|
|
476
|
-
*
|
|
477
|
-
* Clients can pass a number or alternatively a Time object for greater precision.
|
|
478
|
-
*
|
|
479
|
-
* This property may be `undefined` if the current data source does not support seeking.
|
|
480
|
-
*/
|
|
481
|
-
seekPlayback?(time: number | Time): void;
|
|
482
|
-
|
|
483
|
-
/**
|
|
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}.
|
|
486
|
-
*
|
|
487
|
-
* @remarks
|
|
488
|
-
*
|
|
489
|
-
* This method will update the current subscriptions to the new list of Subscriptions and
|
|
490
|
-
* unsubscribe from any previously subscribed topics no longer in the Subscription list. Passing
|
|
491
|
-
* an empty array will unsubscribe from all topics.
|
|
492
|
-
*
|
|
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.
|
|
538
|
-
*/
|
|
539
|
-
subscribe(subscriptions: Subscription[]): void;
|
|
540
|
-
|
|
541
|
-
/**
|
|
542
|
-
* @deprecated Use `subscribe` with an array of Subscription objects instead.
|
|
543
|
-
*/
|
|
544
|
-
subscribe(topics: string[]): void;
|
|
545
|
-
|
|
546
|
-
/**
|
|
547
|
-
* Unsubscribe from all topics.
|
|
548
|
-
*
|
|
549
|
-
* Note: This is analagous to calling `subscribe([])` with an empty array of topics.
|
|
550
|
-
*/
|
|
551
|
-
unsubscribeAll(): void;
|
|
552
|
-
|
|
553
|
-
/**
|
|
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.
|
|
557
|
-
*/
|
|
558
|
-
subscribeAppSettings(settings: string[]): void;
|
|
559
|
-
|
|
560
|
-
/**
|
|
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.
|
|
574
|
-
*
|
|
575
|
-
* @param topic The topic on which the extension will publish messages.
|
|
576
|
-
* @param schemaName The name of the schema that the published messages will conform to.
|
|
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.
|
|
643
|
-
*/
|
|
644
|
-
advertise?(topic: string, schemaName: string, options?: Record<string, unknown>): void;
|
|
645
|
-
|
|
646
|
-
/**
|
|
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.
|
|
654
|
-
*/
|
|
655
|
-
unadvertise?(topic: string): void;
|
|
656
|
-
|
|
657
|
-
/**
|
|
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.
|
|
669
|
-
*
|
|
670
|
-
* @param topic The name of the topic to publish the message on
|
|
671
|
-
* @param message The message to publish
|
|
672
|
-
*/
|
|
673
|
-
publish?(topic: string, message: unknown): void;
|
|
674
|
-
|
|
675
|
-
/**
|
|
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.
|
|
683
|
-
*
|
|
684
|
-
* @param service The name of the service to call
|
|
685
|
-
* @param request The request payload for the service call
|
|
686
|
-
* @returns A promise that resolves when the result is available or rejected with an error
|
|
687
|
-
*/
|
|
688
|
-
callService?(service: string, request: unknown): Promise<unknown>;
|
|
689
|
-
|
|
690
|
-
/**
|
|
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).
|
|
697
|
-
*
|
|
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
|
-
* ```
|
|
711
|
-
*/
|
|
712
|
-
onRender?: (renderState: Immutable<RenderState>, done: () => void) => void;
|
|
713
|
-
|
|
714
|
-
/**
|
|
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`
|
|
821
|
-
*/
|
|
822
|
-
updatePanelSettingsEditor(settings: Immutable<SettingsTree>): void;
|
|
823
|
-
|
|
824
|
-
/**
|
|
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
|
-
* ```
|
|
833
|
-
*/
|
|
834
|
-
setDefaultPanelTitle(defaultTitle: string | undefined): void;
|
|
835
|
-
/**
|
|
836
|
-
* Subscribe to receive the entire time range of messages for a given topic for the current data source.
|
|
837
|
-
*
|
|
838
|
-
* See {@link SubscribeMessageRangeArgs} for more information on behavior.
|
|
839
|
-
*
|
|
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")`.
|
|
843
|
-
*
|
|
844
|
-
* @returns A function that will unsubscribe from the topic, cancel the active async iterator,
|
|
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.
|
|
851
|
-
*/
|
|
852
|
-
UNSTABLE_subscribeMessageRange?: (args: SubscribeMessageRangeArgs) => () => void;
|
|
853
|
-
};
|
|
854
|
-
|
|
855
|
-
/**
|
|
856
|
-
* This type represents the arguments you pass to {@link ExtensionContext.registerPanel}.
|
|
857
|
-
*
|
|
858
|
-
* @category Custom panels
|
|
859
|
-
*/
|
|
860
|
-
export type ExtensionPanelRegistration = {
|
|
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
|
-
*/
|
|
868
|
-
name: string;
|
|
869
|
-
|
|
870
|
-
/**
|
|
871
|
-
* This function is invoked when your panel is initialized
|
|
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.
|
|
875
|
-
*/
|
|
876
|
-
initPanel: (context: PanelExtensionContext) => void | (() => void);
|
|
877
|
-
};
|
|
878
|
-
|
|
879
|
-
/**
|
|
880
|
-
* This type represents the arguments you pass to {@link ExtensionContext.registerMessageConverter}.
|
|
881
|
-
*
|
|
882
|
-
* @category Message converters
|
|
883
|
-
*/
|
|
884
|
-
export type RegisterMessageConverterArgs<Src> = {
|
|
885
|
-
fromSchemaName: string;
|
|
886
|
-
toSchemaName: string;
|
|
887
|
-
converter: (msg: Src, event: Immutable<MessageEvent<Src>>) => unknown;
|
|
888
|
-
};
|
|
889
|
-
|
|
890
|
-
/** @category Topic aliases */
|
|
891
|
-
export type BaseTopic = { name: string; schemaName?: string };
|
|
892
|
-
/** @category Topic aliases */
|
|
893
|
-
export type TopicAlias = { name: string; sourceTopicName: string };
|
|
894
|
-
|
|
895
|
-
/**
|
|
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
|
|
900
|
-
*/
|
|
901
|
-
export type TopicAliasFunction = (
|
|
902
|
-
args: Immutable<{
|
|
903
|
-
topics: BaseTopic[];
|
|
904
|
-
globalVariables: Readonly<Record<string, VariableValue>>;
|
|
905
|
-
}>,
|
|
906
|
-
) => TopicAlias[];
|
|
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
|
-
*/
|
|
920
|
-
export interface ExtensionContext {
|
|
921
|
-
/**
|
|
922
|
-
* @deprecated This field is no longer used.
|
|
923
|
-
* @hidden
|
|
924
|
-
*/
|
|
925
|
-
readonly mode: "production" | "development" | "test";
|
|
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
|
-
*/
|
|
939
|
-
registerPanel(params: ExtensionPanelRegistration): void;
|
|
940
|
-
|
|
941
|
-
/**
|
|
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).
|
|
950
|
-
*
|
|
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.
|
|
957
|
-
*
|
|
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
|
-
|
|
962
|
-
*/
|
|
963
|
-
registerMessageConverter<Src>(args: RegisterMessageConverterArgs<Src>): void;
|
|
964
|
-
|
|
965
|
-
/**
|
|
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.
|
|
974
|
-
*/
|
|
975
|
-
registerTopicAliases(aliasFunction: TopicAliasFunction): void;
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
/**
|
|
979
|
-
* @inline
|
|
980
|
-
* @hidden
|
|
981
|
-
*/
|
|
982
|
-
export type ExtensionActivate = (extensionContext: ExtensionContext) => void;
|
|
983
|
-
|
|
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
|
-
*/
|
|
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
|
-
*/
|
|
1009
|
-
activate: ExtensionActivate;
|
|
1010
|
-
}
|
|
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
|
-
*/
|
|
1018
|
-
export type SettingsIcon =
|
|
1019
|
-
| "Add"
|
|
1020
|
-
| "Addchart"
|
|
1021
|
-
| "AutoAwesome"
|
|
1022
|
-
| "Background"
|
|
1023
|
-
| "Camera"
|
|
1024
|
-
| "Cells"
|
|
1025
|
-
| "Check"
|
|
1026
|
-
| "Circle"
|
|
1027
|
-
| "Clear"
|
|
1028
|
-
| "Clock"
|
|
1029
|
-
| "Collapse"
|
|
1030
|
-
| "Cube"
|
|
1031
|
-
| "Delete"
|
|
1032
|
-
| "Expand"
|
|
1033
|
-
| "Flag"
|
|
1034
|
-
| "Folder"
|
|
1035
|
-
| "FolderOpen"
|
|
1036
|
-
| "Grid"
|
|
1037
|
-
| "Hive"
|
|
1038
|
-
| "ImageProjection"
|
|
1039
|
-
| "Map"
|
|
1040
|
-
| "Move"
|
|
1041
|
-
| "MoveDown"
|
|
1042
|
-
| "MoveUp"
|
|
1043
|
-
| "NorthWest"
|
|
1044
|
-
| "Note"
|
|
1045
|
-
| "NoteFilled"
|
|
1046
|
-
| "Points"
|
|
1047
|
-
| "PrecisionManufacturing"
|
|
1048
|
-
| "Radar"
|
|
1049
|
-
| "Settings"
|
|
1050
|
-
| "Shapes"
|
|
1051
|
-
| "Share"
|
|
1052
|
-
| "Star"
|
|
1053
|
-
| "SouthEast"
|
|
1054
|
-
| "Timeline"
|
|
1055
|
-
| "Topic"
|
|
1056
|
-
| "Walk"
|
|
1057
|
-
| "World";
|
|
1058
|
-
|
|
1059
|
-
/**
|
|
1060
|
-
* A settings tree field specifies the input type and the value of a field
|
|
1061
|
-
* in the settings editor.
|
|
1062
|
-
*
|
|
1063
|
-
* @category Custom panels
|
|
1064
|
-
*/
|
|
1065
|
-
export type SettingsTreeFieldValue =
|
|
1066
|
-
| {
|
|
1067
|
-
input: "autocomplete";
|
|
1068
|
-
value?: string;
|
|
1069
|
-
items: string[];
|
|
1070
|
-
|
|
1071
|
-
/**
|
|
1072
|
-
* Optional placeholder text displayed in the field input when value is undefined
|
|
1073
|
-
*/
|
|
1074
|
-
placeholder?: string;
|
|
1075
|
-
}
|
|
1076
|
-
| { input: "boolean"; value?: boolean }
|
|
1077
|
-
| {
|
|
1078
|
-
input: "rgb";
|
|
1079
|
-
value?: string;
|
|
1080
|
-
|
|
1081
|
-
/**
|
|
1082
|
-
* Optional placeholder text displayed in the field input when value is undefined
|
|
1083
|
-
*/
|
|
1084
|
-
placeholder?: string;
|
|
1085
|
-
|
|
1086
|
-
/**
|
|
1087
|
-
* Optional field that's true if the clear button should be hidden.
|
|
1088
|
-
*/
|
|
1089
|
-
hideClearButton?: boolean;
|
|
1090
|
-
}
|
|
1091
|
-
| {
|
|
1092
|
-
input: "rgba";
|
|
1093
|
-
value?: string;
|
|
1094
|
-
|
|
1095
|
-
/**
|
|
1096
|
-
* Optional placeholder text displayed in the field input when value is undefined
|
|
1097
|
-
*/
|
|
1098
|
-
placeholder?: string;
|
|
1099
|
-
|
|
1100
|
-
/**
|
|
1101
|
-
* Optional field that's true if the clear button should be hidden.
|
|
1102
|
-
*/
|
|
1103
|
-
hideClearButton?: boolean;
|
|
1104
|
-
}
|
|
1105
|
-
| { input: "gradient"; value?: [string, string] }
|
|
1106
|
-
| {
|
|
1107
|
-
input: "messagepath";
|
|
1108
|
-
value?: string;
|
|
1109
|
-
validTypes?: string[];
|
|
1110
|
-
/** True if the input should allow math modifiers like @abs. */
|
|
1111
|
-
supportsMathModifiers?: boolean;
|
|
1112
|
-
}
|
|
1113
|
-
| {
|
|
1114
|
-
input: "number";
|
|
1115
|
-
value?: number;
|
|
1116
|
-
step?: number;
|
|
1117
|
-
max?: number;
|
|
1118
|
-
min?: number;
|
|
1119
|
-
precision?: number;
|
|
1120
|
-
|
|
1121
|
-
/**
|
|
1122
|
-
* Optional placeholder text displayed in the field input when value is undefined
|
|
1123
|
-
*/
|
|
1124
|
-
placeholder?: string;
|
|
1125
|
-
}
|
|
1126
|
-
| {
|
|
1127
|
-
input: "select";
|
|
1128
|
-
value?: number | number[];
|
|
1129
|
-
options: Array<{ label: string; value: undefined | number; disabled?: boolean }>;
|
|
1130
|
-
}
|
|
1131
|
-
| {
|
|
1132
|
-
input: "select";
|
|
1133
|
-
value?: string | string[];
|
|
1134
|
-
options: Array<{ label: string; value: undefined | string; disabled?: boolean }>;
|
|
1135
|
-
}
|
|
1136
|
-
| {
|
|
1137
|
-
input: "string";
|
|
1138
|
-
value?: string;
|
|
1139
|
-
|
|
1140
|
-
/**
|
|
1141
|
-
* Optional placeholder text displayed in the field input when value is undefined
|
|
1142
|
-
*/
|
|
1143
|
-
placeholder?: string;
|
|
1144
|
-
}
|
|
1145
|
-
| {
|
|
1146
|
-
input: "toggle";
|
|
1147
|
-
value?: string;
|
|
1148
|
-
options: string[] | Array<{ label: string; value: undefined | string }>;
|
|
1149
|
-
}
|
|
1150
|
-
| {
|
|
1151
|
-
input: "toggle";
|
|
1152
|
-
value?: number;
|
|
1153
|
-
options: number[] | Array<{ label: string; value: undefined | number }>;
|
|
1154
|
-
}
|
|
1155
|
-
| {
|
|
1156
|
-
input: "vec3";
|
|
1157
|
-
value?: [undefined | number, undefined | number, undefined | number];
|
|
1158
|
-
placeholder?: [undefined | string, undefined | string, undefined | string];
|
|
1159
|
-
step?: number;
|
|
1160
|
-
precision?: number;
|
|
1161
|
-
labels?: [string, string, string];
|
|
1162
|
-
max?: number;
|
|
1163
|
-
min?: number;
|
|
1164
|
-
}
|
|
1165
|
-
| {
|
|
1166
|
-
input: "vec2";
|
|
1167
|
-
value?: [undefined | number, undefined | number];
|
|
1168
|
-
placeholder?: [undefined | string, undefined | string];
|
|
1169
|
-
step?: number;
|
|
1170
|
-
precision?: number;
|
|
1171
|
-
labels?: [string, string];
|
|
1172
|
-
max?: number;
|
|
1173
|
-
min?: number;
|
|
1174
|
-
};
|
|
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
|
-
*/
|
|
1182
|
-
export type SettingsTreeField = SettingsTreeFieldValue & {
|
|
1183
|
-
/**
|
|
1184
|
-
* True if the field is disabled.
|
|
1185
|
-
*/
|
|
1186
|
-
disabled?: boolean;
|
|
1187
|
-
|
|
1188
|
-
/**
|
|
1189
|
-
* Optional help text to explain the purpose of the field.
|
|
1190
|
-
*/
|
|
1191
|
-
help?: string;
|
|
1192
|
-
|
|
1193
|
-
/**
|
|
1194
|
-
* The label displayed alongside the field.
|
|
1195
|
-
*/
|
|
1196
|
-
label: string;
|
|
1197
|
-
|
|
1198
|
-
/**
|
|
1199
|
-
* True if the field is readonly.
|
|
1200
|
-
*/
|
|
1201
|
-
readonly?: boolean;
|
|
1202
|
-
|
|
1203
|
-
/**
|
|
1204
|
-
* Optional message indicating any error state for the field.
|
|
1205
|
-
*/
|
|
1206
|
-
error?: string;
|
|
1207
|
-
};
|
|
1208
|
-
|
|
1209
|
-
/**
|
|
1210
|
-
* @category Custom panels
|
|
1211
|
-
*/
|
|
1212
|
-
export type SettingsTreeFields = Record<string, undefined | SettingsTreeField>;
|
|
1213
|
-
|
|
1214
|
-
/**
|
|
1215
|
-
* @category Custom panels
|
|
1216
|
-
*/
|
|
1217
|
-
export type SettingsTreeChildren = Record<string, undefined | SettingsTreeNode>;
|
|
1218
|
-
|
|
1219
|
-
/**
|
|
1220
|
-
* An action included in the action menu for a settings node.
|
|
1221
|
-
*
|
|
1222
|
-
* @category Custom panels
|
|
1223
|
-
*/
|
|
1224
|
-
export type SettingsTreeNodeActionItem = {
|
|
1225
|
-
type: "action";
|
|
1226
|
-
|
|
1227
|
-
/**
|
|
1228
|
-
* A unique idenfier for the action.
|
|
1229
|
-
*/
|
|
1230
|
-
id: string;
|
|
1231
|
-
|
|
1232
|
-
/**
|
|
1233
|
-
* A descriptive label for the action.
|
|
1234
|
-
*/
|
|
1235
|
-
label: string;
|
|
1236
|
-
|
|
1237
|
-
/**
|
|
1238
|
-
* Optional icon to display with the action.
|
|
1239
|
-
*/
|
|
1240
|
-
icon?: SettingsIcon;
|
|
1241
|
-
|
|
1242
|
-
/**
|
|
1243
|
-
* Specifies whether the item is rendered as an inline action or as an item in the
|
|
1244
|
-
* context menu. Defaults to "menu" if not specified. Inline items will be rendered
|
|
1245
|
-
* as an icon only if their icon is specified.
|
|
1246
|
-
*/
|
|
1247
|
-
display?: "menu" | "inline";
|
|
1248
|
-
};
|
|
1249
|
-
|
|
1250
|
-
/**
|
|
1251
|
-
* @category Custom panels
|
|
1252
|
-
*/
|
|
1253
|
-
export type SettingsTreeNodeActionDivider = { type: "divider" };
|
|
1254
|
-
|
|
1255
|
-
/**
|
|
1256
|
-
* An action included in the action menu for a settings node.
|
|
1257
|
-
*
|
|
1258
|
-
* @category Custom panels
|
|
1259
|
-
*/
|
|
1260
|
-
export type SettingsTreeNodeAction = SettingsTreeNodeActionItem | SettingsTreeNodeActionDivider;
|
|
1261
|
-
|
|
1262
|
-
/**
|
|
1263
|
-
* A node represents a single item or group of items in the settings tree.
|
|
1264
|
-
*
|
|
1265
|
-
* @category Custom panels
|
|
1266
|
-
*/
|
|
1267
|
-
export type SettingsTreeNode = {
|
|
1268
|
-
/**
|
|
1269
|
-
* An array of actions that can be performed on this node.
|
|
1270
|
-
*/
|
|
1271
|
-
actions?: SettingsTreeNodeAction[];
|
|
1272
|
-
|
|
1273
|
-
/**
|
|
1274
|
-
* Other settings tree nodes nested under this node.
|
|
1275
|
-
*/
|
|
1276
|
-
children?: SettingsTreeChildren;
|
|
1277
|
-
|
|
1278
|
-
/**
|
|
1279
|
-
* Set to collapsed if the node should be initially collapsed.
|
|
1280
|
-
*/
|
|
1281
|
-
defaultExpansionState?: "collapsed" | "expanded";
|
|
1282
|
-
|
|
1283
|
-
/**
|
|
1284
|
-
* Optional message indicating any error state for the node.
|
|
1285
|
-
*/
|
|
1286
|
-
error?: string;
|
|
1287
|
-
|
|
1288
|
-
/**
|
|
1289
|
-
* Field inputs attached directly to this node.
|
|
1290
|
-
*/
|
|
1291
|
-
fields?: SettingsTreeFields;
|
|
1292
|
-
|
|
1293
|
-
/**
|
|
1294
|
-
* Optional icon to display next to the node label.
|
|
1295
|
-
*/
|
|
1296
|
-
icon?: SettingsIcon;
|
|
1297
|
-
|
|
1298
|
-
/**
|
|
1299
|
-
* An optional label shown at the top of this node.
|
|
1300
|
-
*/
|
|
1301
|
-
label?: string;
|
|
1302
|
-
|
|
1303
|
-
/**
|
|
1304
|
-
* True if the node label can be edited by the user.
|
|
1305
|
-
*/
|
|
1306
|
-
renamable?: boolean;
|
|
1307
|
-
|
|
1308
|
-
/**
|
|
1309
|
-
* Optional sort order to override natural object ordering. All nodes
|
|
1310
|
-
* with a sort order will be rendered before nodes all with no sort order.
|
|
1311
|
-
*
|
|
1312
|
-
* Nodes without an explicit order will be ordered according to ECMA
|
|
1313
|
-
* object ordering rules.
|
|
1314
|
-
*
|
|
1315
|
-
* https://262.ecma-international.org/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys
|
|
1316
|
-
*/
|
|
1317
|
-
order?: number | string;
|
|
1318
|
-
|
|
1319
|
-
/**
|
|
1320
|
-
* An optional visibility status. If this is not undefined, the node
|
|
1321
|
-
* editor will display a visiblity toggle button and send update actions
|
|
1322
|
-
* to the action handler.
|
|
1323
|
-
**/
|
|
1324
|
-
visible?: boolean;
|
|
1325
|
-
|
|
1326
|
-
/**
|
|
1327
|
-
* Filter Children by visibility status
|
|
1328
|
-
*/
|
|
1329
|
-
enableVisibilityFilter?: boolean;
|
|
1330
|
-
};
|
|
1331
|
-
|
|
1332
|
-
/**
|
|
1333
|
-
* Distributes Pick<T, K> across all members of a union, used for extracting structured
|
|
1334
|
-
* subtypes.
|
|
1335
|
-
*/
|
|
1336
|
-
type DistributivePick<T, K extends keyof T> = T extends unknown ? Pick<T, K> : never;
|
|
1337
|
-
|
|
1338
|
-
/**
|
|
1339
|
-
* Represents actions that can be dispatched to source of the SettingsTree to implement
|
|
1340
|
-
* edits and updates.
|
|
1341
|
-
*
|
|
1342
|
-
* @category Custom panels
|
|
1343
|
-
*/
|
|
1344
|
-
export type SettingsTreeAction =
|
|
1345
|
-
| {
|
|
1346
|
-
action: "update";
|
|
1347
|
-
payload: { path: readonly string[] } & DistributivePick<
|
|
1348
|
-
SettingsTreeFieldValue,
|
|
1349
|
-
"input" | "value"
|
|
1350
|
-
>;
|
|
1351
|
-
}
|
|
1352
|
-
| {
|
|
1353
|
-
action: "perform-node-action";
|
|
1354
|
-
payload: { id: string; path: readonly string[] };
|
|
1355
|
-
};
|
|
1356
|
-
|
|
1357
|
-
/**
|
|
1358
|
-
* @inline
|
|
1359
|
-
* @hidden
|
|
1360
|
-
*/
|
|
1361
|
-
export type SettingsTreeNodes = Record<string, undefined | SettingsTreeNode>;
|
|
1362
|
-
|
|
1363
|
-
/**
|
|
1364
|
-
* A settings tree is a tree of panel settings that can be displayed and edited in
|
|
1365
|
-
* the panel settings sidebar.
|
|
1366
|
-
*
|
|
1367
|
-
* Nodes and fields in the tree can be referred to by a string path, which collects
|
|
1368
|
-
* the keys of each node on the path from the root to the child node or field.
|
|
1369
|
-
*
|
|
1370
|
-
* For example, for the following tree:
|
|
1371
|
-
*
|
|
1372
|
-
* ```json
|
|
1373
|
-
* root: {
|
|
1374
|
-
* children: {
|
|
1375
|
-
* a: {
|
|
1376
|
-
* children: {
|
|
1377
|
-
* b: {
|
|
1378
|
-
* fields: {
|
|
1379
|
-
* toggleMe: {
|
|
1380
|
-
* label: "Toggle me",
|
|
1381
|
-
* input: "boolean",
|
|
1382
|
-
* value: false,
|
|
1383
|
-
* },
|
|
1384
|
-
* },
|
|
1385
|
-
* },
|
|
1386
|
-
* },
|
|
1387
|
-
* },
|
|
1388
|
-
* },
|
|
1389
|
-
* },
|
|
1390
|
-
* ```
|
|
1391
|
-
*
|
|
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
|
|
1394
|
-
* actionHandler, which responds to updates to values in the tree, and also in
|
|
1395
|
-
* the focusedPath, which is used to focus the editor UI at a particular node
|
|
1396
|
-
* in the tree.
|
|
1397
|
-
*
|
|
1398
|
-
* @category Custom panels
|
|
1399
|
-
*/
|
|
1400
|
-
export type SettingsTree = {
|
|
1401
|
-
/**
|
|
1402
|
-
* Handler to process all actions on the settings tree initiated by the UI.
|
|
1403
|
-
*/
|
|
1404
|
-
actionHandler: (action: SettingsTreeAction) => void;
|
|
1405
|
-
|
|
1406
|
-
/**
|
|
1407
|
-
* True if the settings editor should show the filter control.
|
|
1408
|
-
*/
|
|
1409
|
-
enableFilter?: boolean;
|
|
1410
|
-
|
|
1411
|
-
/**
|
|
1412
|
-
* Setting this will have a one-time effect of scrolling the editor to the
|
|
1413
|
-
* node at the path and highlighting it. This is a transient effect so it is
|
|
1414
|
-
* not necessary to subsequently unset this.
|
|
1415
|
-
*/
|
|
1416
|
-
focusedPath?: readonly string[];
|
|
1417
|
-
|
|
1418
|
-
/**
|
|
1419
|
-
* The settings tree root nodes. Updates to these will automatically be
|
|
1420
|
-
* reflected in the editor UI.
|
|
1421
|
-
*/
|
|
1422
|
-
nodes: SettingsTreeNodes;
|
|
1423
|
-
};
|
|
3
|
+
export type { Experimental } from "./experimental";
|