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