@vonage/vivid 4.12.0 → 4.13.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 (124) hide show
  1. package/custom-elements.json +2339 -288
  2. package/lib/accordion/accordion.d.ts +21 -2
  3. package/lib/accordion-item/accordion-item.d.ts +6 -2
  4. package/lib/calendar/calendar.d.ts +1 -1
  5. package/lib/date-picker/date-picker.d.ts +1 -0
  6. package/lib/file-picker/file-picker.d.ts +6 -0
  7. package/lib/menu/menu.d.ts +16 -3
  8. package/lib/menu-item/menu-item.d.ts +10 -2
  9. package/lib/option/option.d.ts +27 -7
  10. package/lib/radio/radio.d.ts +12 -2
  11. package/lib/radio/radio.form-associated.d.ts +10 -0
  12. package/lib/radio-group/radio-group.d.ts +20 -2
  13. package/lib/switch/switch.d.ts +5 -2
  14. package/lib/switch/switch.form-associated.d.ts +10 -0
  15. package/lib/tab/tab.d.ts +3 -2
  16. package/lib/tab-panel/tab-panel.d.ts +2 -2
  17. package/lib/tabs/tabs.d.ts +33 -11
  18. package/lib/text-area/text-area.d.ts +25 -3
  19. package/lib/text-area/text-field.form-associated.d.ts +10 -0
  20. package/lib/text-field/text-field.d.ts +28 -3
  21. package/lib/text-field/text-field.form-associated.d.ts +10 -0
  22. package/package.json +1 -1
  23. package/shared/date-picker/date-picker-base.d.ts +1 -0
  24. package/shared/definition.cjs +29 -72
  25. package/shared/definition.js +30 -73
  26. package/shared/definition11.cjs +1 -1
  27. package/shared/definition11.js +1 -1
  28. package/shared/definition16.cjs +1 -2
  29. package/shared/definition16.js +1 -2
  30. package/shared/definition17.cjs +3 -3
  31. package/shared/definition17.js +3 -3
  32. package/shared/definition18.cjs +6 -1
  33. package/shared/definition18.js +6 -1
  34. package/shared/definition19.cjs +17 -8
  35. package/shared/definition19.js +17 -8
  36. package/shared/definition2.cjs +154 -187
  37. package/shared/definition2.js +157 -190
  38. package/shared/definition20.cjs +3 -2
  39. package/shared/definition20.js +3 -2
  40. package/shared/definition21.cjs +1 -1
  41. package/shared/definition21.js +1 -1
  42. package/shared/definition24.cjs +1 -1
  43. package/shared/definition24.js +1 -1
  44. package/shared/definition25.cjs +24 -3
  45. package/shared/definition25.js +24 -3
  46. package/shared/definition29.cjs +358 -559
  47. package/shared/definition29.js +359 -560
  48. package/shared/definition30.cjs +2 -0
  49. package/shared/definition30.js +2 -0
  50. package/shared/definition35.cjs +223 -3
  51. package/shared/definition35.js +223 -3
  52. package/shared/definition36.cjs +149 -14
  53. package/shared/definition36.js +150 -15
  54. package/shared/definition40.cjs +226 -399
  55. package/shared/definition40.js +229 -402
  56. package/shared/definition42.cjs +3 -2
  57. package/shared/definition42.js +3 -2
  58. package/shared/definition43.cjs +1 -0
  59. package/shared/definition43.js +1 -0
  60. package/shared/definition44.cjs +1 -1
  61. package/shared/definition44.js +1 -1
  62. package/shared/definition46.cjs +1 -1
  63. package/shared/definition46.js +1 -1
  64. package/shared/definition47.cjs +8 -16
  65. package/shared/definition47.js +4 -12
  66. package/shared/definition49.cjs +64 -89
  67. package/shared/definition49.js +66 -91
  68. package/shared/definition5.cjs +1 -1
  69. package/shared/definition5.js +1 -1
  70. package/shared/definition50.cjs +1 -11
  71. package/shared/definition50.js +1 -11
  72. package/shared/definition51.cjs +5 -15
  73. package/shared/definition51.js +6 -16
  74. package/shared/definition52.cjs +284 -20
  75. package/shared/definition52.js +288 -24
  76. package/shared/definition55.cjs +160 -180
  77. package/shared/definition55.js +160 -180
  78. package/shared/definition56.cjs +3 -307
  79. package/shared/definition56.js +5 -309
  80. package/shared/definition57.cjs +34 -11
  81. package/shared/definition57.js +30 -7
  82. package/shared/definition61.cjs +1 -1
  83. package/shared/definition61.js +1 -1
  84. package/shared/definition62.cjs +17 -8
  85. package/shared/definition62.js +17 -8
  86. package/shared/definition64.cjs +18 -7
  87. package/shared/definition64.js +19 -8
  88. package/shared/form-associated.cjs +1 -1
  89. package/shared/form-associated.js +1 -1
  90. package/shared/icon.cjs +1 -1
  91. package/shared/icon.js +1 -1
  92. package/shared/index.cjs +1 -0
  93. package/shared/index.js +1 -1
  94. package/shared/key-codes.cjs +1 -94
  95. package/shared/key-codes.js +2 -89
  96. package/shared/key-codes2.cjs +87 -1
  97. package/shared/key-codes2.js +83 -2
  98. package/shared/listbox.cjs +204 -10
  99. package/shared/listbox.js +200 -6
  100. package/shared/{direction.cjs → localization.cjs} +12 -3
  101. package/shared/{direction.js → localization.js} +12 -3
  102. package/shared/numbers.cjs +0 -12
  103. package/shared/numbers.js +1 -12
  104. package/shared/presentationDate.cjs +22 -8
  105. package/shared/presentationDate.js +16 -2
  106. package/shared/radio.cjs +92 -117
  107. package/shared/radio.js +93 -118
  108. package/shared/slider.template.cjs +2 -15
  109. package/shared/slider.template.js +2 -14
  110. package/shared/strings.cjs +26 -0
  111. package/shared/strings.js +25 -1
  112. package/shared/text-field2.cjs +538 -194
  113. package/shared/text-field2.js +539 -195
  114. package/styles/core/all.css +21 -1
  115. package/styles/core/theme.css +21 -1
  116. package/styles/core/typography.css +1 -1
  117. package/styles/tokens/theme-dark.css +4 -4
  118. package/styles/tokens/theme-light.css +4 -4
  119. package/styles/tokens/vivid-2-compat.css +1 -1
  120. package/vivid.api.json +44 -0
  121. package/shared/Reflector.cjs +0 -71
  122. package/shared/Reflector.js +0 -69
  123. package/shared/listbox-option.cjs +0 -204
  124. package/shared/listbox-option.js +0 -201
@@ -2,15 +2,12 @@
2
2
 
3
3
  const index = require('./index.cjs');
4
4
  const definition = require('./definition27.cjs');
5
- const keyCodes$1 = require('./key-codes2.cjs');
5
+ const keyCodes = require('./key-codes.cjs');
6
6
  const affix = require('./affix.cjs');
7
7
  const applyMixins = require('./apply-mixins.cjs');
8
- const startEnd = require('./start-end.cjs');
9
- const direction = require('./direction.cjs');
10
- const keyCodes = require('./key-codes.cjs');
8
+ const localization = require('./localization.cjs');
11
9
  const icon = require('./icon.cjs');
12
10
  const anchored = require('./anchored.cjs');
13
- const dom = require('./dom.cjs');
14
11
  const slotted = require('./slotted.cjs');
15
12
  const when = require('./when.cjs');
16
13
  const classNames = require('./class-names.cjs');
@@ -43,533 +40,11 @@ const roleForMenuItem = {
43
40
  };
44
41
 
45
42
  /**
46
- * A Switch Custom HTML Element.
47
- * Implements {@link https://www.w3.org/TR/wai-aria-1.1/#menuitem | ARIA menuitem }, {@link https://www.w3.org/TR/wai-aria-1.1/#menuitemcheckbox | ARIA menuitemcheckbox}, or {@link https://www.w3.org/TR/wai-aria-1.1/#menuitemradio | ARIA menuitemradio }.
48
- *
49
- * @slot checked-indicator - The checked indicator
50
- * @slot radio-indicator - The radio indicator
51
- * @slot start - Content which can be provided before the menu item content
52
- * @slot end - Content which can be provided after the menu item content
53
- * @slot - The default slot for menu item content
54
- * @slot expand-collapse-indicator - The expand/collapse indicator
55
- * @slot submenu - Used to nest menu's within menu items
56
- * @csspart input-container - The element representing the visual checked or radio indicator
57
- * @csspart checkbox - The element wrapping the `menuitemcheckbox` indicator
58
- * @csspart radio - The element wrapping the `menuitemradio` indicator
59
- * @csspart content - The element wrapping the menu item content
60
- * @csspart expand-collapse-glyph-container - The element wrapping the expand collapse element
61
- * @csspart expand-collapse - The expand/collapse element
62
- * @csspart submenu-region - The container for the submenu, used for positioning
63
- * @fires expanded-change - Fires a custom 'expanded-change' event when the expanded state changes
64
- * @fires change - Fires a custom 'change' event when a non-submenu item with a role of `menuitemcheckbox`, `menuitemradio`, or `menuitem` is invoked
65
- *
66
- * @public
67
- */
68
- let MenuItem$1 = class MenuItem extends index.FoundationElement {
69
- constructor() {
70
- super(...arguments);
71
- /**
72
- * The role of the element.
73
- *
74
- * @public
75
- * @remarks
76
- * HTML Attribute: role
77
- */
78
- this.role = MenuItemRole$1.menuitem;
79
- /**
80
- * @internal
81
- */
82
- this.hasSubmenu = false;
83
- /**
84
- * Track current direction to pass to the anchored region
85
- *
86
- * @internal
87
- */
88
- this.currentDirection = direction.Direction.ltr;
89
- this.focusSubmenuOnLoad = false;
90
- /**
91
- * @internal
92
- */
93
- this.handleMenuItemKeyDown = (e) => {
94
- if (e.defaultPrevented) {
95
- return false;
96
- }
97
- switch (e.key) {
98
- case keyCodes.keyEnter:
99
- case keyCodes.keySpace:
100
- this.invoke();
101
- return false;
102
- case keyCodes.keyArrowRight:
103
- //open/focus on submenu
104
- this.expandAndFocus();
105
- return false;
106
- case keyCodes.keyArrowLeft:
107
- //close submenu
108
- if (this.expanded) {
109
- this.expanded = false;
110
- this.focus();
111
- return false;
112
- }
113
- }
114
- return true;
115
- };
116
- /**
117
- * @internal
118
- */
119
- this.handleMenuItemClick = (e) => {
120
- if (e.defaultPrevented || this.disabled) {
121
- return false;
122
- }
123
- this.invoke();
124
- return false;
125
- };
126
- /**
127
- * @internal
128
- */
129
- this.submenuLoaded = () => {
130
- if (!this.focusSubmenuOnLoad) {
131
- return;
132
- }
133
- this.focusSubmenuOnLoad = false;
134
- if (this.hasSubmenu) {
135
- this.submenu.focus();
136
- this.setAttribute("tabindex", "-1");
137
- }
138
- };
139
- /**
140
- * @internal
141
- */
142
- this.handleMouseOver = (e) => {
143
- if (this.disabled || !this.hasSubmenu || this.expanded) {
144
- return false;
145
- }
146
- this.expanded = true;
147
- return false;
148
- };
149
- /**
150
- * @internal
151
- */
152
- this.handleMouseOut = (e) => {
153
- if (!this.expanded || this.contains(document.activeElement)) {
154
- return false;
155
- }
156
- this.expanded = false;
157
- return false;
158
- };
159
- /**
160
- * @internal
161
- */
162
- this.expandAndFocus = () => {
163
- if (!this.hasSubmenu) {
164
- return;
165
- }
166
- this.focusSubmenuOnLoad = true;
167
- this.expanded = true;
168
- };
169
- /**
170
- * @internal
171
- */
172
- this.invoke = () => {
173
- if (this.disabled) {
174
- return;
175
- }
176
- switch (this.role) {
177
- case MenuItemRole$1.menuitemcheckbox:
178
- this.checked = !this.checked;
179
- break;
180
- case MenuItemRole$1.menuitem:
181
- // update submenu
182
- this.updateSubmenu();
183
- if (this.hasSubmenu) {
184
- this.expandAndFocus();
185
- }
186
- else {
187
- this.$emit("change");
188
- }
189
- break;
190
- case MenuItemRole$1.menuitemradio:
191
- if (!this.checked) {
192
- this.checked = true;
193
- }
194
- break;
195
- }
196
- };
197
- /**
198
- * Gets the submenu element if any
199
- *
200
- * @internal
201
- */
202
- this.updateSubmenu = () => {
203
- this.submenu = this.domChildren().find((element) => {
204
- return element.getAttribute("role") === "menu";
205
- });
206
- this.hasSubmenu = this.submenu === undefined ? false : true;
207
- };
208
- }
209
- expandedChanged(oldValue) {
210
- if (this.$fastController.isConnected) {
211
- if (this.submenu === undefined) {
212
- return;
213
- }
214
- if (this.expanded === false) {
215
- this.submenu.collapseExpandedItem();
216
- }
217
- else {
218
- this.currentDirection = direction.getDirection(this);
219
- }
220
- this.$emit("expanded-change", this, { bubbles: false });
221
- }
222
- }
223
- checkedChanged(oldValue, newValue) {
224
- if (this.$fastController.isConnected) {
225
- this.$emit("change");
226
- }
227
- }
228
- /**
229
- * @internal
230
- */
231
- connectedCallback() {
232
- super.connectedCallback();
233
- index.DOM.queueUpdate(() => {
234
- this.updateSubmenu();
235
- });
236
- if (!this.startColumnCount) {
237
- this.startColumnCount = 1;
238
- }
239
- this.observer = new MutationObserver(this.updateSubmenu);
240
- }
241
- /**
242
- * @internal
243
- */
244
- disconnectedCallback() {
245
- super.disconnectedCallback();
246
- this.submenu = undefined;
247
- if (this.observer !== undefined) {
248
- this.observer.disconnect();
249
- this.observer = undefined;
250
- }
251
- }
252
- /**
253
- * get an array of valid DOM children
254
- */
255
- domChildren() {
256
- return Array.from(this.children).filter(child => !child.hasAttribute("hidden"));
257
- }
258
- };
259
- index.__decorate([
260
- index.attr({ mode: "boolean" })
261
- ], MenuItem$1.prototype, "disabled", void 0);
262
- index.__decorate([
263
- index.attr({ mode: "boolean" })
264
- ], MenuItem$1.prototype, "expanded", void 0);
265
- index.__decorate([
266
- index.observable
267
- ], MenuItem$1.prototype, "startColumnCount", void 0);
268
- index.__decorate([
269
- index.attr
270
- ], MenuItem$1.prototype, "role", void 0);
271
- index.__decorate([
272
- index.attr({ mode: "boolean" })
273
- ], MenuItem$1.prototype, "checked", void 0);
274
- index.__decorate([
275
- index.observable
276
- ], MenuItem$1.prototype, "submenuRegion", void 0);
277
- index.__decorate([
278
- index.observable
279
- ], MenuItem$1.prototype, "hasSubmenu", void 0);
280
- index.__decorate([
281
- index.observable
282
- ], MenuItem$1.prototype, "currentDirection", void 0);
283
- index.__decorate([
284
- index.observable
285
- ], MenuItem$1.prototype, "submenu", void 0);
286
- applyMixins.applyMixins(MenuItem$1, startEnd.StartEnd);
287
-
288
- /**
289
- * A Menu Custom HTML Element.
290
- * Implements the {@link https://www.w3.org/TR/wai-aria-1.1/#menu | ARIA menu }.
291
- *
292
- * @slot - The default slot for the menu items
293
- *
294
- * @public
43
+ * A test that ensures that all arguments are HTML Elements
295
44
  */
296
- let Menu$1 = class Menu extends index.FoundationElement {
297
- constructor() {
298
- super(...arguments);
299
- this.expandedItem = null;
300
- /**
301
- * The index of the focusable element in the items array
302
- * defaults to -1
303
- */
304
- this.focusIndex = -1;
305
- /**
306
- * @internal
307
- */
308
- this.isNestedMenu = () => {
309
- return (this.parentElement !== null &&
310
- dom.isHTMLElement(this.parentElement) &&
311
- this.parentElement.getAttribute("role") === "menuitem");
312
- };
313
- /**
314
- * if focus is moving out of the menu, reset to a stable initial state
315
- * @internal
316
- */
317
- this.handleFocusOut = (e) => {
318
- if (!this.contains(e.relatedTarget) && this.menuItems !== undefined) {
319
- this.collapseExpandedItem();
320
- // find our first focusable element
321
- const focusIndex = this.menuItems.findIndex(this.isFocusableElement);
322
- // set the current focus index's tabindex to -1
323
- this.menuItems[this.focusIndex].setAttribute("tabindex", "-1");
324
- // set the first focusable element tabindex to 0
325
- this.menuItems[focusIndex].setAttribute("tabindex", "0");
326
- // set the focus index
327
- this.focusIndex = focusIndex;
328
- }
329
- };
330
- this.handleItemFocus = (e) => {
331
- const targetItem = e.target;
332
- if (this.menuItems !== undefined &&
333
- targetItem !== this.menuItems[this.focusIndex]) {
334
- this.menuItems[this.focusIndex].setAttribute("tabindex", "-1");
335
- this.focusIndex = this.menuItems.indexOf(targetItem);
336
- targetItem.setAttribute("tabindex", "0");
337
- }
338
- };
339
- this.handleExpandedChanged = (e) => {
340
- if (e.defaultPrevented ||
341
- e.target === null ||
342
- this.menuItems === undefined ||
343
- this.menuItems.indexOf(e.target) < 0) {
344
- return;
345
- }
346
- e.preventDefault();
347
- const changedItem = e.target;
348
- // closing an expanded item without opening another
349
- if (this.expandedItem !== null &&
350
- changedItem === this.expandedItem &&
351
- changedItem.expanded === false) {
352
- this.expandedItem = null;
353
- return;
354
- }
355
- if (changedItem.expanded) {
356
- if (this.expandedItem !== null && this.expandedItem !== changedItem) {
357
- this.expandedItem.expanded = false;
358
- }
359
- this.menuItems[this.focusIndex].setAttribute("tabindex", "-1");
360
- this.expandedItem = changedItem;
361
- this.focusIndex = this.menuItems.indexOf(changedItem);
362
- changedItem.setAttribute("tabindex", "0");
363
- }
364
- };
365
- this.removeItemListeners = () => {
366
- if (this.menuItems !== undefined) {
367
- this.menuItems.forEach((item) => {
368
- item.removeEventListener("expanded-change", this.handleExpandedChanged);
369
- item.removeEventListener("focus", this.handleItemFocus);
370
- });
371
- }
372
- };
373
- this.setItems = () => {
374
- const newItems = this.domChildren();
375
- this.removeItemListeners();
376
- this.menuItems = newItems;
377
- const menuItems = this.menuItems.filter(this.isMenuItemElement);
378
- // if our focus index is not -1 we have items
379
- if (menuItems.length) {
380
- this.focusIndex = 0;
381
- }
382
- function elementIndent(el) {
383
- const role = el.getAttribute("role");
384
- const startSlot = el.querySelector("[slot=start]");
385
- if (role !== MenuItemRole$1.menuitem && startSlot === null) {
386
- return 1;
387
- }
388
- else if (role === MenuItemRole$1.menuitem && startSlot !== null) {
389
- return 1;
390
- }
391
- else if (role !== MenuItemRole$1.menuitem && startSlot !== null) {
392
- return 2;
393
- }
394
- else {
395
- return 0;
396
- }
397
- }
398
- const indent = menuItems.reduce((accum, current) => {
399
- const elementValue = elementIndent(current);
400
- return accum > elementValue ? accum : elementValue;
401
- }, 0);
402
- menuItems.forEach((item, index) => {
403
- item.setAttribute("tabindex", index === 0 ? "0" : "-1");
404
- item.addEventListener("expanded-change", this.handleExpandedChanged);
405
- item.addEventListener("focus", this.handleItemFocus);
406
- if (item instanceof MenuItem$1 || "startColumnCount" in item) {
407
- item.startColumnCount = indent;
408
- }
409
- });
410
- };
411
- /**
412
- * handle change from child element
413
- */
414
- this.changeHandler = (e) => {
415
- if (this.menuItems === undefined) {
416
- return;
417
- }
418
- const changedMenuItem = e.target;
419
- const changeItemIndex = this.menuItems.indexOf(changedMenuItem);
420
- if (changeItemIndex === -1) {
421
- return;
422
- }
423
- if (changedMenuItem.role === "menuitemradio" &&
424
- changedMenuItem.checked === true) {
425
- for (let i = changeItemIndex - 1; i >= 0; --i) {
426
- const item = this.menuItems[i];
427
- const role = item.getAttribute("role");
428
- if (role === MenuItemRole$1.menuitemradio) {
429
- item.checked = false;
430
- }
431
- if (role === "separator") {
432
- break;
433
- }
434
- }
435
- const maxIndex = this.menuItems.length - 1;
436
- for (let i = changeItemIndex + 1; i <= maxIndex; ++i) {
437
- const item = this.menuItems[i];
438
- const role = item.getAttribute("role");
439
- if (role === MenuItemRole$1.menuitemradio) {
440
- item.checked = false;
441
- }
442
- if (role === "separator") {
443
- break;
444
- }
445
- }
446
- }
447
- };
448
- /**
449
- * check if the item is a menu item
450
- */
451
- this.isMenuItemElement = (el) => {
452
- return (dom.isHTMLElement(el) &&
453
- Menu.focusableElementRoles.hasOwnProperty(el.getAttribute("role")));
454
- };
455
- /**
456
- * check if the item is focusable
457
- */
458
- this.isFocusableElement = (el) => {
459
- return this.isMenuItemElement(el);
460
- };
461
- }
462
- itemsChanged(oldValue, newValue) {
463
- // only update children after the component is connected and
464
- // the setItems has run on connectedCallback
465
- // (menuItems is undefined until then)
466
- if (this.$fastController.isConnected && this.menuItems !== undefined) {
467
- this.setItems();
468
- }
469
- }
470
- /**
471
- * @internal
472
- */
473
- connectedCallback() {
474
- super.connectedCallback();
475
- index.DOM.queueUpdate(() => {
476
- // wait until children have had a chance to
477
- // connect before setting/checking their props/attributes
478
- this.setItems();
479
- });
480
- this.addEventListener("change", this.changeHandler);
481
- }
482
- /**
483
- * @internal
484
- */
485
- disconnectedCallback() {
486
- super.disconnectedCallback();
487
- this.removeItemListeners();
488
- this.menuItems = undefined;
489
- this.removeEventListener("change", this.changeHandler);
490
- }
491
- /**
492
- * Focuses the first item in the menu.
493
- *
494
- * @public
495
- */
496
- focus() {
497
- this.setFocus(0, 1);
498
- }
499
- /**
500
- * Collapses any expanded menu items.
501
- *
502
- * @public
503
- */
504
- collapseExpandedItem() {
505
- if (this.expandedItem !== null) {
506
- this.expandedItem.expanded = false;
507
- this.expandedItem = null;
508
- }
509
- }
510
- /**
511
- * @internal
512
- */
513
- handleMenuKeyDown(e) {
514
- if (e.defaultPrevented || this.menuItems === undefined) {
515
- return;
516
- }
517
- switch (e.key) {
518
- case keyCodes.keyArrowDown:
519
- // go forward one index
520
- this.setFocus(this.focusIndex + 1, 1);
521
- return;
522
- case keyCodes.keyArrowUp:
523
- // go back one index
524
- this.setFocus(this.focusIndex - 1, -1);
525
- return;
526
- case keyCodes.keyEnd:
527
- // set focus on last item
528
- this.setFocus(this.menuItems.length - 1, -1);
529
- return;
530
- case keyCodes.keyHome:
531
- // set focus on first item
532
- this.setFocus(0, 1);
533
- return;
534
- default:
535
- // if we are not handling the event, do not prevent default
536
- return true;
537
- }
538
- }
539
- /**
540
- * get an array of valid DOM children
541
- */
542
- domChildren() {
543
- return Array.from(this.children).filter(child => !child.hasAttribute("hidden"));
544
- }
545
- setFocus(focusIndex, adjustment) {
546
- if (this.menuItems === undefined) {
547
- return;
548
- }
549
- while (focusIndex >= 0 && focusIndex < this.menuItems.length) {
550
- const child = this.menuItems[focusIndex];
551
- if (this.isFocusableElement(child)) {
552
- // change the previous index to -1
553
- if (this.focusIndex > -1 &&
554
- this.menuItems.length >= this.focusIndex - 1) {
555
- this.menuItems[this.focusIndex].setAttribute("tabindex", "-1");
556
- }
557
- // update the focus index
558
- this.focusIndex = focusIndex;
559
- // update the tabindex of next focusable element
560
- child.setAttribute("tabindex", "0");
561
- // focus the element
562
- child.focus();
563
- break;
564
- }
565
- focusIndex += adjustment;
566
- }
567
- }
568
- };
569
- Menu$1.focusableElementRoles = roleForMenuItem;
570
- index.__decorate([
571
- index.observable
572
- ], Menu$1.prototype, "items", void 0);
45
+ function isHTMLElement(...args) {
46
+ return args.every((arg) => arg instanceof HTMLElement);
47
+ }
573
48
 
574
49
  const styles = ":host(:focus-visible){outline:none}:host([disabled]){pointer-events:none}.base{--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.base:where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)){--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: var(--_connotation-color-faint);--_appearance-color-outline: transparent}.base:where(.disabled,:disabled){--_appearance-color-text: var(--vvd-color-neutral-300);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.base:where(.active,:active):where(:not(.disabled,:disabled)){--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: var(--_connotation-color-soft);--_appearance-color-outline: transparent}.base:where(.selected):where(:not(.disabled,:disabled)){--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: var(--_connotation-color-soft);--_appearance-color-outline: transparent}.base:where(.selected):where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)){--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: var(--_connotation-color-dim);--_appearance-color-outline: transparent}.base.connotation-cta{--_connotation-color-primary: var(--vvd-menu-item-cta-primary, var(--vvd-color-cta-500));--_connotation-color-primary-text: var(--vvd-menu-item-cta-primary-text, var(--vvd-color-canvas));--_connotation-color-primary-increment: var(--vvd-menu-item-cta-primary-increment, var(--vvd-color-cta-600));--_connotation-color-firm: var(--vvd-menu-item-cta-firm, var(--vvd-color-cta-600));--_connotation-color-faint: var(--vvd-menu-item-cta-faint, var(--vvd-color-cta-50));--_connotation-color-soft: var(--vvd-menu-item-cta-soft, var(--vvd-color-cta-100));--_connotation-color-pale: var(--vvd-menu-item-cta-pale, var(--vvd-color-cta-300));--_connotation-color-dim: var(--vvd-menu-item-cta-dim, var(--vvd-color-cta-200))}.base:not(.connotation-cta){--_connotation-color-primary: var(--vvd-menu-item-accent-primary, var(--vvd-color-canvas-text));--_connotation-color-primary-text: var(--vvd-menu-item-accent-primary-text, var(--vvd-color-canvas));--_connotation-color-primary-increment: var(--vvd-menu-item-accent-primary-increment, var(--vvd-color-neutral-800));--_connotation-color-firm: var(--vvd-menu-item-accent-firm, var(--vvd-color-canvas-text));--_connotation-color-faint: var(--vvd-menu-item-accent-faint, var(--vvd-color-neutral-50));--_connotation-color-soft: var(--vvd-menu-item-accent-soft, var(--vvd-color-neutral-100));--_connotation-color-pale: var(--vvd-menu-item-accent-pale, var(--vvd-color-neutral-300));--_connotation-color-dim: var(--vvd-menu-item-accent-dim, var(--vvd-color-neutral-200))}.base{display:flex;box-sizing:border-box;align-items:center;background-color:var(--_appearance-color-fill);box-shadow:inset 0 0 0 1px var(--_appearance-color-outline);inline-size:100%}.base:not(.two-lines){gap:12px;min-block-size:calc(1px*(40 + 4*clamp(-1,var(--vvd-size-density, 0),2)));padding-block:8px;padding-inline:12px}.base.two-lines{padding:12px;gap:16px;min-block-size:calc(1px*(40 + 4*clamp(-1,var(--vvd-size-density, 0),2)) + 1px*(24 + 4*clamp(-1,var(--vvd-size-density, 0),2)))}@supports (user-select: none){.base{user-select:none}}.base:not(.disabled){cursor:pointer}:host(:not([role=presentation]):focus-visible) .base{box-shadow:inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:2px solid var(--focus-stroke-color, var(--vvd-color-canvas-text));outline-offset:calc(-2px - var(--focus-inset, 0px));--focus-stroke-gap-color: transparent}.icon{flex-shrink:0;font-size:calc(1px*(40 + 4*clamp(-1,var(--vvd-size-density, 0),2))/2);line-height:1}.action,.decorative{display:flex;place-content:center}.action{color:var(--_appearance-color-text)}.base.trailing .action,.base.has-meta .action{order:2}:host(:not([check-appearance],[aria-checked=true],[disabled])) .action{color:var(--vvd-color-neutral-500)}.base:not(.disabled) .decorative{color:var(--vvd-color-neutral-600)}.base.disabled .decorative{color:var(--vvd-color-neutral-200)}.base.has-meta .decorative{order:1}.chevron{order:3}.text{display:flex;overflow:hidden;flex-direction:column;gap:4px;margin-inline-end:auto}.text-primary,.text-secondary{display:-webkit-box;overflow:hidden;-webkit-box-orient:vertical;font:var(--vvd-typography-base)}.text-primary{font:var(--vvd-typography-base);-webkit-line-clamp:var(--text-primary-line-clamp, 1)}.base:not(.disabled) .text-primary{color:var(--vvd-color-canvas-text)}.base.disabled .text-primary{color:var(--_appearance-color-text)}.base.two-lines .text-primary{font:var(--vvd-typography-base-bold)}.text-secondary{color:var(--vvd-color-neutral-800);font:var(--vvd-typography-base-condensed);-webkit-line-clamp:var(--text-secondary-line-clamp, 1)}.base.two-lines .text-secondary{color:var(--vvd-color-neutral-600)}.base.disabled .text-secondary{color:var(--_appearance-color-text)}.base.selected:not(.disabled) .text-secondary{color:var(--vvd-color-neutral-800)}";
575
50
 
@@ -591,10 +66,88 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
591
66
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
592
67
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
593
68
  var _Menu_instances, triggerBehaviour_get, setupAnchor_fn, updateAnchor_fn, cleanupAnchor_fn, _onAnchorClick;
594
- exports.Menu = class Menu extends Menu$1 {
69
+ exports.Menu = class Menu extends index.FoundationElement {
595
70
  constructor() {
596
- super();
71
+ super(...arguments);
597
72
  __privateAdd(this, _Menu_instances);
73
+ this.expandedItem = null;
74
+ /**
75
+ * The index of the focusable element in the items array
76
+ * defaults to -1
77
+ */
78
+ this.focusIndex = -1;
79
+ /**
80
+ * if focus is moving out of the menu, reset to a stable initial state
81
+ * @internal
82
+ */
83
+ this.handleFocusOut = (e) => {
84
+ if (!this.contains(e.relatedTarget) && this.menuItems !== void 0 && this.menuItems.length) {
85
+ this.collapseExpandedItem();
86
+ const focusIndex = this.menuItems.findIndex(
87
+ this.isFocusableElement
88
+ );
89
+ this.menuItems[this.focusIndex].setAttribute("tabindex", "-1");
90
+ this.menuItems[focusIndex].setAttribute("tabindex", "0");
91
+ this.focusIndex = focusIndex;
92
+ }
93
+ };
94
+ this.handleItemFocus = (e) => {
95
+ const targetItem = e.target;
96
+ if (this.menuItems !== void 0 && targetItem !== this.menuItems[this.focusIndex]) {
97
+ this.menuItems[this.focusIndex].setAttribute("tabindex", "-1");
98
+ this.focusIndex = this.menuItems.indexOf(targetItem);
99
+ targetItem.setAttribute("tabindex", "0");
100
+ }
101
+ };
102
+ this.handleExpandedChanged = (e) => {
103
+ const changedItem = e.target;
104
+ if (this.expandedItem !== null && changedItem === this.expandedItem && changedItem.expanded === false) {
105
+ this.expandedItem = null;
106
+ }
107
+ if (changedItem.expanded) {
108
+ this.expandedItem = changedItem;
109
+ }
110
+ };
111
+ this.removeItemListeners = () => {
112
+ if (this.menuItems !== void 0) {
113
+ this.menuItems.forEach((item) => {
114
+ item.removeEventListener("expanded-change", this.handleExpandedChanged);
115
+ item.removeEventListener(
116
+ "focus",
117
+ this.handleItemFocus
118
+ );
119
+ });
120
+ }
121
+ };
122
+ this.setItems = () => {
123
+ const newItems = this.domChildren();
124
+ this.removeItemListeners();
125
+ this.menuItems = newItems;
126
+ const menuItems = this.menuItems.filter(this.isMenuItemElement);
127
+ if (menuItems.length) {
128
+ this.focusIndex = 0;
129
+ }
130
+ menuItems.forEach((item, index) => {
131
+ item.setAttribute("tabindex", index === 0 ? "0" : "-1");
132
+ item.addEventListener("expanded-change", this.handleExpandedChanged);
133
+ item.addEventListener("focus", this.handleItemFocus);
134
+ });
135
+ };
136
+ /**
137
+ * check if the item is a menu item
138
+ */
139
+ this.isMenuItemElement = (el) => {
140
+ return isHTMLElement(el) && Object.prototype.hasOwnProperty.call(
141
+ exports.Menu.focusableElementRoles,
142
+ el.getAttribute("role")
143
+ );
144
+ };
145
+ /**
146
+ * check if the item is focusable
147
+ */
148
+ this.isFocusableElement = (el) => {
149
+ return this.isMenuItemElement(el);
150
+ };
598
151
  this.ariaLabel = null;
599
152
  this.placement = "bottom";
600
153
  this.autoDismiss = false;
@@ -617,24 +170,112 @@ exports.Menu = class Menu extends Menu$1 {
617
170
  this.open = false;
618
171
  }
619
172
  };
620
- const handleFocusOut = this.handleFocusOut;
621
- this.handleFocusOut = (e) => {
622
- const privates2 = this;
623
- const isSafeToCallSuper = privates2.menuItems.some(
624
- privates2.isFocusableElement
625
- );
626
- if (!isSafeToCallSuper) {
173
+ }
174
+ /**
175
+ * @internal
176
+ */
177
+ itemsChanged() {
178
+ if (this.$fastController.isConnected && this.menuItems !== void 0) {
179
+ this.setItems();
180
+ }
181
+ }
182
+ /**
183
+ * @internal
184
+ */
185
+ connectedCallback() {
186
+ super.connectedCallback();
187
+ index.DOM.queueUpdate(() => {
188
+ this.setItems();
189
+ });
190
+ }
191
+ /**
192
+ * @internal
193
+ */
194
+ disconnectedCallback() {
195
+ super.disconnectedCallback();
196
+ this.removeItemListeners();
197
+ this.menuItems = void 0;
198
+ }
199
+ /**
200
+ * Moves focus into the menu. If there is a child with the `autofocus` attribute, it will be focused.
201
+ * Otherwise, the first focusable child will be focused.
202
+ *
203
+ * @public
204
+ */
205
+ focus() {
206
+ const autoFocusElement = this.querySelector(
207
+ '[autofocus]:not([slot="anchor"])'
208
+ );
209
+ if (autoFocusElement instanceof HTMLElement) {
210
+ autoFocusElement.focus();
211
+ } else {
212
+ this.setFocus(0, 1);
213
+ }
214
+ }
215
+ /**
216
+ * Collapses any expanded Menu Items.
217
+ *
218
+ * @public
219
+ */
220
+ collapseExpandedItem() {
221
+ if (this.expandedItem !== null) {
222
+ this.expandedItem.expanded = false;
223
+ this.expandedItem = null;
224
+ }
225
+ }
226
+ /**
227
+ * @internal
228
+ */
229
+ handleMenuKeyDown(e) {
230
+ if (e.defaultPrevented || this.menuItems === void 0) {
231
+ return;
232
+ }
233
+ switch (e.key) {
234
+ case keyCodes.keyArrowDown:
235
+ this.setFocus(this.focusIndex + 1, 1);
236
+ return;
237
+ case keyCodes.keyArrowUp:
238
+ this.setFocus(this.focusIndex - 1, -1);
627
239
  return;
240
+ case keyCodes.keyEnd:
241
+ this.setFocus(this.menuItems.length - 1, -1);
242
+ return;
243
+ case keyCodes.keyHome:
244
+ this.setFocus(0, 1);
245
+ return;
246
+ default:
247
+ return true;
248
+ }
249
+ }
250
+ /**
251
+ * get an array of valid DOM children
252
+ */
253
+ domChildren() {
254
+ return Array.from(this.children).filter((child) => !child.hasAttribute("hidden")).filter((child) => !child.hasAttribute("slot"));
255
+ }
256
+ setFocus(focusIndex, adjustment) {
257
+ if (this.menuItems === void 0) {
258
+ return;
259
+ }
260
+ while (focusIndex >= 0 && focusIndex < this.menuItems.length) {
261
+ const child = this.menuItems[focusIndex];
262
+ if (this.isFocusableElement(child)) {
263
+ if (this.focusIndex > -1 && this.menuItems.length >= this.focusIndex - 1) {
264
+ this.menuItems[this.focusIndex].setAttribute("tabindex", "-1");
265
+ }
266
+ this.focusIndex = focusIndex;
267
+ child.setAttribute("tabindex", "0");
268
+ child.focus();
269
+ break;
628
270
  }
629
- handleFocusOut(e);
630
- };
631
- const privates = this;
632
- const domChildren = privates.domChildren;
633
- privates.domChildren = () => {
634
- return domChildren.call(this).filter((child) => !child.hasAttribute("slot"));
635
- };
271
+ focusIndex += adjustment;
272
+ }
636
273
  }
637
274
  openChanged(_, newValue) {
275
+ if (newValue) {
276
+ this._popupEl?.show();
277
+ this.focus();
278
+ }
638
279
  newValue ? this.$emit("open", void 0, { bubbles: false }) : this.$emit("close", void 0, { bubbles: false });
639
280
  if (this._anchorEl) {
640
281
  __privateMethod(this, _Menu_instances, updateAnchor_fn).call(this, this._anchorEl);
@@ -655,6 +296,34 @@ exports.Menu = class Menu extends Menu$1 {
655
296
  if (__privateGet(this, _Menu_instances, triggerBehaviour_get) === "auto" && clickedOnNonCheckboxMenuItem) {
656
297
  this.open = false;
657
298
  }
299
+ const changedMenuItem = e.target;
300
+ const changeItemIndex = this.menuItems.indexOf(changedMenuItem);
301
+ if (changeItemIndex === -1) {
302
+ return;
303
+ }
304
+ if (changedMenuItem.role === "menuitemradio" && changedMenuItem.checked) {
305
+ for (let i = changeItemIndex - 1; i >= 0; --i) {
306
+ const item = this.menuItems[i];
307
+ const role = item.getAttribute("role");
308
+ if (role === MenuItemRole.menuitemradio) {
309
+ item.checked = false;
310
+ }
311
+ if (role === "separator") {
312
+ break;
313
+ }
314
+ }
315
+ const maxIndex = this.menuItems.length - 1;
316
+ for (let i = changeItemIndex + 1; i <= maxIndex; ++i) {
317
+ const item = this.menuItems[i];
318
+ const role = item.getAttribute("role");
319
+ if (role === MenuItemRole.menuitemradio) {
320
+ item.checked = false;
321
+ }
322
+ if (role === "separator") {
323
+ break;
324
+ }
325
+ }
326
+ }
658
327
  return true;
659
328
  }
660
329
  };
@@ -678,6 +347,10 @@ cleanupAnchor_fn = function(a) {
678
347
  a.removeAttribute("aria-expanded");
679
348
  };
680
349
  _onAnchorClick = new WeakMap();
350
+ exports.Menu.focusableElementRoles = roleForMenuItem;
351
+ __decorateClass$1([
352
+ index.observable
353
+ ], exports.Menu.prototype, "items", 2);
681
354
  __decorateClass$1([
682
355
  index.attr({ attribute: "aria-label" })
683
356
  ], exports.Menu.prototype, "ariaLabel", 2);
@@ -724,43 +397,146 @@ var CheckAppearance = /* @__PURE__ */ ((CheckAppearance2) => {
724
397
  CheckAppearance2["TickOnly"] = "tick-only";
725
398
  return CheckAppearance2;
726
399
  })(CheckAppearance || {});
727
- class MenuItem extends MenuItem$1 {
400
+ class MenuItem extends index.FoundationElement {
728
401
  constructor() {
729
402
  super();
403
+ // eslint-disable-next-line @nrwl/nx/workspace/no-attribute-default-value
404
+ this.role = MenuItemRole.menuitem;
405
+ this.hasSubmenu = false;
406
+ this.currentDirection = localization.Direction.ltr;
407
+ /**
408
+ * @internal
409
+ */
410
+ this.handleMenuItemClick = (e) => {
411
+ if (e.defaultPrevented || this.disabled) {
412
+ return false;
413
+ }
414
+ this.invoke();
415
+ return false;
416
+ };
417
+ /**
418
+ * @internal
419
+ */
420
+ this.handleMouseOver = (_) => {
421
+ if (this.disabled || !this.hasSubmenu || this.expanded) {
422
+ return false;
423
+ }
424
+ this.expanded = true;
425
+ return false;
426
+ };
427
+ /**
428
+ * @internal
429
+ */
430
+ this.handleMouseOut = (_) => {
431
+ if (!this.expanded || this.contains(document.activeElement)) {
432
+ return false;
433
+ }
434
+ this.expanded = false;
435
+ return false;
436
+ };
437
+ this.invoke = () => {
438
+ if (this.disabled) {
439
+ return;
440
+ }
441
+ switch (this.role) {
442
+ case MenuItemRole.menuitemcheckbox:
443
+ this.checked = !this.checked;
444
+ break;
445
+ case MenuItemRole.menuitem:
446
+ this.updateSubmenu();
447
+ if (this.hasSubmenu) {
448
+ this.expanded = true;
449
+ } else {
450
+ this.$emit("change");
451
+ }
452
+ break;
453
+ case MenuItemRole.menuitemradio:
454
+ if (!this.checked) {
455
+ this.checked = true;
456
+ }
457
+ break;
458
+ }
459
+ };
730
460
  this.checkTrailing = false;
731
461
  this.#submenuArray = [];
732
- this.#handleMenuItemKeyDown = (e) => {
462
+ /**
463
+ * @internal
464
+ */
465
+ this.handleMenuItemKeyDown = (e) => {
733
466
  if (e.defaultPrevented) {
734
467
  return false;
735
468
  }
736
469
  switch (e.key) {
737
- case keyCodes$1.keyEnter:
738
- case keyCodes$1.keySpace:
470
+ case keyCodes.keyEnter:
471
+ case keyCodes.keySpace:
739
472
  this.invoke();
740
473
  if (!this.disabled) {
741
474
  this.#emitSyntheticClick();
742
475
  }
743
476
  return false;
744
- case keyCodes$1.keyArrowRight:
745
- this.expandAndFocus();
477
+ case keyCodes.keyArrowRight:
746
478
  if (this.hasSubmenu) {
479
+ this.expanded = true;
747
480
  this.#emitSyntheticClick();
748
481
  }
749
482
  return false;
750
- case keyCodes$1.keyArrowLeft:
483
+ case keyCodes.keyArrowLeft:
751
484
  if (this.expanded) {
485
+ this.#emitSyntheticClick();
752
486
  this.expanded = false;
753
487
  this.focus();
754
- this.#emitSyntheticClick();
755
488
  return false;
756
489
  }
757
490
  }
758
491
  return true;
759
492
  };
760
493
  this.#syntheticClickEvents = /* @__PURE__ */ new WeakSet();
761
- this.updateSubmenu = () => this.#updateSubmenu();
762
494
  this.addEventListener("expanded-change", this.#expandedChange);
763
- this.handleMenuItemKeyDown = this.#handleMenuItemKeyDown;
495
+ }
496
+ /**
497
+ * @internal
498
+ */
499
+ expandedChanged() {
500
+ if (this.$fastController.isConnected) {
501
+ if (this.submenu === void 0) {
502
+ return;
503
+ }
504
+ if (this.expanded === false) {
505
+ this.submenu.collapseExpandedItem();
506
+ } else {
507
+ this.currentDirection = localization.getDirection(this);
508
+ }
509
+ this.$emit("expanded-change", this, { bubbles: false });
510
+ }
511
+ }
512
+ /**
513
+ * @internal
514
+ */
515
+ checkedChanged() {
516
+ if (this.$fastController.isConnected) {
517
+ this.$emit("change");
518
+ }
519
+ }
520
+ /**
521
+ * @internal
522
+ */
523
+ connectedCallback() {
524
+ super.connectedCallback();
525
+ index.DOM.queueUpdate(() => {
526
+ this.updateSubmenu();
527
+ });
528
+ this.observer = new MutationObserver(this.updateSubmenu);
529
+ }
530
+ /**
531
+ * @internal
532
+ */
533
+ disconnectedCallback() {
534
+ super.disconnectedCallback();
535
+ this.submenu = void 0;
536
+ if (this.observer !== void 0) {
537
+ this.observer.disconnect();
538
+ this.observer = void 0;
539
+ }
764
540
  }
765
541
  #submenuArray;
766
542
  /**
@@ -771,7 +547,7 @@ class MenuItem extends MenuItem$1 {
771
547
  slottedSubmenuChanged(_oldValue, newValue) {
772
548
  this.#submenuArray = newValue;
773
549
  }
774
- #updateSubmenu() {
550
+ updateSubmenu() {
775
551
  for (const submenu of this.#submenuArray) {
776
552
  this.submenu = submenu;
777
553
  this.submenu.anchor = this;
@@ -788,7 +564,6 @@ class MenuItem extends MenuItem$1 {
788
564
  this.submenu.open = this.expanded;
789
565
  }
790
566
  }
791
- #handleMenuItemKeyDown;
792
567
  #syntheticClickEvents;
793
568
  /**
794
569
  * @internal
@@ -805,6 +580,30 @@ class MenuItem extends MenuItem$1 {
805
580
  this.dispatchEvent(mouseEvent);
806
581
  }
807
582
  }
583
+ __decorateClass([
584
+ index.attr({ mode: "boolean" })
585
+ ], MenuItem.prototype, "disabled");
586
+ __decorateClass([
587
+ index.attr({ mode: "boolean" })
588
+ ], MenuItem.prototype, "expanded");
589
+ __decorateClass([
590
+ index.attr
591
+ ], MenuItem.prototype, "role");
592
+ __decorateClass([
593
+ index.attr({ mode: "boolean" })
594
+ ], MenuItem.prototype, "checked");
595
+ __decorateClass([
596
+ index.observable
597
+ ], MenuItem.prototype, "submenuRegion");
598
+ __decorateClass([
599
+ index.observable
600
+ ], MenuItem.prototype, "hasSubmenu");
601
+ __decorateClass([
602
+ index.observable
603
+ ], MenuItem.prototype, "currentDirection");
604
+ __decorateClass([
605
+ index.observable
606
+ ], MenuItem.prototype, "submenu");
808
607
  __decorateClass([
809
608
  index.attr
810
609
  ], MenuItem.prototype, "text");