@vonage/vivid 3.35.0 → 3.37.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 (116) hide show
  1. package/accordion/index.js +1 -2
  2. package/accordion-item/index.js +1 -0
  3. package/alert/index.js +1 -0
  4. package/badge/index.js +1 -0
  5. package/banner/index.js +1 -0
  6. package/breadcrumb/index.js +0 -1
  7. package/breadcrumb-item/index.js +1 -0
  8. package/button/index.js +1 -0
  9. package/card/index.js +0 -1
  10. package/checkbox/index.js +1 -2
  11. package/combobox/index.js +1 -2
  12. package/custom-elements.json +196 -76
  13. package/data-grid/index.js +1 -2
  14. package/date-picker/index.js +1 -2
  15. package/dialog/index.js +1 -2
  16. package/empty-state/index.js +0 -1
  17. package/fab/index.js +1 -0
  18. package/file-picker/index.js +1 -0
  19. package/index.js +1 -2
  20. package/lib/date-picker/date-picker.d.ts +12 -12
  21. package/lib/date-picker/date-picker.form-associated.d.ts +11 -0
  22. package/lib/menu-item/menu-item.d.ts +2 -0
  23. package/lib/menu-item/menu-item.template.d.ts +1 -1
  24. package/lib/number-field/number-field.d.ts +6 -2
  25. package/lib/tree-item/tree-item.template.d.ts +1 -1
  26. package/listbox/index.js +1 -2
  27. package/menu/index.js +1 -2
  28. package/menu-item/index.js +2 -2
  29. package/nav-disclosure/index.js +1 -0
  30. package/nav-item/index.js +1 -0
  31. package/note/index.js +1 -0
  32. package/number-field/index.js +1 -0
  33. package/option/index.js +1 -0
  34. package/package.json +1 -1
  35. package/pagination/index.js +1 -1
  36. package/popup/index.js +1 -0
  37. package/radio-group/index.js +1 -2
  38. package/select/index.js +1 -2
  39. package/shared/affix.js +16 -5
  40. package/shared/apply-mixins.js +1 -1
  41. package/shared/children.js +2 -2
  42. package/shared/definition.js +3 -3
  43. package/shared/definition10.js +1 -1
  44. package/shared/definition11.js +1 -1
  45. package/shared/definition12.js +1 -1
  46. package/shared/definition13.js +1 -1
  47. package/shared/definition14.js +1 -1
  48. package/shared/definition15.js +1 -1
  49. package/shared/definition16.js +3 -4
  50. package/shared/definition17.js +99 -45
  51. package/shared/definition18.js +1 -1
  52. package/shared/definition19.js +1 -1
  53. package/shared/definition2.js +2 -3
  54. package/shared/definition20.js +1 -1
  55. package/shared/definition21.js +6 -5
  56. package/shared/definition22.js +1 -1
  57. package/shared/definition23.js +1 -1
  58. package/shared/definition26.js +475 -54
  59. package/shared/definition27.js +7 -400
  60. package/shared/definition28.js +3 -3
  61. package/shared/definition29.js +1 -1
  62. package/shared/definition3.js +1 -1
  63. package/shared/definition31.js +1 -1
  64. package/shared/definition32.js +56 -9
  65. package/shared/definition33.js +4 -6
  66. package/shared/definition34.js +2 -2
  67. package/shared/definition35.js +1 -1
  68. package/shared/definition36.js +1 -1
  69. package/shared/definition37.js +2 -3
  70. package/shared/definition38.js +1 -1
  71. package/shared/definition39.js +5 -7
  72. package/shared/definition4.js +1 -1
  73. package/shared/definition40.js +1 -1
  74. package/shared/definition42.js +1 -1
  75. package/shared/definition43.js +1 -1
  76. package/shared/definition45.js +3 -3
  77. package/shared/definition46.js +1 -1
  78. package/shared/definition48.js +3 -3
  79. package/shared/definition49.js +1 -1
  80. package/shared/definition5.js +1 -1
  81. package/shared/definition51.js +1 -1
  82. package/shared/definition52.js +1 -1
  83. package/shared/definition53.js +5 -6
  84. package/shared/definition55.js +1 -1
  85. package/shared/definition6.js +4 -4
  86. package/shared/definition7.js +3 -3
  87. package/shared/definition8.js +1 -1
  88. package/shared/definition9.js +1 -2
  89. package/shared/icon.js +1 -1
  90. package/shared/index.js +1 -1
  91. package/shared/index2.js +66 -73
  92. package/shared/patterns/affix.d.ts +7 -1
  93. package/shared/patterns/form-elements/form-elements.d.ts +9 -7
  94. package/shared/ref.js +1 -1
  95. package/shared/slotted.js +73 -3
  96. package/shared/text-field.js +1 -1
  97. package/split-button/index.js +1 -0
  98. package/style.css +295 -281
  99. package/styles/core/all.css +44 -13
  100. package/styles/core/theme.css +1 -1
  101. package/styles/core/typography.css +44 -13
  102. package/styles/tokens/theme-dark.css +4 -4
  103. package/styles/tokens/theme-light.css +4 -4
  104. package/styles/tokens/vivid-2-compat.css +1 -1
  105. package/switch/index.js +1 -0
  106. package/tab/index.js +1 -0
  107. package/tabs/index.js +1 -2
  108. package/tag/index.js +1 -0
  109. package/text-anchor/index.js +1 -0
  110. package/text-area/index.js +1 -0
  111. package/text-field/index.js +1 -2
  112. package/toggletip/index.js +1 -0
  113. package/tooltip/index.js +1 -0
  114. package/tree-item/index.js +1 -2
  115. package/tree-view/index.js +0 -1
  116. package/shared/node-observation.js +0 -74
@@ -5,10 +5,12 @@ import { A as AffixIcon, a as affixIconTemplateFactory } from './affix.js';
5
5
  import { a as applyMixins } from './apply-mixins.js';
6
6
  import { S as StartEnd } from './start-end.js';
7
7
  import { D as Direction, g as getDirection } from './direction.js';
8
- import { i as keyArrowLeft, h as keyArrowRight, a as keySpace, k as keyEnter } from './key-codes.js';
8
+ import { i as keyArrowLeft, h as keyArrowRight, a as keySpace, k as keyEnter, c as keyHome, b as keyEnd, e as keyArrowUp, d as keyArrowDown } from './key-codes.js';
9
+ import { I as Icon } from './icon.js';
10
+ import { i as isHTMLElement } from './dom.js';
9
11
  import { f as focusTemplateFactory } from './focus2.js';
12
+ import { s as slotted, e as elements } from './slotted.js';
10
13
  import { w as when } from './when.js';
11
- import { s as slotted } from './slotted.js';
12
14
  import { c as classNames } from './class-names.js';
13
15
 
14
16
  /**
@@ -281,17 +283,303 @@ __decorate([
281
283
  ], MenuItem$1.prototype, "submenu", void 0);
282
284
  applyMixins(MenuItem$1, StartEnd);
283
285
 
284
- const styles = "/**\n * Do not edit directly\n * Generated on Wed, 06 Sep 2023 09:40:36 GMT\n */\n@supports selector(:focus-visible) {\n :host(:focus-visible) {\n outline: none;\n }\n}\n.base {\n position: relative;\n display: flex;\n box-sizing: border-box;\n align-items: center;\n background-color: var(--_appearance-color-fill);\n box-shadow: inset 0 0 0 1px var(--_appearance-color-outline);\n gap: 12px;\n inline-size: 100%;\n padding-block: 2px;\n padding-inline: 16px;\n}\n.base {\n --_appearance-color-text: var(--_connotation-color-primary);\n --_appearance-color-fill: transparent;\n --_appearance-color-outline: transparent;\n}\n.base:where(:hover, .hover):where(:not(:disabled, .disabled, .readonly)) {\n --_appearance-color-text: var(--_connotation-color-primary);\n --_appearance-color-fill: var(--_connotation-color-faint);\n --_appearance-color-outline: transparent;\n}\n.base:where(:disabled, .disabled) {\n --_appearance-color-text: var(--vvd-color-neutral-300);\n --_appearance-color-fill: transparent;\n --_appearance-color-outline: transparent;\n}\n.base:where(:active, .active):where(:not(:disabled, .disabled)) {\n --_appearance-color-text: var(--_connotation-color-primary);\n --_appearance-color-fill: var(--_connotation-color-soft);\n --_appearance-color-outline: transparent;\n}\n.base:where(.selected, [aria-current]):where(:not(:disabled, .disabled, :hover, .hover)) {\n --_appearance-color-text: var(--_connotation-color-primary);\n --_appearance-color-fill: var(--_connotation-color-dim);\n --_appearance-color-outline: transparent;\n}\n.base:where(.selected, [aria-current]):where(:hover, .hover) {\n --_appearance-color-text: var(--_connotation-color-primary);\n --_appearance-color-fill: var(--_connotation-color-pale);\n --_appearance-color-outline: transparent;\n}\n.base {\n /* @cssprop [--vvd-menu-item-accent-primary=var(--vvd-color-canvas-text)] */\n --_connotation-color-primary: var(--vvd-menu-item-accent-primary, var(--vvd-color-canvas-text));\n /* @cssprop [--vvd-menu-item-accent-primary-text=var(--vvd-color-canvas)] */\n --_connotation-color-primary-text: var(--vvd-menu-item-accent-primary-text, var(--vvd-color-canvas));\n /* @cssprop [--vvd-menu-item-accent-primary-increment=var(--vvd-color-neutral-800)] */\n --_connotation-color-primary-increment: var(--vvd-menu-item-accent-primary-increment, var(--vvd-color-neutral-800));\n /* @cssprop [--vvd-menu-item-accent-faint=var(--vvd-color-neutral-50)] */\n --_connotation-color-faint: var(--vvd-menu-item-accent-faint, var(--vvd-color-neutral-50));\n /* @cssprop [--vvd-menu-item-accent-soft=var(--vvd-color-neutral-100)] */\n --_connotation-color-soft: var(--vvd-menu-item-accent-soft, var(--vvd-color-neutral-100));\n /* @cssprop [--vvd-menu-item-accent-pale=var(--vvd-color-neutral-300)] */\n --_connotation-color-pale: var(--vvd-menu-item-accent-pale, var(--vvd-color-neutral-300));\n /* @cssprop [--vvd-menu-item-accent-dim=var(--vvd-color-neutral-200)] */\n --_connotation-color-dim: var(--vvd-menu-item-accent-dim, var(--vvd-color-neutral-200));\n}\n.base:not(.two-lines) {\n min-block-size: calc(1px * (40 + 4 * clamp(-1, var(--vvd-size-density, 0), 2)));\n}\n.base.two-lines {\n min-block-size: calc(calc(1px * (40 + 4 * clamp(-1, var(--vvd-size-density, 0), 2))) + calc(1px * (40 + 4 * clamp(-1, var(--vvd-size-density, 0), 2) - 16)));\n}\n@supports (user-select: none) {\n .base {\n user-select: none;\n }\n}\n.base:not(.disabled) {\n cursor: pointer;\n}\n.base.disabled {\n cursor: not-allowed;\n pointer-events: none;\n}\n\n.focus-indicator {\n border-radius: 6px;\n}\n:host(:not(:focus-visible)) .focus-indicator {\n display: none;\n}\n\n.icon {\n flex-shrink: 0;\n font-size: calc(calc(1px * (40 + 4 * clamp(-1, var(--vvd-size-density, 0), 2))) / 2);\n line-height: 1;\n}\n\n.action,\n.decorative {\n display: flex;\n place-content: center;\n}\n\n.action {\n color: var(--_appearance-color-text);\n}\n.base.trailing .action {\n order: 1;\n margin-inline-start: auto;\n}\n.base.has-meta .action {\n order: 1;\n margin-inline-start: auto;\n}\n\n.base:not(.disabled) .decorative {\n color: var(--vvd-color-neutral-600);\n}\n.base.disabled .decorative {\n color: var(--vvd-color-neutral-200);\n}\n.base.has-meta .decorative {\n order: 1;\n margin-inline-start: auto;\n}\n\n.text {\n display: flex;\n overflow: hidden;\n flex-direction: column;\n}\n\n.text-primary,\n.text-secondary {\n /* stylelint-disable value-no-vendor-prefix */\n display: -webkit-box;\n /* stylelint-enable value-no-vendor-prefix */\n overflow: hidden;\n -webkit-box-orient: vertical;\n color: var(--_appearance-color-text);\n font: var(--vvd-typography-base);\n}\n\n.text-primary {\n -webkit-line-clamp: var(--text-primary-line-clamp, 1);\n}\n.base.two-lines .text-primary {\n font: var(--vvd-typography-base-bold);\n}\n\n.text-secondary {\n -webkit-line-clamp: var(--text-secondary-line-clamp, 1);\n}\n.base.two-lines .text-secondary {\n color: var(--vvd-color-neutral-600);\n}";
286
+ /**
287
+ * A Menu Custom HTML Element.
288
+ * Implements the {@link https://www.w3.org/TR/wai-aria-1.1/#menu | ARIA menu }.
289
+ *
290
+ * @slot - The default slot for the menu items
291
+ *
292
+ * @public
293
+ */
294
+ let Menu$1 = class Menu extends FoundationElement {
295
+ constructor() {
296
+ super(...arguments);
297
+ this.expandedItem = null;
298
+ /**
299
+ * The index of the focusable element in the items array
300
+ * defaults to -1
301
+ */
302
+ this.focusIndex = -1;
303
+ /**
304
+ * @internal
305
+ */
306
+ this.isNestedMenu = () => {
307
+ return (this.parentElement !== null &&
308
+ isHTMLElement(this.parentElement) &&
309
+ this.parentElement.getAttribute("role") === "menuitem");
310
+ };
311
+ /**
312
+ * if focus is moving out of the menu, reset to a stable initial state
313
+ * @internal
314
+ */
315
+ this.handleFocusOut = (e) => {
316
+ if (!this.contains(e.relatedTarget) && this.menuItems !== undefined) {
317
+ this.collapseExpandedItem();
318
+ // find our first focusable element
319
+ const focusIndex = this.menuItems.findIndex(this.isFocusableElement);
320
+ // set the current focus index's tabindex to -1
321
+ this.menuItems[this.focusIndex].setAttribute("tabindex", "-1");
322
+ // set the first focusable element tabindex to 0
323
+ this.menuItems[focusIndex].setAttribute("tabindex", "0");
324
+ // set the focus index
325
+ this.focusIndex = focusIndex;
326
+ }
327
+ };
328
+ this.handleItemFocus = (e) => {
329
+ const targetItem = e.target;
330
+ if (this.menuItems !== undefined &&
331
+ targetItem !== this.menuItems[this.focusIndex]) {
332
+ this.menuItems[this.focusIndex].setAttribute("tabindex", "-1");
333
+ this.focusIndex = this.menuItems.indexOf(targetItem);
334
+ targetItem.setAttribute("tabindex", "0");
335
+ }
336
+ };
337
+ this.handleExpandedChanged = (e) => {
338
+ if (e.defaultPrevented ||
339
+ e.target === null ||
340
+ this.menuItems === undefined ||
341
+ this.menuItems.indexOf(e.target) < 0) {
342
+ return;
343
+ }
344
+ e.preventDefault();
345
+ const changedItem = e.target;
346
+ // closing an expanded item without opening another
347
+ if (this.expandedItem !== null &&
348
+ changedItem === this.expandedItem &&
349
+ changedItem.expanded === false) {
350
+ this.expandedItem = null;
351
+ return;
352
+ }
353
+ if (changedItem.expanded) {
354
+ if (this.expandedItem !== null && this.expandedItem !== changedItem) {
355
+ this.expandedItem.expanded = false;
356
+ }
357
+ this.menuItems[this.focusIndex].setAttribute("tabindex", "-1");
358
+ this.expandedItem = changedItem;
359
+ this.focusIndex = this.menuItems.indexOf(changedItem);
360
+ changedItem.setAttribute("tabindex", "0");
361
+ }
362
+ };
363
+ this.removeItemListeners = () => {
364
+ if (this.menuItems !== undefined) {
365
+ this.menuItems.forEach((item) => {
366
+ item.removeEventListener("expanded-change", this.handleExpandedChanged);
367
+ item.removeEventListener("focus", this.handleItemFocus);
368
+ });
369
+ }
370
+ };
371
+ this.setItems = () => {
372
+ const newItems = this.domChildren();
373
+ this.removeItemListeners();
374
+ this.menuItems = newItems;
375
+ const menuItems = this.menuItems.filter(this.isMenuItemElement);
376
+ // if our focus index is not -1 we have items
377
+ if (menuItems.length) {
378
+ this.focusIndex = 0;
379
+ }
380
+ function elementIndent(el) {
381
+ const role = el.getAttribute("role");
382
+ const startSlot = el.querySelector("[slot=start]");
383
+ if (role !== MenuItemRole$1.menuitem && startSlot === null) {
384
+ return 1;
385
+ }
386
+ else if (role === MenuItemRole$1.menuitem && startSlot !== null) {
387
+ return 1;
388
+ }
389
+ else if (role !== MenuItemRole$1.menuitem && startSlot !== null) {
390
+ return 2;
391
+ }
392
+ else {
393
+ return 0;
394
+ }
395
+ }
396
+ const indent = menuItems.reduce((accum, current) => {
397
+ const elementValue = elementIndent(current);
398
+ return accum > elementValue ? accum : elementValue;
399
+ }, 0);
400
+ menuItems.forEach((item, index) => {
401
+ item.setAttribute("tabindex", index === 0 ? "0" : "-1");
402
+ item.addEventListener("expanded-change", this.handleExpandedChanged);
403
+ item.addEventListener("focus", this.handleItemFocus);
404
+ if (item instanceof MenuItem$1) {
405
+ item.startColumnCount = indent;
406
+ }
407
+ });
408
+ };
409
+ /**
410
+ * handle change from child element
411
+ */
412
+ this.changeHandler = (e) => {
413
+ if (this.menuItems === undefined) {
414
+ return;
415
+ }
416
+ const changedMenuItem = e.target;
417
+ const changeItemIndex = this.menuItems.indexOf(changedMenuItem);
418
+ if (changeItemIndex === -1) {
419
+ return;
420
+ }
421
+ if (changedMenuItem.role === "menuitemradio" &&
422
+ changedMenuItem.checked === true) {
423
+ for (let i = changeItemIndex - 1; i >= 0; --i) {
424
+ const item = this.menuItems[i];
425
+ const role = item.getAttribute("role");
426
+ if (role === MenuItemRole$1.menuitemradio) {
427
+ item.checked = false;
428
+ }
429
+ if (role === "separator") {
430
+ break;
431
+ }
432
+ }
433
+ const maxIndex = this.menuItems.length - 1;
434
+ for (let i = changeItemIndex + 1; i <= maxIndex; ++i) {
435
+ const item = this.menuItems[i];
436
+ const role = item.getAttribute("role");
437
+ if (role === MenuItemRole$1.menuitemradio) {
438
+ item.checked = false;
439
+ }
440
+ if (role === "separator") {
441
+ break;
442
+ }
443
+ }
444
+ }
445
+ };
446
+ /**
447
+ * check if the item is a menu item
448
+ */
449
+ this.isMenuItemElement = (el) => {
450
+ return (isHTMLElement(el) &&
451
+ Menu.focusableElementRoles.hasOwnProperty(el.getAttribute("role")));
452
+ };
453
+ /**
454
+ * check if the item is focusable
455
+ */
456
+ this.isFocusableElement = (el) => {
457
+ return this.isMenuItemElement(el);
458
+ };
459
+ }
460
+ itemsChanged(oldValue, newValue) {
461
+ // only update children after the component is connected and
462
+ // the setItems has run on connectedCallback
463
+ // (menuItems is undefined until then)
464
+ if (this.$fastController.isConnected && this.menuItems !== undefined) {
465
+ this.setItems();
466
+ }
467
+ }
468
+ /**
469
+ * @internal
470
+ */
471
+ connectedCallback() {
472
+ super.connectedCallback();
473
+ DOM.queueUpdate(() => {
474
+ // wait until children have had a chance to
475
+ // connect before setting/checking their props/attributes
476
+ this.setItems();
477
+ });
478
+ this.addEventListener("change", this.changeHandler);
479
+ }
480
+ /**
481
+ * @internal
482
+ */
483
+ disconnectedCallback() {
484
+ super.disconnectedCallback();
485
+ this.removeItemListeners();
486
+ this.menuItems = undefined;
487
+ this.removeEventListener("change", this.changeHandler);
488
+ }
489
+ /**
490
+ * Focuses the first item in the menu.
491
+ *
492
+ * @public
493
+ */
494
+ focus() {
495
+ this.setFocus(0, 1);
496
+ }
497
+ /**
498
+ * Collapses any expanded menu items.
499
+ *
500
+ * @public
501
+ */
502
+ collapseExpandedItem() {
503
+ if (this.expandedItem !== null) {
504
+ this.expandedItem.expanded = false;
505
+ this.expandedItem = null;
506
+ }
507
+ }
508
+ /**
509
+ * @internal
510
+ */
511
+ handleMenuKeyDown(e) {
512
+ if (e.defaultPrevented || this.menuItems === undefined) {
513
+ return;
514
+ }
515
+ switch (e.key) {
516
+ case keyArrowDown:
517
+ // go forward one index
518
+ this.setFocus(this.focusIndex + 1, 1);
519
+ return;
520
+ case keyArrowUp:
521
+ // go back one index
522
+ this.setFocus(this.focusIndex - 1, -1);
523
+ return;
524
+ case keyEnd:
525
+ // set focus on last item
526
+ this.setFocus(this.menuItems.length - 1, -1);
527
+ return;
528
+ case keyHome:
529
+ // set focus on first item
530
+ this.setFocus(0, 1);
531
+ return;
532
+ default:
533
+ // if we are not handling the event, do not prevent default
534
+ return true;
535
+ }
536
+ }
537
+ /**
538
+ * get an array of valid DOM children
539
+ */
540
+ domChildren() {
541
+ return Array.from(this.children).filter(child => !child.hasAttribute("hidden"));
542
+ }
543
+ setFocus(focusIndex, adjustment) {
544
+ if (this.menuItems === undefined) {
545
+ return;
546
+ }
547
+ while (focusIndex >= 0 && focusIndex < this.menuItems.length) {
548
+ const child = this.menuItems[focusIndex];
549
+ if (this.isFocusableElement(child)) {
550
+ // change the previous index to -1
551
+ if (this.focusIndex > -1 &&
552
+ this.menuItems.length >= this.focusIndex - 1) {
553
+ this.menuItems[this.focusIndex].setAttribute("tabindex", "-1");
554
+ }
555
+ // update the focus index
556
+ this.focusIndex = focusIndex;
557
+ // update the tabindex of next focusable element
558
+ child.setAttribute("tabindex", "0");
559
+ // focus the element
560
+ child.focus();
561
+ break;
562
+ }
563
+ focusIndex += adjustment;
564
+ }
565
+ }
566
+ };
567
+ Menu$1.focusableElementRoles = roleForMenuItem;
568
+ __decorate([
569
+ observable
570
+ ], Menu$1.prototype, "items", void 0);
285
571
 
286
- var __defProp = Object.defineProperty;
287
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
288
- var __decorateClass = (decorators, target, key, kind) => {
289
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
572
+ const styles = "/**\n * Do not edit directly\n * Generated on Tue, 26 Sep 2023 13:00:58 GMT\n */\n@supports selector(:focus-visible) {\n :host(:focus-visible) {\n outline: none;\n }\n}\n.base {\n position: relative;\n display: flex;\n box-sizing: border-box;\n align-items: center;\n background-color: var(--_appearance-color-fill);\n box-shadow: inset 0 0 0 1px var(--_appearance-color-outline);\n gap: 12px;\n inline-size: 100%;\n padding-block: 2px;\n padding-inline: 16px;\n}\n.base {\n --_appearance-color-text: var(--_connotation-color-primary);\n --_appearance-color-fill: transparent;\n --_appearance-color-outline: transparent;\n}\n.base:where(:hover, .hover):where(:not(:disabled, .disabled, .readonly)) {\n --_appearance-color-text: var(--_connotation-color-primary);\n --_appearance-color-fill: var(--_connotation-color-faint);\n --_appearance-color-outline: transparent;\n}\n.base:where(:disabled, .disabled) {\n --_appearance-color-text: var(--vvd-color-neutral-300);\n --_appearance-color-fill: transparent;\n --_appearance-color-outline: transparent;\n}\n.base:where(:active, .active):where(:not(:disabled, .disabled)) {\n --_appearance-color-text: var(--_connotation-color-primary);\n --_appearance-color-fill: var(--_connotation-color-soft);\n --_appearance-color-outline: transparent;\n}\n.base:where(.selected, [aria-current]):where(:not(:disabled, .disabled, :hover, .hover)) {\n --_appearance-color-text: var(--_connotation-color-primary);\n --_appearance-color-fill: var(--_connotation-color-dim);\n --_appearance-color-outline: transparent;\n}\n.base:where(.selected, [aria-current]):where(:hover, .hover) {\n --_appearance-color-text: var(--_connotation-color-primary);\n --_appearance-color-fill: var(--_connotation-color-pale);\n --_appearance-color-outline: transparent;\n}\n.base {\n /* @cssprop [--vvd-menu-item-accent-primary=var(--vvd-color-canvas-text)] */\n --_connotation-color-primary: var(--vvd-menu-item-accent-primary, var(--vvd-color-canvas-text));\n /* @cssprop [--vvd-menu-item-accent-primary-text=var(--vvd-color-canvas)] */\n --_connotation-color-primary-text: var(--vvd-menu-item-accent-primary-text, var(--vvd-color-canvas));\n /* @cssprop [--vvd-menu-item-accent-primary-increment=var(--vvd-color-neutral-800)] */\n --_connotation-color-primary-increment: var(--vvd-menu-item-accent-primary-increment, var(--vvd-color-neutral-800));\n /* @cssprop [--vvd-menu-item-accent-faint=var(--vvd-color-neutral-50)] */\n --_connotation-color-faint: var(--vvd-menu-item-accent-faint, var(--vvd-color-neutral-50));\n /* @cssprop [--vvd-menu-item-accent-soft=var(--vvd-color-neutral-100)] */\n --_connotation-color-soft: var(--vvd-menu-item-accent-soft, var(--vvd-color-neutral-100));\n /* @cssprop [--vvd-menu-item-accent-pale=var(--vvd-color-neutral-300)] */\n --_connotation-color-pale: var(--vvd-menu-item-accent-pale, var(--vvd-color-neutral-300));\n /* @cssprop [--vvd-menu-item-accent-dim=var(--vvd-color-neutral-200)] */\n --_connotation-color-dim: var(--vvd-menu-item-accent-dim, var(--vvd-color-neutral-200));\n}\n.base:not(.two-lines) {\n min-block-size: calc(1px * (40 + 4 * clamp(-1, var(--vvd-size-density, 0), 2)));\n}\n.base.two-lines {\n min-block-size: calc(calc(1px * (40 + 4 * clamp(-1, var(--vvd-size-density, 0), 2))) + calc(1px * (40 + 4 * clamp(-1, var(--vvd-size-density, 0), 2) - 16)));\n}\n@supports (user-select: none) {\n .base {\n user-select: none;\n }\n}\n.base:not(.disabled) {\n cursor: pointer;\n}\n.base.disabled {\n cursor: not-allowed;\n pointer-events: none;\n}\n\n.focus-indicator {\n border-radius: 6px;\n}\n:host(:not(:focus-visible)) .focus-indicator {\n display: none;\n}\n\n.icon {\n flex-shrink: 0;\n font-size: calc(calc(1px * (40 + 4 * clamp(-1, var(--vvd-size-density, 0), 2))) / 2);\n line-height: 1;\n}\n\n.action,\n.decorative {\n display: flex;\n place-content: center;\n}\n\n.action {\n color: var(--_appearance-color-text);\n}\n.base.trailing .action {\n order: 1;\n margin-inline-start: auto;\n}\n.base.has-meta .action {\n order: 1;\n margin-inline-start: auto;\n}\n\n.base:not(.disabled) .decorative {\n color: var(--vvd-color-neutral-600);\n}\n.base.disabled .decorative {\n color: var(--vvd-color-neutral-200);\n}\n.base.has-meta .decorative {\n order: 1;\n margin-inline-start: auto;\n}\n\n.chevron {\n margin-inline-start: auto;\n}\n\n.text {\n display: flex;\n overflow: hidden;\n flex-direction: column;\n}\n\n.text-primary,\n.text-secondary {\n /* stylelint-disable value-no-vendor-prefix */\n display: -webkit-box;\n /* stylelint-enable value-no-vendor-prefix */\n overflow: hidden;\n -webkit-box-orient: vertical;\n color: var(--_appearance-color-text);\n font: var(--vvd-typography-base);\n}\n\n.text-primary {\n -webkit-line-clamp: var(--text-primary-line-clamp, 1);\n}\n.base.two-lines .text-primary {\n font: var(--vvd-typography-base-bold);\n}\n\n.text-secondary {\n -webkit-line-clamp: var(--text-secondary-line-clamp, 1);\n}\n.base.two-lines .text-secondary {\n color: var(--vvd-color-neutral-600);\n}";
573
+
574
+ var __defProp$1 = Object.defineProperty;
575
+ var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
576
+ var __decorateClass$1 = (decorators, target, key, kind) => {
577
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
290
578
  for (var i = decorators.length - 1, decorator; i >= 0; i--)
291
579
  if (decorator = decorators[i])
292
580
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
293
581
  if (kind && result)
294
- __defProp(target, key, result);
582
+ __defProp$1(target, key, result);
295
583
  return result;
296
584
  };
297
585
  const MenuItemRole = {
@@ -299,18 +587,159 @@ const MenuItemRole = {
299
587
  presentation: "presentation"
300
588
  };
301
589
  class MenuItem extends MenuItem$1 {
590
+ constructor() {
591
+ super();
592
+ this.#submenuArray = [];
593
+ this.updateSubmenu = () => this.#updateSubmenu();
594
+ this.addEventListener("expanded-change", this.#expandedChange);
595
+ }
596
+ #submenuArray;
597
+ /**
598
+ *
599
+ *
600
+ * @internal
601
+ */
602
+ slottedSubmenuChanged(_oldValue, newValue) {
603
+ this.#submenuArray = newValue;
604
+ }
605
+ #updateSubmenu() {
606
+ for (const submenu of this.#submenuArray) {
607
+ this.submenu = submenu;
608
+ this.submenu.anchor = this;
609
+ this.submenu.placement = "right-start";
610
+ this.submenu.collapseExpandedItem = () => this.#collapseExpandedItem();
611
+ }
612
+ this.hasSubmenu = this.submenu === void 0 ? false : true;
613
+ }
614
+ #collapseExpandedItem() {
615
+ this.expanded = false;
616
+ }
617
+ #expandedChange() {
618
+ if (this.hasSubmenu) {
619
+ this.submenu.open = this.expanded;
620
+ }
621
+ }
302
622
  }
303
- __decorateClass([
623
+ __decorateClass$1([
304
624
  attr
305
625
  ], MenuItem.prototype, "text", 2);
306
- __decorateClass([
626
+ __decorateClass$1([
307
627
  attr({ attribute: "text-secondary" })
308
628
  ], MenuItem.prototype, "textSecondary", 2);
309
- __decorateClass([
629
+ __decorateClass$1([
310
630
  observable
311
631
  ], MenuItem.prototype, "metaSlottedContent", 2);
632
+ __decorateClass$1([
633
+ observable
634
+ ], MenuItem.prototype, "slottedSubmenu", 2);
312
635
  applyMixins(MenuItem, AffixIcon);
313
636
 
637
+ var __defProp = Object.defineProperty;
638
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
639
+ var __decorateClass = (decorators, target, key, kind) => {
640
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
641
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
642
+ if (decorator = decorators[i])
643
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
644
+ if (kind && result)
645
+ __defProp(target, key, result);
646
+ return result;
647
+ };
648
+ class Menu extends Menu$1 {
649
+ constructor() {
650
+ super(...arguments);
651
+ this.#anchorEl = null;
652
+ this.#observeMissingAnchor = (anchorId) => {
653
+ this.#observer = new MutationObserver(() => {
654
+ const anchor = document.getElementById(anchorId);
655
+ if (anchor) {
656
+ this.#anchorEl = anchor;
657
+ this.#setupAnchor(this.#anchorEl);
658
+ this.#observer.disconnect();
659
+ this.#observer = void 0;
660
+ }
661
+ });
662
+ this.#observer.observe(document.body, { childList: true, subtree: true });
663
+ };
664
+ this.placement = "bottom";
665
+ this.anchor = "";
666
+ this.autoDismiss = false;
667
+ this.open = false;
668
+ this.#openIfClosed = () => {
669
+ if (!this.open)
670
+ DOM.queueUpdate(() => this.open = true);
671
+ };
672
+ this.#closeOnClickOutside = (e) => {
673
+ if (!this.contains(e.target))
674
+ this.open = false;
675
+ };
676
+ }
677
+ #observer;
678
+ #anchorEl;
679
+ #observeMissingAnchor;
680
+ anchorChanged(_, newValue) {
681
+ if (this.#anchorEl)
682
+ this.#cleanupAnchor(this.#anchorEl);
683
+ this.#observer?.disconnect();
684
+ this.#anchorEl = newValue instanceof HTMLElement ? newValue : document.getElementById(newValue);
685
+ if (this.#anchorEl) {
686
+ this.#setupAnchor(this.#anchorEl);
687
+ } else {
688
+ this.#observeMissingAnchor(newValue);
689
+ }
690
+ }
691
+ autoDismissChanged(oldValue, newValue) {
692
+ if (oldValue === void 0)
693
+ return;
694
+ if (newValue) {
695
+ document.addEventListener("click", this.#closeOnClickOutside);
696
+ } else {
697
+ document.removeEventListener("click", this.#closeOnClickOutside);
698
+ }
699
+ }
700
+ openChanged(_, newValue) {
701
+ newValue ? this.$emit("open", void 0, { bubbles: false }) : this.$emit("close", void 0, { bubbles: false });
702
+ if (this.#anchorEl) {
703
+ this.#anchorEl.ariaExpanded = this.open.toString();
704
+ }
705
+ }
706
+ disconnectedCallback() {
707
+ super.disconnectedCallback();
708
+ if (this.#anchorEl)
709
+ this.#cleanupAnchor(this.#anchorEl);
710
+ this.#observer?.disconnect();
711
+ document.removeEventListener("click", this.#closeOnClickOutside);
712
+ }
713
+ #setupAnchor(a) {
714
+ a.addEventListener("click", this.#openIfClosed, true);
715
+ a.setAttribute("aria-haspopup", "menu");
716
+ }
717
+ #cleanupAnchor(a) {
718
+ a.removeEventListener("click", this.#openIfClosed, true);
719
+ a.removeAttribute("aria-hasPopup");
720
+ }
721
+ #openIfClosed;
722
+ #closeOnClickOutside;
723
+ }
724
+ __decorateClass([
725
+ attr({ mode: "fromView" })
726
+ ], Menu.prototype, "placement", 2);
727
+ __decorateClass([
728
+ attr({ mode: "fromView" })
729
+ ], Menu.prototype, "anchor", 2);
730
+ __decorateClass([
731
+ attr({ mode: "boolean", attribute: "auto-dismiss" })
732
+ ], Menu.prototype, "autoDismiss", 2);
733
+ __decorateClass([
734
+ attr({ mode: "boolean" })
735
+ ], Menu.prototype, "open", 2);
736
+ __decorateClass([
737
+ observable
738
+ ], Menu.prototype, "headerSlottedContent", 2);
739
+ __decorateClass([
740
+ observable
741
+ ], Menu.prototype, "actionItemsSlottedContent", 2);
742
+
314
743
  const getCheckIcon = (affixIconTemplate, x, iconType) => {
315
744
  const iconStatus = x.checked ? "checked" : "unchecked";
316
745
  const icon = `${iconType}-${iconStatus}-line`;
@@ -319,9 +748,8 @@ const getCheckIcon = (affixIconTemplate, x, iconType) => {
319
748
  const getClasses = ({
320
749
  disabled,
321
750
  checked,
322
- expanded,
323
751
  role,
324
- text,
752
+ text: text2,
325
753
  textSecondary,
326
754
  icon,
327
755
  metaSlottedContent
@@ -330,22 +758,46 @@ const getClasses = ({
330
758
  ["disabled", Boolean(disabled)],
331
759
  ["selected", role !== MenuItemRole.menuitem && Boolean(checked)],
332
760
  ["trailing", role !== MenuItemRole.menuitem && Boolean(icon)],
333
- ["expanded", Boolean(expanded)],
334
761
  ["item-checkbox", role === MenuItemRole.menuitemcheckbox],
335
762
  ["item-radio", role === MenuItemRole.menuitemradio],
336
- ["two-lines", Boolean(text?.length) && Boolean(textSecondary?.length)],
763
+ ["two-lines", Boolean(text2?.length) && Boolean(textSecondary?.length)],
337
764
  ["has-meta", Boolean(metaSlottedContent?.length)]
338
765
  );
339
766
  function handleClick(x, { event }) {
340
767
  x.handleMenuItemClick(event);
341
768
  return x.role === MenuItemRole.presentation;
342
769
  }
343
- const MenuItemTemplate = (context, definition) => {
770
+ function checkbox(context) {
771
+ const affixIconTemplate = affixIconTemplateFactory(context);
772
+ return html`${when(
773
+ (x) => x.role === MenuItemRole.menuitemcheckbox,
774
+ html`<span class="action">${(x) => getCheckIcon(affixIconTemplate, x, "checkbox")}</span>`
775
+ )}`;
776
+ }
777
+ function radio(context) {
778
+ const affixIconTemplate = affixIconTemplateFactory(context);
779
+ return html`${when(
780
+ (x) => x.role === MenuItemRole.menuitemradio,
781
+ html`<span class="action">${(x) => getCheckIcon(affixIconTemplate, x, "radio")}</span>`
782
+ )}`;
783
+ }
784
+ function text() {
785
+ return html`${when(
786
+ (x) => x.text || x.textSecondary,
787
+ html`<span class="text">
788
+ ${when((x) => x.text, html`<span class="text-primary">${(x) => x.text}</span>`)}
789
+ ${when((x) => x.textSecondary, html`<span class="text-secondary">${(x) => x.textSecondary}</span>`)}
790
+ </span>`
791
+ )}`;
792
+ }
793
+ const MenuItemTemplate = (context) => {
344
794
  const affixIconTemplate = affixIconTemplateFactory(context);
345
795
  const focusTemplate = focusTemplateFactory(context);
796
+ const iconTag = context.tagFor(Icon);
346
797
  return html`
347
798
  <template
348
799
  role="${(x) => x.role ? x.role : MenuItemRole.menuitem}"
800
+ aria-haspopup="${(x) => x.hasSubmenu ? "menu" : void 0}"
349
801
  aria-checked="${(x) => x.role !== MenuItemRole.menuitem ? x.checked : void 0}"
350
802
  aria-disabled="${(x) => x.disabled}"
351
803
  aria-expanded="${(x) => x.expanded}"
@@ -355,46 +807,15 @@ const MenuItemTemplate = (context, definition) => {
355
807
  @mouseout="${(x, c) => x.handleMouseOut(c.event)}"
356
808
  >
357
809
  <div class="${getClasses}">
358
-
359
- ${when(
360
- (x) => x.hasSubmenu,
361
- html`
362
- <div
363
- class="expand-collapse-glyph-container"
364
- >
365
- <span class="expand-collapse">
366
- <slot name="expand-collapse-indicator">
367
- ${definition.expandCollapseGlyph || ""}
368
- </slot>
369
- </span>
370
- </div>
371
- `
372
- )}
373
810
  ${() => focusTemplate}
374
811
  <slot name="meta" ${slotted("metaSlottedContent")}></slot>
375
- ${when(
376
- (x) => x.role === MenuItemRole.menuitemcheckbox,
377
- html`<span class="action">${(x) => getCheckIcon(affixIconTemplate, x, "checkbox")}</span>`
378
- )}
379
-
380
- ${when(
381
- (x) => x.role === MenuItemRole.menuitemradio,
382
- html`<span class="action">${(x) => getCheckIcon(affixIconTemplate, x, "radio")}</span>`
383
- )}
384
-
385
- ${when(
386
- (x) => x.icon,
387
- html`<span class="decorative">${(x) => affixIconTemplate(x.icon)}</span>`
388
- )}
389
-
390
- ${when((x) => x.text || x.textSecondary, html`<span class="text">
391
- ${when((x) => x.text, html`<span class="text-primary">${(x) => x.text}</span>`)}
392
- ${when((x) => x.textSecondary, html`<span class="text-secondary">${(x) => x.textSecondary}</span>`)}
393
- </span>`)}
394
-
395
-
396
-
812
+ ${checkbox(context)}
813
+ ${radio(context)}
814
+ ${when((x) => x.icon, html`<span class="decorative">${(x) => affixIconTemplate(x.icon)}</span>`)}
815
+ ${text()}
816
+ ${when((x) => x.hasSubmenu, html`<${iconTag} class="chevron" name="chevron-right-line"></${iconTag}>`)}
397
817
  </div>
818
+ <slot name="submenu" ${slotted({ property: "slottedSubmenu", filter: elements(context.tagFor(Menu)) })}></slot>
398
819
  </template>
399
820
  `;
400
821
  };
@@ -407,4 +828,4 @@ const menuItemDefinition = MenuItem.compose({
407
828
  const menuItemRegistries = [menuItemDefinition(), ...iconRegistries, ...focusRegistries];
408
829
  const registerMenuItem = registerFactory(menuItemRegistries);
409
830
 
410
- export { MenuItem$1 as M, menuItemRegistries as a, MenuItemRole$1 as b, roleForMenuItem as c, menuItemDefinition as m, registerMenuItem as r };
831
+ export { Menu as M, menuItemRegistries as a, menuItemDefinition as m, registerMenuItem as r };