@tailor-platform/app-shell 1.16.0 → 1.17.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.
Files changed (42) hide show
  1. package/dist/app-shell-core.css +1 -1
  2. package/dist/app-shell.d.ts +692 -106
  3. package/dist/app-shell.js +6294 -4939
  4. package/dist/{appshell-B0wh5Lq0.js → appshell-CahhZy7v.js} +316 -297
  5. package/dist/semantic-contrast.test.ts +154 -0
  6. package/dist/style-entry.d.ts +117 -82
  7. package/dist/testing.d.ts +122 -85
  8. package/dist/testing.js +1 -1
  9. package/dist/theme-bridge.test.ts +101 -1
  10. package/dist/theme.bridge.css +91 -0
  11. package/dist/theme.css +6 -1
  12. package/dist/themes/_template.css +7 -1
  13. package/dist/themes/bloom.css +0 -6
  14. package/dist/themes/cream.css +0 -6
  15. package/dist/themes/default.css +389 -69
  16. package/dist/vite-plugin.d.ts +117 -82
  17. package/package.json +1 -1
  18. package/skills/app-shell-patterns/SKILL.md +7 -5
  19. package/skills/app-shell-patterns/references/api/define-module.md +2 -2
  20. package/skills/app-shell-patterns/references/api/define-resource.md +2 -2
  21. package/skills/app-shell-patterns/references/api/use-app-shell-config.md +53 -47
  22. package/skills/app-shell-patterns/references/api/use-app-shell-data.md +30 -26
  23. package/skills/app-shell-patterns/references/api/use-app-shell.md +37 -30
  24. package/skills/app-shell-patterns/references/api/use-toast.md +28 -31
  25. package/skills/app-shell-patterns/references/components/app-shell.md +4 -4
  26. package/skills/app-shell-patterns/references/components/card.md +79 -7
  27. package/skills/app-shell-patterns/references/components/data-table.md +267 -52
  28. package/skills/app-shell-patterns/references/components/date-picker.md +32 -21
  29. package/skills/app-shell-patterns/references/components/filter-rail.md +165 -0
  30. package/skills/app-shell-patterns/references/components/sidebar-group.md +6 -0
  31. package/skills/app-shell-patterns/references/components/sidebar-section.md +114 -0
  32. package/skills/app-shell-patterns/references/concepts/custom-components.md +1 -1
  33. package/skills/app-shell-patterns/references/concepts/file-based-routing.md +7 -1
  34. package/skills/app-shell-patterns/references/concepts/graphql.md +20 -14
  35. package/skills/app-shell-patterns/references/concepts/routing-navigation.md +41 -3
  36. package/skills/app-shell-patterns/references/concepts/sidebar-navigation.md +32 -0
  37. package/skills/app-shell-patterns/references/concepts/styling-theming.md +255 -58
  38. package/skills/app-shell-patterns/references/migrations.md +21 -0
  39. package/skills/app-shell-patterns/references/pages/document-detail.md +6 -6
  40. package/skills/app-shell-patterns/references/patterns/form-modal.md +26 -20
  41. package/skills/app-shell-patterns/references/patterns/interaction-multi-select.md +129 -118
  42. package/skills/app-shell-patterns/references/patterns/list-dense-scan.md +2 -2
@@ -0,0 +1,154 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { describe, expect, it } from "vitest";
5
+
6
+ /**
7
+ * WCAG 1.4.3 contrast checks for the semantic colour roles, computed from
8
+ * `themes/default.css` itself. Nothing is copied into the test, so a change to
9
+ * a hue step or an alias that breaks a pair fails here.
10
+ *
11
+ * Scope of the guarantee: the default state of each pair, on the default
12
+ * palette's `--card` and `--background`. Not covered on purpose:
13
+ * - hover states (`surface-hover`) against 4.5:1: subtle-badge hover text is
14
+ * below 4.5:1 for some roles (danger and success in light mode). They are held
15
+ * at a documented floor (MIN_HOVER_TEXT) so they cannot get worse unnoticed,
16
+ * see decisions/semantic-color-roles.md;
17
+ * - branded palettes (cream, bloom) and their tinted shell backgrounds;
18
+ * - the neutral intent, whose values are the pre-existing system tokens;
19
+ * - the warning `solid` fill against the card (a fill, not a text pair).
20
+ */
21
+ const here = dirname(fileURLToPath(import.meta.url));
22
+ const css = readFileSync(join(here, "themes/default.css"), "utf8").replace(/\/\*[\s\S]*?\*\//g, "");
23
+
24
+ type Rgba = { r: number; g: number; b: number; a: number };
25
+ type Mode = "light" | "dark";
26
+
27
+ /** Custom properties in effect on <html> for a mode, applying rules in source order. */
28
+ function variablesFor(mode: Mode): Map<string, string> {
29
+ const vars = new Map<string, string>();
30
+ for (const rule of css.matchAll(/([^{}]+)\{([^{}]*)\}/g)) {
31
+ const selectors = rule[1].split(",").map((s) => s.trim());
32
+ // <html class="dark"> matches both `:root` and `.dark`; light matches `:root` only.
33
+ const applies = selectors.some((s) => s === ":root" || (mode === "dark" && s === ".dark"));
34
+ if (!applies) continue;
35
+ for (const decl of rule[2].matchAll(/(--[a-z0-9-]+)\s*:\s*([^;]+);/g)) {
36
+ vars.set(decl[1], decl[2].replace(/\s+/g, " ").trim());
37
+ }
38
+ }
39
+ return vars;
40
+ }
41
+
42
+ function parseColor(value: string, vars: Map<string, string>): Rgba {
43
+ const v = value.trim();
44
+ const ref = /^var\((--[a-z0-9-]+)\)$/.exec(v);
45
+ if (ref) {
46
+ const target = vars.get(ref[1]);
47
+ if (target === undefined) throw new Error(`Undefined variable ${ref[1]}`);
48
+ return parseColor(target, vars);
49
+ }
50
+ const hex = /^#([0-9a-f]{3,8})$/i.exec(v);
51
+ if (hex) {
52
+ let h = hex[1];
53
+ if (h.length === 3 || h.length === 4) h = [...h].map((c) => c + c).join("");
54
+ if (h.length !== 6 && h.length !== 8) throw new Error(`Bad hex colour ${v}`);
55
+ return {
56
+ r: parseInt(h.slice(0, 2), 16),
57
+ g: parseInt(h.slice(2, 4), 16),
58
+ b: parseInt(h.slice(4, 6), 16),
59
+ a: h.length === 8 ? parseInt(h.slice(6, 8), 16) / 255 : 1,
60
+ };
61
+ }
62
+ const fn = /^rgba?\(([^)]+)\)$/.exec(v);
63
+ if (fn) {
64
+ const [r, g, b, a = "1"] = fn[1].split(",").map((p) => p.trim());
65
+ return { r: Number(r), g: Number(g), b: Number(b), a: Number(a) };
66
+ }
67
+ throw new Error(`Unsupported colour syntax: ${v}`);
68
+ }
69
+
70
+ function over(top: Rgba, base: Rgba): Rgba {
71
+ const a = top.a + base.a * (1 - top.a);
72
+ const mix = (t: number, b: number) => (t * top.a + b * base.a * (1 - top.a)) / a;
73
+ return { r: mix(top.r, base.r), g: mix(top.g, base.g), b: mix(top.b, base.b), a };
74
+ }
75
+
76
+ function linearize(channel: number): number {
77
+ const s = channel / 255;
78
+ return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
79
+ }
80
+
81
+ function luminance({ r, g, b }: Rgba): number {
82
+ return 0.2126 * linearize(r) + 0.7152 * linearize(g) + 0.0722 * linearize(b);
83
+ }
84
+
85
+ function contrast(a: Rgba, b: Rgba): number {
86
+ const [hi, lo] = [luminance(a), luminance(b)].toSorted((x, y) => y - x);
87
+ return (hi + 0.05) / (lo + 0.05);
88
+ }
89
+
90
+ const MIN_TEXT = 4.5;
91
+ /** Known and accepted: subtle hover text is below AA for some roles. A floor, not a pass. */
92
+ const MIN_HOVER_TEXT = 4.2;
93
+ const modes: Mode[] = ["light", "dark"];
94
+ const intents = ["info", "success", "warning", "danger"] as const;
95
+ const alertVariantFor = { info: "info", success: "success", warning: "warning", danger: "error" };
96
+ const pages = ["--card", "--background"] as const;
97
+
98
+ describe.each(modes)("semantic colour contrast (%s)", (mode) => {
99
+ const vars = variablesFor(mode);
100
+ const color = (name: string) => parseColor(`var(${name})`, vars);
101
+ /** Foreground drawn on a translucent surface that sits on a page colour. */
102
+ const pair = (fg: string, surface: string, page: string) => {
103
+ const base = color(page);
104
+ const bg = over(color(surface), base);
105
+ return contrast(over(color(fg), bg), bg);
106
+ };
107
+
108
+ it("resolves the page colours to opaque values", () => {
109
+ for (const page of pages) expect(color(page).a).toBe(1);
110
+ });
111
+
112
+ describe.each(intents)("%s", (intent) => {
113
+ const role = (name: string) => `--${intent}-${name}`;
114
+
115
+ it("the contrast role meets 4.5:1 on solid", () => {
116
+ expect(contrast(color(role("contrast")), color(role("solid")))).toBeGreaterThanOrEqual(
117
+ MIN_TEXT,
118
+ );
119
+ });
120
+
121
+ it("the contrast role meets 4.5:1 on solid-hover", () => {
122
+ expect(contrast(color(role("contrast")), color(role("solid-hover")))).toBeGreaterThanOrEqual(
123
+ MIN_TEXT,
124
+ );
125
+ });
126
+
127
+ it.each(pages)("text meets 4.5:1 on surface over %s", (page) => {
128
+ expect(pair(role("text"), role("surface"), page)).toBeGreaterThanOrEqual(MIN_TEXT);
129
+ });
130
+
131
+ it.each(pages)(
132
+ "text stays above the documented hover floor on surface-hover over %s",
133
+ (page) => {
134
+ expect(pair(role("text"), role("surface-hover"), page)).toBeGreaterThanOrEqual(
135
+ MIN_HOVER_TEXT,
136
+ );
137
+ },
138
+ );
139
+
140
+ const variant = alertVariantFor[intent];
141
+
142
+ it.each(pages)("alert foreground meets 4.5:1 on alert background over %s", (page) => {
143
+ expect(
144
+ pair(`--alert-${variant}-foreground`, `--alert-${variant}-background`, page),
145
+ ).toBeGreaterThanOrEqual(MIN_TEXT);
146
+ });
147
+
148
+ it.each(pages)("alert description meets 4.5:1 on alert background over %s", (page) => {
149
+ expect(
150
+ pair(`--alert-${variant}-foreground-muted`, `--alert-${variant}-background`, page),
151
+ ).toBeGreaterThanOrEqual(MIN_TEXT);
152
+ });
153
+ });
154
+ });
@@ -31,12 +31,12 @@ declare namespace Root {
31
31
  }
32
32
 
33
33
 
34
- declare namespace Title {
34
+ declare namespace Image {
35
35
  var displayName: string;
36
36
  }
37
37
 
38
38
 
39
- declare namespace Description {
39
+ declare namespace Fallback {
40
40
  var displayName: string;
41
41
  }
42
42
 
@@ -46,32 +46,37 @@ declare namespace Root {
46
46
  }
47
47
 
48
48
 
49
- declare namespace List {
49
+ declare namespace Header {
50
50
  var displayName: string;
51
51
  }
52
52
 
53
53
 
54
- declare namespace Tab {
54
+ declare namespace Body {
55
55
  var displayName: string;
56
56
  }
57
57
 
58
58
 
59
- declare namespace Panel {
59
+ declare namespace Footer {
60
60
  var displayName: string;
61
61
  }
62
62
 
63
63
 
64
- declare namespace Root {
64
+ declare namespace Row {
65
65
  var displayName: string;
66
66
  }
67
67
 
68
68
 
69
- declare namespace Image {
69
+ declare namespace Head {
70
70
  var displayName: string;
71
71
  }
72
72
 
73
73
 
74
- declare namespace Fallback {
74
+ declare namespace Cell {
75
+ var displayName: string;
76
+ }
77
+
78
+
79
+ declare namespace Caption {
75
80
  var displayName: string;
76
81
  }
77
82
 
@@ -86,47 +91,47 @@ declare namespace Header {
86
91
  }
87
92
 
88
93
 
89
- declare namespace Body {
94
+ declare namespace Content {
90
95
  var displayName: string;
91
96
  }
92
97
 
93
98
 
94
- declare namespace Footer {
99
+ declare namespace Root {
95
100
  var displayName: string;
96
101
  }
97
102
 
98
103
 
99
- declare namespace Row {
104
+ declare namespace Trigger {
100
105
  var displayName: string;
101
106
  }
102
107
 
103
108
 
104
- declare namespace Head {
109
+ declare namespace Close {
105
110
  var displayName: string;
106
111
  }
107
112
 
108
113
 
109
- declare namespace Cell {
114
+ declare namespace Content {
110
115
  var displayName: string;
111
116
  }
112
117
 
113
118
 
114
- declare namespace Caption {
119
+ declare namespace Header {
115
120
  var displayName: string;
116
121
  }
117
122
 
118
123
 
119
- declare namespace Root {
124
+ declare namespace Footer {
120
125
  var displayName: string;
121
126
  }
122
127
 
123
128
 
124
- declare namespace Header {
129
+ declare namespace Title {
125
130
  var displayName: string;
126
131
  }
127
132
 
128
133
 
129
- declare namespace Content {
134
+ declare namespace Description {
130
135
  var displayName: string;
131
136
  }
132
137
 
@@ -136,192 +141,197 @@ declare namespace Root {
136
141
  }
137
142
 
138
143
 
139
- declare namespace Trigger {
144
+ declare namespace Legend {
140
145
  var displayName: string;
141
146
  }
142
147
 
143
148
 
144
- declare namespace Close {
149
+ declare namespace ComboboxRoot {
145
150
  var displayName: string;
146
151
  }
147
152
 
148
153
 
149
- declare namespace Content {
154
+ declare namespace ComboboxInput {
150
155
  var displayName: string;
151
156
  }
152
157
 
153
158
 
154
- declare namespace Header {
159
+ declare namespace ComboboxTrigger {
155
160
  var displayName: string;
156
161
  }
157
162
 
158
163
 
159
- declare namespace Footer {
164
+ declare namespace ComboboxInputGroup {
160
165
  var displayName: string;
161
166
  }
162
167
 
163
168
 
164
- declare namespace Title {
169
+ declare namespace ComboboxContent {
165
170
  var displayName: string;
166
171
  }
167
172
 
168
173
 
169
- declare namespace Description {
174
+ declare namespace ComboboxList {
170
175
  var displayName: string;
171
176
  }
172
177
 
173
178
 
174
- declare namespace Root {
179
+ declare namespace ComboboxItem {
175
180
  var displayName: string;
176
181
  }
177
182
 
178
183
 
179
- declare namespace Label {
184
+ declare namespace ComboboxEmpty {
180
185
  var displayName: string;
181
186
  }
182
187
 
183
188
 
184
- declare namespace Control {
189
+ declare namespace ComboboxGroup {
185
190
  var displayName: string;
186
191
  }
187
192
 
188
193
 
189
- declare namespace Description {
194
+ declare namespace ComboboxGroupLabel {
190
195
  var displayName: string;
191
196
  }
192
197
 
193
198
 
194
- declare namespace Error {
199
+ declare namespace ComboboxClear {
195
200
  var displayName: string;
196
201
  }
197
202
 
198
203
 
199
- declare namespace Validity {
204
+ declare namespace ComboboxChips {
200
205
  var displayName: string;
201
206
  }
202
207
 
203
208
 
204
- declare namespace Root {
209
+ declare namespace ComboboxChip {
205
210
  var displayName: string;
206
211
  }
207
212
 
208
213
 
209
- declare namespace Legend {
214
+ declare namespace ComboboxChipRemove {
210
215
  var displayName: string;
211
216
  }
212
217
 
213
218
 
214
- declare namespace Root {
219
+ declare namespace ComboboxValue {
215
220
  var displayName: string;
216
221
  }
217
222
 
218
223
 
219
- declare namespace Trigger {
224
+ declare namespace ComboboxStatus {
220
225
  var displayName: string;
221
226
  }
222
227
 
223
228
 
224
- declare namespace Content {
229
+ declare namespace ComboboxCollection {
225
230
  var displayName: string;
226
231
  }
227
232
 
228
233
 
229
- declare namespace Item {
234
+ declare namespace Root {
230
235
  var displayName: string;
231
236
  }
232
237
 
233
238
 
234
- declare namespace LinkItem {
239
+ declare namespace Label {
235
240
  var displayName: string;
236
241
  }
237
242
 
238
243
 
239
- declare namespace CheckboxItem {
244
+ declare namespace Control {
240
245
  var displayName: string;
241
246
  }
242
247
 
243
248
 
244
- declare namespace CheckboxItemIndicator {
249
+ declare namespace Description {
245
250
  var displayName: string;
246
251
  }
247
252
 
248
253
 
249
- declare namespace RadioItem {
254
+ declare namespace Error {
250
255
  var displayName: string;
251
256
  }
252
257
 
253
258
 
254
- declare namespace RadioItemIndicator {
259
+ declare namespace Validity {
255
260
  var displayName: string;
256
261
  }
257
262
 
258
263
 
259
- declare namespace RadioGroup {
264
+ declare namespace Root {
260
265
  var displayName: string;
261
266
  }
262
267
 
263
268
 
264
- declare namespace Group {
269
+ declare namespace Trigger {
265
270
  var displayName: string;
266
271
  }
267
272
 
268
273
 
269
- declare namespace GroupLabel {
274
+ declare namespace Content {
270
275
  var displayName: string;
271
276
  }
272
277
 
273
278
 
274
- declare namespace MenuSeparator {
279
+ declare namespace Item {
275
280
  var displayName: string;
276
281
  }
277
282
 
278
283
 
279
- declare namespace SubmenuRoot {
284
+ declare namespace LinkItem {
280
285
  var displayName: string;
281
286
  }
282
287
 
283
288
 
284
- declare namespace SubmenuTrigger {
289
+ declare namespace CheckboxItem {
285
290
  var displayName: string;
286
291
  }
287
292
 
288
293
 
289
- declare namespace Root {
294
+ declare namespace CheckboxItemIndicator {
290
295
  var displayName: string;
291
296
  }
292
297
 
293
298
 
294
- declare namespace Trigger {
299
+ declare namespace RadioItem {
295
300
  var displayName: string;
296
301
  }
297
302
 
298
303
 
299
- declare namespace Close {
304
+ declare namespace RadioItemIndicator {
300
305
  var displayName: string;
301
306
  }
302
307
 
303
308
 
304
- declare namespace Content {
309
+ declare namespace RadioGroup {
305
310
  var displayName: string;
306
311
  }
307
312
 
308
313
 
309
- declare namespace Header {
314
+ declare namespace Group {
310
315
  var displayName: string;
311
316
  }
312
317
 
313
318
 
314
- declare namespace Footer {
319
+ declare namespace GroupLabel {
315
320
  var displayName: string;
316
321
  }
317
322
 
318
323
 
319
- declare namespace Title {
324
+ declare namespace MenuSeparator {
320
325
  var displayName: string;
321
326
  }
322
327
 
323
328
 
324
- declare namespace Description {
329
+ declare namespace SubmenuRoot {
330
+ var displayName: string;
331
+ }
332
+
333
+
334
+ declare namespace SubmenuTrigger {
325
335
  var displayName: string;
326
336
  }
327
337
 
@@ -346,47 +356,62 @@ declare namespace Separator {
346
356
  }
347
357
 
348
358
 
349
- declare namespace SelectRoot {
359
+ declare namespace Root {
350
360
  var displayName: string;
351
361
  }
352
362
 
353
363
 
354
- declare namespace SelectTrigger {
364
+ declare namespace Trigger {
355
365
  var displayName: string;
356
366
  }
357
367
 
358
368
 
359
- declare namespace SelectValue {
369
+ declare namespace Close {
360
370
  var displayName: string;
361
371
  }
362
372
 
363
373
 
364
- declare namespace SelectContent {
374
+ declare namespace Content {
365
375
  var displayName: string;
366
376
  }
367
377
 
368
378
 
369
- declare namespace SelectItem {
379
+ declare namespace Header {
370
380
  var displayName: string;
371
381
  }
372
382
 
373
383
 
374
- declare namespace SelectGroup {
384
+ declare namespace Footer {
375
385
  var displayName: string;
376
386
  }
377
387
 
378
388
 
379
- declare namespace SelectGroupLabel {
389
+ declare namespace Title {
380
390
  var displayName: string;
381
391
  }
382
392
 
383
393
 
384
- declare namespace SelectSeparator {
394
+ declare namespace Description {
385
395
  var displayName: string;
386
396
  }
387
397
 
388
398
 
389
- declare namespace Provider {
399
+ declare namespace Root {
400
+ var displayName: string;
401
+ }
402
+
403
+
404
+ declare namespace List {
405
+ var displayName: string;
406
+ }
407
+
408
+
409
+ declare namespace Tab {
410
+ var displayName: string;
411
+ }
412
+
413
+
414
+ declare namespace Panel {
390
415
  var displayName: string;
391
416
  }
392
417
 
@@ -396,97 +421,107 @@ declare namespace Root {
396
421
  }
397
422
 
398
423
 
424
+ declare namespace Title {
425
+ var displayName: string;
426
+ }
427
+
428
+
429
+ declare namespace Description {
430
+ var displayName: string;
431
+ }
432
+
433
+
399
434
  declare namespace Trigger {
400
435
  var displayName: string;
401
436
  }
402
437
 
403
438
 
404
- declare namespace Content {
439
+ declare namespace Settings {
405
440
  var displayName: string;
406
441
  }
407
442
 
408
443
 
409
- declare namespace ComboboxRoot {
444
+ declare namespace Provider {
410
445
  var displayName: string;
411
446
  }
412
447
 
413
448
 
414
- declare namespace ComboboxInput {
449
+ declare namespace Root {
415
450
  var displayName: string;
416
451
  }
417
452
 
418
453
 
419
- declare namespace ComboboxTrigger {
454
+ declare namespace Header {
420
455
  var displayName: string;
421
456
  }
422
457
 
423
458
 
424
- declare namespace ComboboxInputGroup {
459
+ declare namespace ClearAll {
425
460
  var displayName: string;
426
461
  }
427
462
 
428
463
 
429
- declare namespace ComboboxContent {
464
+ declare namespace Sections {
430
465
  var displayName: string;
431
466
  }
432
467
 
433
468
 
434
- declare namespace ComboboxList {
469
+ declare namespace Provider {
435
470
  var displayName: string;
436
471
  }
437
472
 
438
473
 
439
- declare namespace ComboboxItem {
474
+ declare namespace Root {
440
475
  var displayName: string;
441
476
  }
442
477
 
443
478
 
444
- declare namespace ComboboxEmpty {
479
+ declare namespace Trigger {
445
480
  var displayName: string;
446
481
  }
447
482
 
448
483
 
449
- declare namespace ComboboxGroup {
484
+ declare namespace Content {
450
485
  var displayName: string;
451
486
  }
452
487
 
453
488
 
454
- declare namespace ComboboxGroupLabel {
489
+ declare namespace SelectRoot {
455
490
  var displayName: string;
456
491
  }
457
492
 
458
493
 
459
- declare namespace ComboboxClear {
494
+ declare namespace SelectTrigger {
460
495
  var displayName: string;
461
496
  }
462
497
 
463
498
 
464
- declare namespace ComboboxChips {
499
+ declare namespace SelectValue {
465
500
  var displayName: string;
466
501
  }
467
502
 
468
503
 
469
- declare namespace ComboboxChip {
504
+ declare namespace SelectContent {
470
505
  var displayName: string;
471
506
  }
472
507
 
473
508
 
474
- declare namespace ComboboxChipRemove {
509
+ declare namespace SelectItem {
475
510
  var displayName: string;
476
511
  }
477
512
 
478
513
 
479
- declare namespace ComboboxValue {
514
+ declare namespace SelectGroup {
480
515
  var displayName: string;
481
516
  }
482
517
 
483
518
 
484
- declare namespace ComboboxStatus {
519
+ declare namespace SelectGroupLabel {
485
520
  var displayName: string;
486
521
  }
487
522
 
488
523
 
489
- declare namespace ComboboxCollection {
524
+ declare namespace SelectSeparator {
490
525
  var displayName: string;
491
526
  }
492
527