0
# Command Metadata
1
2
Rich metadata system for command presentation in user interfaces, including labels, icons, state management, and contextual information. The metadata system enables commands to provide dynamic visual representation and state-dependent behavior.
3
4
## Capabilities
5
6
### Command Description
7
8
Get comprehensive description and schema information for commands.
9
10
```typescript { .api }
11
/**
12
* Get the description for a specific command.
13
* @param id - The id of the command of interest
14
* @param args - The arguments for the command
15
* @returns The description for the command
16
*/
17
describedBy(id: string, args?: ReadonlyPartialJSONObject): Promise<CommandRegistry.Description>;
18
19
type Description = { args: ReadonlyJSONObject | null };
20
```
21
22
### Text Metadata
23
24
Get textual information about commands for UI display.
25
26
```typescript { .api }
27
/**
28
* Get the display label for a specific command.
29
* @param id - The id of the command of interest
30
* @param args - The arguments for the command
31
* @returns The display label for the command, or an empty string if the command is not registered
32
*/
33
label(id: string, args?: ReadonlyPartialJSONObject): string;
34
35
/**
36
* Get the mnemonic index for a specific command.
37
* @param id - The id of the command of interest
38
* @param args - The arguments for the command
39
* @returns The mnemonic index for the command, or -1 if the command is not registered
40
*/
41
mnemonic(id: string, args?: ReadonlyPartialJSONObject): number;
42
43
/**
44
* Get the short form caption for a specific command.
45
* @param id - The id of the command of interest
46
* @param args - The arguments for the command
47
* @returns The caption for the command, or an empty string if the command is not registered
48
*/
49
caption(id: string, args?: ReadonlyPartialJSONObject): string;
50
51
/**
52
* Get the usage help text for a specific command.
53
* @param id - The id of the command of interest
54
* @param args - The arguments for the command
55
* @returns The usage text for the command, or an empty string if the command is not registered
56
*/
57
usage(id: string, args?: ReadonlyPartialJSONObject): string;
58
```
59
60
### Visual Metadata
61
62
Get visual representation information for commands including icons and styling.
63
64
```typescript { .api }
65
/**
66
* Get the icon renderer for a specific command.
67
* @param id - The id of the command of interest
68
* @param args - The arguments for the command
69
* @returns The icon renderer for the command or undefined
70
*/
71
icon(id: string, args?: ReadonlyPartialJSONObject): VirtualElement.IRenderer | undefined;
72
73
/**
74
* Get the icon class for a specific command.
75
* @param id - The id of the command of interest
76
* @param args - The arguments for the command
77
* @returns The icon class for the command, or an empty string if the command is not registered
78
*/
79
iconClass(id: string, args?: ReadonlyPartialJSONObject): string;
80
81
/**
82
* Get the icon label for a specific command.
83
* @param id - The id of the command of interest
84
* @param args - The arguments for the command
85
* @returns The icon label for the command, or an empty string if the command is not registered
86
*/
87
iconLabel(id: string, args?: ReadonlyPartialJSONObject): string;
88
89
/**
90
* Get the extra class name for a specific command.
91
* @param id - The id of the command of interest
92
* @param args - The arguments for the command
93
* @returns The class name for the command, or an empty string if the command is not registered
94
*/
95
className(id: string, args?: ReadonlyPartialJSONObject): string;
96
97
/**
98
* Get the dataset for a specific command.
99
* @param id - The id of the command of interest
100
* @param args - The arguments for the command
101
* @returns The dataset for the command, or an empty dataset if the command is not registered
102
*/
103
dataset(id: string, args?: ReadonlyPartialJSONObject): CommandRegistry.Dataset;
104
```
105
106
### Command State
107
108
Check the current state of commands for UI state management.
109
110
```typescript { .api }
111
/**
112
* Test whether a specific command is enabled.
113
* @param id - The id of the command of interest
114
* @param args - The arguments for the command
115
* @returns A boolean indicating whether the command is enabled, or false if the command is not registered
116
*/
117
isEnabled(id: string, args?: ReadonlyPartialJSONObject): boolean;
118
119
/**
120
* Test whether a specific command is toggled.
121
* @param id - The id of the command of interest
122
* @param args - The arguments for the command
123
* @returns A boolean indicating whether the command is toggled, or false if the command is not registered
124
*/
125
isToggled(id: string, args?: ReadonlyPartialJSONObject): boolean;
126
127
/**
128
* Test whether a specific command is toggleable.
129
* @param id - The id of the command of interest
130
* @param args - The arguments for the command
131
* @returns A boolean indicating whether the command is toggleable, or false if the command is not registered
132
*/
133
isToggleable(id: string, args?: ReadonlyJSONObject): boolean;
134
135
/**
136
* Test whether a specific command is visible.
137
* @param id - The id of the command of interest
138
* @param args - The arguments for the command
139
* @returns A boolean indicating whether the command is visible, or false if the command is not registered
140
*/
141
isVisible(id: string, args?: ReadonlyPartialJSONObject): boolean;
142
```
143
144
## Usage Examples
145
146
### Dynamic Labels
147
148
```typescript
149
import { CommandRegistry } from "@lumino/commands";
150
151
const registry = new CommandRegistry();
152
153
// Command with dynamic label based on context
154
registry.addCommand("open-file", {
155
execute: (args) => {
156
console.log(`Opening ${args.filename}`);
157
},
158
label: (args) => {
159
return args.filename ? `Open ${args.filename}` : "Open File";
160
},
161
caption: (args) => {
162
return args.filename ? `Open the file: ${args.filename}` : "Open a file";
163
}
164
});
165
166
// Get labels with different arguments
167
console.log(registry.label("open-file")); // "Open File"
168
console.log(registry.label("open-file", { filename: "document.txt" })); // "Open document.txt"
169
console.log(registry.caption("open-file", { filename: "document.txt" })); // "Open the file: document.txt"
170
```
171
172
### Icon Management
173
174
```typescript
175
import { CommandRegistry } from "@lumino/commands";
176
177
const registry = new CommandRegistry();
178
179
// Icon renderer object
180
const saveIconRenderer = {
181
render: (host: HTMLElement) => {
182
const icon = document.createElement("i");
183
icon.className = "fa fa-save";
184
host.appendChild(icon);
185
}
186
};
187
188
registry.addCommand("save", {
189
execute: () => console.log("Saving..."),
190
label: "Save",
191
icon: saveIconRenderer,
192
iconClass: "save-icon",
193
iconLabel: "💾" // Emoji fallback
194
});
195
196
// Get icon information
197
const iconRenderer = registry.icon("save");
198
const iconClass = registry.iconClass("save"); // "save-icon"
199
const iconLabel = registry.iconLabel("save"); // "💾"
200
```
201
202
### State-Dependent Styling
203
204
```typescript
205
import { CommandRegistry } from "@lumino/commands";
206
207
const registry = new CommandRegistry();
208
let isPlaying = false;
209
210
registry.addCommand("play-pause", {
211
execute: () => {
212
isPlaying = !isPlaying;
213
registry.notifyCommandChanged("play-pause");
214
},
215
label: () => isPlaying ? "Pause" : "Play",
216
iconClass: () => isPlaying ? "fa fa-pause" : "fa fa-play",
217
className: () => isPlaying ? "active playing" : "inactive",
218
isToggled: () => isPlaying,
219
isToggleable: true
220
});
221
222
// Check current state
223
console.log(registry.label("play-pause")); // "Play"
224
console.log(registry.iconClass("play-pause")); // "fa fa-play"
225
console.log(registry.isToggled("play-pause")); // false
226
console.log(registry.isToggleable("play-pause")); // true
227
228
// Execute to change state
229
await registry.execute("play-pause");
230
231
console.log(registry.label("play-pause")); // "Pause"
232
console.log(registry.iconClass("play-pause")); // "fa fa-pause"
233
console.log(registry.isToggled("play-pause")); // true
234
```
235
236
### Context-Sensitive Metadata
237
238
```typescript
239
import { CommandRegistry } from "@lumino/commands";
240
241
const registry = new CommandRegistry();
242
243
registry.addCommand("format-text", {
244
execute: (args) => {
245
console.log(`Formatting as ${args.format}`);
246
},
247
label: (args) => {
248
const format = args.format || "default";
249
return `Format as ${format.toUpperCase()}`;
250
},
251
iconClass: (args) => {
252
switch (args.format) {
253
case "bold": return "fa fa-bold";
254
case "italic": return "fa fa-italic";
255
case "underline": return "fa fa-underline";
256
default: return "fa fa-font";
257
}
258
},
259
isEnabled: (args) => Boolean(args.selectedText),
260
dataset: (args) => ({
261
"format-type": args.format || "default",
262
"has-selection": args.selectedText ? "true" : "false"
263
})
264
});
265
266
// Get metadata with different contexts
267
const boldContext = { format: "bold", selectedText: "Hello World" };
268
console.log(registry.label("format-text", boldContext)); // "Format as BOLD"
269
console.log(registry.iconClass("format-text", boldContext)); // "fa fa-bold"
270
console.log(registry.isEnabled("format-text", boldContext)); // true
271
console.log(registry.dataset("format-text", boldContext)); // { "format-type": "bold", "has-selection": "true" }
272
273
const noSelectionContext = { format: "bold" };
274
console.log(registry.isEnabled("format-text", noSelectionContext)); // false
275
```
276
277
### Mnemonic Handling
278
279
```typescript
280
import { CommandRegistry } from "@lumino/commands";
281
282
const registry = new CommandRegistry();
283
284
registry.addCommand("file-menu", {
285
execute: () => console.log("Opening file menu"),
286
label: "File",
287
mnemonic: 0, // 'F' is at index 0
288
caption: "File operations menu"
289
});
290
291
registry.addCommand("edit-menu", {
292
execute: () => console.log("Opening edit menu"),
293
label: "Edit",
294
mnemonic: 0, // 'E' is at index 0
295
caption: "Edit operations menu"
296
});
297
298
// Get mnemonic indices for keyboard navigation
299
console.log(registry.mnemonic("file-menu")); // 0
300
console.log(registry.mnemonic("edit-menu")); // 0
301
302
// Dynamic mnemonic based on context
303
registry.addCommand("save-as", {
304
execute: (args) => console.log("Save as:", args.filename),
305
label: (args) => args.filename ? `Save as ${args.filename}` : "Save As...",
306
mnemonic: (args) => args.filename ? 8 : 5, // 'A' in "Save As..." or 'a' in filename
307
});
308
```
309
310
### Comprehensive Metadata Example
311
312
```typescript
313
import { CommandRegistry } from "@lumino/commands";
314
315
const registry = new CommandRegistry();
316
317
// Complex command with rich metadata
318
registry.addCommand("document-action", {
319
execute: async (args) => {
320
console.log(`Performing ${args.action} on document ${args.docId}`);
321
return { success: true, action: args.action };
322
},
323
324
describedBy: (args) => ({
325
args: {
326
type: "object",
327
properties: {
328
action: { type: "string", enum: ["save", "export", "print"] },
329
docId: { type: "string" },
330
format: { type: "string", optional: true }
331
}
332
}
333
}),
334
335
label: (args) => {
336
const action = args.action || "action";
337
const docName = args.docName || `Document ${args.docId || ""}`.trim();
338
return `${action.charAt(0).toUpperCase() + action.slice(1)} ${docName}`;
339
},
340
341
caption: (args) => {
342
return `${args.action || "Perform action on"} the current document`;
343
},
344
345
usage: () => "document-action --action=<save|export|print> --docId=<id> [--format=<format>]",
346
347
iconClass: (args) => {
348
switch (args.action) {
349
case "save": return "fa fa-save";
350
case "export": return "fa fa-download";
351
case "print": return "fa fa-print";
352
default: return "fa fa-file";
353
}
354
},
355
356
className: (args) => {
357
const classes = ["document-action"];
358
if (args.action) classes.push(`action-${args.action}`);
359
if (args.urgent) classes.push("urgent");
360
return classes.join(" ");
361
},
362
363
dataset: (args) => ({
364
"action": args.action || "",
365
"doc-id": args.docId || "",
366
"format": args.format || "",
367
"timestamp": Date.now().toString()
368
}),
369
370
isEnabled: (args) => Boolean(args.docId && args.action),
371
isVisible: (args) => Boolean(args.hasPermission),
372
isToggled: (args) => args.action === "save" && args.autoSave,
373
isToggleable: true
374
});
375
376
// Use the comprehensive metadata
377
const context = {
378
action: "export",
379
docId: "doc123",
380
docName: "Annual Report",
381
format: "pdf",
382
hasPermission: true,
383
urgent: true
384
};
385
386
console.log(registry.label("document-action", context)); // "Export Annual Report"
387
console.log(registry.caption("document-action", context)); // "export the current document"
388
console.log(registry.iconClass("document-action", context)); // "fa fa-download"
389
console.log(registry.className("document-action", context)); // "document-action action-export urgent"
390
console.log(registry.isEnabled("document-action", context)); // true
391
console.log(registry.isVisible("document-action", context)); // true
392
393
const description = await registry.describedBy("document-action", context);
394
console.log(description); // { args: { type: "object", properties: { ... } } }
395
```
396
397
## Types
398
399
```typescript { .api }
400
type Dataset = { readonly [key: string]: string };
401
type Description = { args: ReadonlyJSONObject | null };
402
type CommandFunc<T> = (args: ReadonlyPartialJSONObject) => T;
403
```