@zanichelli/albe-web-components 16.3.1 → 16.3.2

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 (74) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/dist/cjs/loader.cjs.js +1 -1
  3. package/dist/cjs/web-components-library.cjs.js +1 -1
  4. package/dist/cjs/z-app-header_12.cjs.entry.js +67 -17
  5. package/dist/cjs/z-app-header_12.cjs.entry.js.map +1 -1
  6. package/dist/cjs/z-menu-section.cjs.entry.js +28 -13
  7. package/dist/cjs/z-menu-section.cjs.entry.js.map +1 -1
  8. package/dist/cjs/z-menu.cjs.entry.js +89 -43
  9. package/dist/cjs/z-menu.cjs.entry.js.map +1 -1
  10. package/dist/collection/components/z-app-header/index.js +55 -13
  11. package/dist/collection/components/z-app-header/index.js.map +1 -1
  12. package/dist/collection/components/z-app-header/index.stories.js +50 -116
  13. package/dist/collection/components/z-app-header/index.stories.js.map +1 -1
  14. package/dist/collection/components/z-app-header/styles.css +34 -25
  15. package/dist/collection/components/z-menu/index.js +93 -42
  16. package/dist/collection/components/z-menu/index.js.map +1 -1
  17. package/dist/collection/components/z-menu/styles.css +40 -52
  18. package/dist/collection/components/z-menu-section/index.js +31 -16
  19. package/dist/collection/components/z-menu-section/index.js.map +1 -1
  20. package/dist/collection/components/z-menu-section/styles.css +8 -0
  21. package/dist/collection/components/z-searchbar/index.js +14 -5
  22. package/dist/collection/components/z-searchbar/index.js.map +1 -1
  23. package/dist/components/index23.js +14 -5
  24. package/dist/components/index23.js.map +1 -1
  25. package/dist/components/z-app-header.js +56 -14
  26. package/dist/components/z-app-header.js.map +1 -1
  27. package/dist/components/z-menu-section.js +30 -15
  28. package/dist/components/z-menu-section.js.map +1 -1
  29. package/dist/components/z-menu.js +89 -44
  30. package/dist/components/z-menu.js.map +1 -1
  31. package/dist/esm/loader.js +1 -1
  32. package/dist/esm/web-components-library.js +1 -1
  33. package/dist/esm/z-app-header_12.entry.js +67 -17
  34. package/dist/esm/z-app-header_12.entry.js.map +1 -1
  35. package/dist/esm/z-menu-section.entry.js +28 -13
  36. package/dist/esm/z-menu-section.entry.js.map +1 -1
  37. package/dist/esm/z-menu.entry.js +89 -43
  38. package/dist/esm/z-menu.entry.js.map +1 -1
  39. package/dist/types/components/z-app-header/index.d.ts +4 -3
  40. package/dist/types/components/z-menu/index.d.ts +9 -1
  41. package/dist/types/components/z-menu-section/index.d.ts +4 -2
  42. package/dist/types/components/z-searchbar/index.d.ts +1 -0
  43. package/dist/web-components-library/p-8e5f1ae0.entry.js +2 -0
  44. package/dist/web-components-library/p-8e5f1ae0.entry.js.map +1 -0
  45. package/dist/web-components-library/p-b6e7866f.entry.js +2 -0
  46. package/dist/web-components-library/p-b6e7866f.entry.js.map +1 -0
  47. package/dist/web-components-library/p-fb0b11cd.entry.js +2 -0
  48. package/dist/web-components-library/p-fb0b11cd.entry.js.map +1 -0
  49. package/dist/web-components-library/web-components-library.esm.js +1 -1
  50. package/dist/web-components-library/web-components-library.esm.js.map +1 -1
  51. package/package.json +1 -1
  52. package/www/build/p-38bf2bfc.js +2 -0
  53. package/www/build/p-8e5f1ae0.entry.js +2 -0
  54. package/www/build/p-8e5f1ae0.entry.js.map +1 -0
  55. package/www/build/p-b6e7866f.entry.js +2 -0
  56. package/www/build/p-b6e7866f.entry.js.map +1 -0
  57. package/www/build/p-fb0b11cd.entry.js +2 -0
  58. package/www/build/p-fb0b11cd.entry.js.map +1 -0
  59. package/www/build/web-components-library.esm.js +1 -1
  60. package/www/build/web-components-library.esm.js.map +1 -1
  61. package/www/index.html +1 -1
  62. package/dist/web-components-library/p-04c39e8a.entry.js +0 -2
  63. package/dist/web-components-library/p-04c39e8a.entry.js.map +0 -1
  64. package/dist/web-components-library/p-0542a3c9.entry.js +0 -2
  65. package/dist/web-components-library/p-0542a3c9.entry.js.map +0 -1
  66. package/dist/web-components-library/p-16d625b3.entry.js +0 -2
  67. package/dist/web-components-library/p-16d625b3.entry.js.map +0 -1
  68. package/www/build/p-04c39e8a.entry.js +0 -2
  69. package/www/build/p-04c39e8a.entry.js.map +0 -1
  70. package/www/build/p-0542a3c9.entry.js +0 -2
  71. package/www/build/p-0542a3c9.entry.js.map +0 -1
  72. package/www/build/p-16d625b3.entry.js +0 -2
  73. package/www/build/p-16d625b3.entry.js.map +0 -1
  74. package/www/build/p-ae5cec65.js +0 -2
@@ -2,7 +2,7 @@ import { proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/
2
2
  import { g as KeyboardCode } from './index2.js';
3
3
  import { d as defineCustomElement$2 } from './index9.js';
4
4
 
5
- const stylesCss = ":host{display:flex;flex-direction:column;align-items:flex-start;justify-content:center;padding:0;font-family:var(--font-family-sans)}:host,::slotted(*),*{box-sizing:border-box}::slotted(a){text-decoration:none}::slotted(*){color:var(--color-default-text);font-family:var(--font-family-sans);font-weight:var(--font-rg)}.label{display:flex;width:100%;align-items:center;padding:var(--space-unit) 0;border:0;border-bottom:var(--border-size-small) solid var(--color-surface03);margin:0;background:transparent;border-radius:0;cursor:pointer;text-align:left}:host(:is([active],[open])) .label,.label:focus:focus-visible,.label:hover{border-color:var(--color-secondary01)}.label:focus:focus-visible{box-shadow:var(--shadow-focus-primary);outline:none}:host(:is([active],[open])) .label ::slotted(*),.label:focus:focus-visible ::slotted(*),.label:hover ::slotted(*){font-weight:var(--font-bd)}::slotted([data-text]){display:inline-flex;flex-direction:column}::slotted([data-text])::after{overflow:hidden;height:0;content:attr(data-text);content:attr(data-text) / \"\";font-weight:var(--font-bd);pointer-events:none;user-select:none;visibility:hidden}@media speech{::slotted([data-text])::after{display:none}}.label ::slotted(*){width:100%;margin:0;font-size:var(--font-size-3);line-height:1.5}.label z-icon{margin-left:calc(var(--space-unit) * 4);fill:var(--color-default-icon)}.items{display:flex;width:100%;flex-direction:column;padding:calc(var(--space-unit) / 2);padding-bottom:calc(var(--space-unit) * 1.5)}::slotted([slot=\"section\"]){display:inline-flex;padding:calc(var(--space-unit) / 2);margin:0;font-size:var(--font-size-1);line-height:1.333;outline:none}::slotted([slot=\"section\"]:last-of-type){border:none}::slotted([slot=\"section\"]:focus:focus-visible){box-shadow:var(--shadow-focus-primary);color:var(--color-secondary01)}::slotted([slot=\"section\"]:hover),::slotted([slot=\"section\"]:focus:focus-visible),::slotted([slot=\"section\"][active]){color:var(--color-secondary01);font-weight:var(--font-bd)}";
5
+ const stylesCss = ":host{display:flex;flex-direction:column;align-items:flex-start;justify-content:center;padding:0;font-family:var(--font-family-sans)}:host,::slotted(*),*{box-sizing:border-box}::slotted(a){text-decoration:none}::slotted(*){color:var(--color-default-text);font-family:var(--font-family-sans);font-weight:var(--font-rg)}.label{display:flex;width:100%;align-items:center;padding:var(--space-unit) 0;border:0;border-bottom:var(--border-size-small) solid var(--color-surface03);margin:0;background:transparent;border-radius:0;cursor:pointer;text-align:left}:host(:last-child:not([open])) .label{border-bottom:none}:host(:is([active],[open])) .label,.label:focus:focus-visible,.label:hover{border-color:var(--color-secondary01)}.label:focus:focus-visible{box-shadow:var(--shadow-focus-primary);outline:none}:host(:is([active],[open])) .label ::slotted(*),.label:focus:focus-visible ::slotted(*),.label:hover ::slotted(*){font-weight:var(--font-bd)}::slotted([data-text]){display:inline-flex;flex-direction:column}::slotted([data-text])::after{overflow:hidden;height:0;content:attr(data-text);content:attr(data-text) / \"\";font-weight:var(--font-bd);pointer-events:none;user-select:none;visibility:hidden}@media speech{::slotted([data-text])::after{display:none}}.label ::slotted(*){width:100%;margin:0;font-size:var(--font-size-3);line-height:1.5}.label z-icon{margin-left:calc(var(--space-unit) * 4);fill:var(--color-default-icon)}.items{display:flex;width:100%;flex-direction:column;padding:calc(var(--space-unit) / 2);padding-bottom:calc(var(--space-unit) * 1.5)}.items[hidden]{display:none}::slotted([slot=\"section\"]){display:inline-flex;padding:calc(var(--space-unit) / 2);margin:0;font-size:var(--font-size-1);line-height:1.333;outline:none}::slotted([slot=\"section\"]:last-of-type){border:none}::slotted([slot=\"section\"]:focus:focus-visible){box-shadow:var(--shadow-focus-primary);color:var(--color-secondary01)}::slotted([slot=\"section\"]:hover),::slotted([slot=\"section\"]:focus:focus-visible),::slotted([slot=\"section\"][active]){color:var(--color-secondary01);font-weight:var(--font-bd)}";
6
6
  const ZMenuSectionStyle0 = stylesCss;
7
7
 
8
8
  const ZMenuSection$1 = /*@__PURE__*/ proxyCustomElement(class ZMenuSection extends HTMLElement {
@@ -14,15 +14,14 @@ const ZMenuSection$1 = /*@__PURE__*/ proxyCustomElement(class ZMenuSection exten
14
14
  return;
15
15
  }
16
16
  this.open = !this.open;
17
- this.setFocus();
18
17
  }
19
18
  setItemsA11yAttrs() {
20
19
  if (!this.hasItems) {
21
20
  return;
22
21
  }
23
- this.items.forEach((item, index) => {
22
+ this.items.forEach((item) => {
24
23
  item.setAttribute("role", "menuitem");
25
- item.setAttribute("tabindex", index === 0 ? "0" : "-1");
24
+ item.tabIndex = -1;
26
25
  });
27
26
  }
28
27
  onItemsChange() {
@@ -38,11 +37,18 @@ const ZMenuSection$1 = /*@__PURE__*/ proxyCustomElement(class ZMenuSection exten
38
37
  const labelElement = ev.target.assignedElements()[0];
39
38
  labelElement.dataset.text = labelElement === null || labelElement === void 0 ? void 0 : labelElement.textContent;
40
39
  }
40
+ onLabelClick() {
41
+ this.toggle();
42
+ this.setFocus();
43
+ }
41
44
  onLabelKeydown(ev) {
42
45
  if (ev.key === KeyboardCode.ENTER || ev.key === KeyboardCode.SPACE) {
43
46
  ev.preventDefault();
44
47
  ev.stopPropagation();
45
48
  this.toggle();
49
+ if (this.open) {
50
+ this.focustFirstItem();
51
+ }
46
52
  }
47
53
  }
48
54
  /**
@@ -58,6 +64,13 @@ const ZMenuSection$1 = /*@__PURE__*/ proxyCustomElement(class ZMenuSection exten
58
64
  current.tabIndex = -1;
59
65
  }
60
66
  }
67
+ focustFirstItem() {
68
+ this.moveFocus(this.items[0]);
69
+ }
70
+ /** Focus the last item. */
71
+ async focusLastItem() {
72
+ this.moveFocus(this.items[this.items.length - 1]);
73
+ }
61
74
  /** Set tabindex of the label to 0, then focus it. */
62
75
  async setFocus() {
63
76
  this.htmlTabindex = 0;
@@ -65,15 +78,10 @@ const ZMenuSection$1 = /*@__PURE__*/ proxyCustomElement(class ZMenuSection exten
65
78
  this.label.focus();
66
79
  }, 100);
67
80
  }
68
- /** Focus the last item. */
69
- async focusLastItem() {
70
- this.htmlTabindex = 0;
71
- this.moveFocus(this.items[this.items.length - 1]);
72
- }
73
81
  onOpenChange() {
74
82
  if (!this.open) {
75
- this.closed.emit();
76
83
  this.setItemsA11yAttrs();
84
+ this.closed.emit();
77
85
  }
78
86
  else {
79
87
  this.opened.emit();
@@ -91,7 +99,7 @@ const ZMenuSection$1 = /*@__PURE__*/ proxyCustomElement(class ZMenuSection exten
91
99
  }
92
100
  ev.preventDefault();
93
101
  ev.stopPropagation();
94
- this.label.focus();
102
+ this.moveFocus(this.label, this.focusableItem);
95
103
  this.open = false;
96
104
  break;
97
105
  case KeyboardCode.ARROW_RIGHT:
@@ -101,6 +109,7 @@ const ZMenuSection$1 = /*@__PURE__*/ proxyCustomElement(class ZMenuSection exten
101
109
  ev.preventDefault();
102
110
  ev.stopPropagation();
103
111
  this.open = true;
112
+ this.focustFirstItem();
104
113
  break;
105
114
  case KeyboardCode.ARROW_DOWN: {
106
115
  if (!this.open) {
@@ -109,7 +118,7 @@ const ZMenuSection$1 = /*@__PURE__*/ proxyCustomElement(class ZMenuSection exten
109
118
  if (document.activeElement === this.host) {
110
119
  ev.preventDefault();
111
120
  ev.stopPropagation();
112
- this.moveFocus(this.items[0]);
121
+ this.focustFirstItem();
113
122
  break;
114
123
  }
115
124
  const currentIndex = this.items.indexOf(this.focusableItem);
@@ -119,6 +128,10 @@ const ZMenuSection$1 = /*@__PURE__*/ proxyCustomElement(class ZMenuSection exten
119
128
  ev.stopPropagation();
120
129
  this.moveFocus(receiver, this.focusableItem);
121
130
  }
131
+ else {
132
+ this.htmlTabindex = 0;
133
+ this.focusableItem.tabIndex = -1;
134
+ }
122
135
  break;
123
136
  }
124
137
  case KeyboardCode.ARROW_UP: {
@@ -134,6 +147,7 @@ const ZMenuSection$1 = /*@__PURE__*/ proxyCustomElement(class ZMenuSection exten
134
147
  }
135
148
  else {
136
149
  // since there isn't a previous item to focus, give the focus to the label element
150
+ this.focusableItem.tabIndex = -1;
137
151
  this.setFocus();
138
152
  }
139
153
  break;
@@ -154,6 +168,7 @@ const ZMenuSection$1 = /*@__PURE__*/ proxyCustomElement(class ZMenuSection exten
154
168
  this.toggle = this.toggle.bind(this);
155
169
  this.onItemsChange = this.onItemsChange.bind(this);
156
170
  this.onLabelSlotChange = this.onLabelSlotChange.bind(this);
171
+ this.onLabelClick = this.onLabelClick.bind(this);
157
172
  this.onLabelKeydown = this.onLabelKeydown.bind(this);
158
173
  this.onItemsKeydown = this.onItemsKeydown.bind(this);
159
174
  }
@@ -161,7 +176,7 @@ const ZMenuSection$1 = /*@__PURE__*/ proxyCustomElement(class ZMenuSection exten
161
176
  this.onItemsChange();
162
177
  }
163
178
  render() {
164
- return (h(Host, { key: '387e43b42ac8233f88d329a592bef924ebcf9ee9', open: this.open }, h("button", { key: 'd6014cdeb9a6ff2b4e95c43db7d2bae2b4d1c811', ref: (el) => (this.label = el), class: "label", "aria-haspopup": `${this.hasItems}`, "aria-expanded": `${!!this.open}`, role: "menuitem", tabindex: this.htmlTabindex, onClick: this.toggle, onKeyDown: this.onLabelKeydown }, h("slot", { key: 'd0065cf62f83d83df43b5c2413d3e13b23a1bb6a', onSlotchange: this.onLabelSlotChange }), this.hasItems && h("z-icon", { key: 'e6adc51de79f1fbcb76b025cd6226388ff4d90f0', name: this.open ? "chevron-up" : "chevron-down" })), this.open && (h("div", { key: '151f31f24ec306ce4cb45b70b8ae5a6023fd063d', class: "items", role: "menu" }, h("slot", { key: 'd4d67539788121360de0e4dabf51ba22086c1345', name: "section", onSlotchange: this.onItemsChange })))));
179
+ return (h(Host, { key: '4d9223bebf25df5eb224a7674c920ebc17470826', open: this.open }, h("button", { key: '2f75c046ad4519df706283d3b37c2d9feb8734d3', ref: (el) => (this.label = el), class: "label", "aria-haspopup": `${!!this.hasItems}`, "aria-expanded": `${!!this.open}`, role: "menuitem", tabindex: this.htmlTabindex, onClick: this.onLabelClick, onKeyDown: this.onLabelKeydown }, h("slot", { key: '0a3b20723371deac12792436d977c343c237720b', onSlotchange: this.onLabelSlotChange }), this.hasItems && h("z-icon", { key: '7fe5e9dc4a9eac28f0f3a381fedbe0ec3e7ca99d', name: this.open ? "chevron-up" : "chevron-down" })), h("div", { key: '80e167ce90df12c27eddc1e28b6bf6dd3b5d0dd7', class: "items", role: "menu", hidden: !this.open }, h("slot", { key: 'a0e88a56848abf198ced22e4fc390267aea6114e', name: "section", onSlotchange: this.onItemsChange }))));
165
180
  }
166
181
  get host() { return this; }
167
182
  static get watchers() { return {
@@ -175,8 +190,8 @@ const ZMenuSection$1 = /*@__PURE__*/ proxyCustomElement(class ZMenuSection exten
175
190
  "open": [1028],
176
191
  "hasItems": [32],
177
192
  "items": [32],
178
- "setFocus": [64],
179
- "focusLastItem": [64]
193
+ "focusLastItem": [64],
194
+ "setFocus": [64]
180
195
  }, [[0, "keydown", "onItemsKeydown"]], {
181
196
  "open": ["onOpenChange"],
182
197
  "htmlTabindex": ["onTabindexChange"]
@@ -1 +1 @@
1
- {"file":"z-menu-section.js","mappings":"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","names":["ZMenuSection"],"sources":["src/components/z-menu-section/styles.css?tag=z-menu-section&encapsulation=shadow","src/components/z-menu-section/index.tsx"],"sourcesContent":[":host {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n justify-content: center;\n padding: 0;\n font-family: var(--font-family-sans);\n}\n\n:host,\n::slotted(*),\n* {\n box-sizing: border-box;\n}\n\n::slotted(a) {\n text-decoration: none;\n}\n\n::slotted(*) {\n color: var(--color-default-text);\n font-family: var(--font-family-sans);\n font-weight: var(--font-rg);\n}\n\n.label {\n display: flex;\n width: 100%;\n align-items: center;\n padding: var(--space-unit) 0;\n border: 0;\n border-bottom: var(--border-size-small) solid var(--color-surface03);\n margin: 0;\n background: transparent;\n border-radius: 0;\n cursor: pointer;\n text-align: left;\n}\n\n:host(:is([active], [open])) .label,\n.label:focus:focus-visible,\n.label:hover {\n border-color: var(--color-secondary01);\n}\n\n.label:focus:focus-visible {\n box-shadow: var(--shadow-focus-primary);\n outline: none;\n}\n\n:host(:is([active], [open])) .label ::slotted(*),\n.label:focus:focus-visible ::slotted(*),\n.label:hover ::slotted(*) {\n font-weight: var(--font-bd);\n}\n\n::slotted([data-text]) {\n display: inline-flex;\n flex-direction: column;\n}\n\n/* Trick to prevent layout shifts on font-weight changes.\nThe trick is to put an hidden copy of the text already set to bold,\nso the needed space is correctly calculated before any hover/active state changes the\nfont-weight of the real text.\nThe hidden text has an height of 0px so it can expand the width without changing the height\nwhen placed below the real text using `flex-direction: column`. */\n::slotted([data-text])::after {\n overflow: hidden;\n height: 0;\n content: attr(data-text);\n content: attr(data-text) / \"\";\n font-weight: var(--font-bd);\n pointer-events: none;\n user-select: none;\n visibility: hidden;\n}\n\n@media speech {\n ::slotted([data-text])::after {\n display: none;\n }\n}\n\n.label ::slotted(*) {\n width: 100%;\n margin: 0;\n font-size: var(--font-size-3);\n line-height: 1.5;\n}\n\n.label z-icon {\n margin-left: calc(var(--space-unit) * 4);\n fill: var(--color-default-icon);\n}\n\n.items {\n display: flex;\n width: 100%;\n flex-direction: column;\n padding: calc(var(--space-unit) / 2);\n padding-bottom: calc(var(--space-unit) * 1.5);\n}\n\n::slotted([slot=\"section\"]) {\n display: inline-flex;\n padding: calc(var(--space-unit) / 2);\n margin: 0;\n font-size: var(--font-size-1);\n line-height: 1.333;\n outline: none;\n}\n\n::slotted([slot=\"section\"]:last-of-type) {\n border: none;\n}\n\n::slotted([slot=\"section\"]:focus:focus-visible) {\n box-shadow: var(--shadow-focus-primary);\n color: var(--color-secondary01);\n}\n\n::slotted([slot=\"section\"]:hover),\n::slotted([slot=\"section\"]:focus:focus-visible),\n::slotted([slot=\"section\"][active]) {\n color: var(--color-secondary01);\n font-weight: var(--font-bd);\n}\n","import {Component, Element, Event, EventEmitter, Host, Listen, Method, Prop, State, Watch, h} from \"@stencil/core\";\nimport {KeyboardCode} from \"../../beans\";\n\n/**\n * A component to create submenus inside the ZMenu.\n * @slot - Label of the menu section.\n * @slot item - Single entry of the section. Set the same slot name to different items to put many of them. Add the `active` attribute to a slotted item to highlight it.\n */\n@Component({\n tag: \"z-menu-section\",\n styleUrl: \"styles.css\",\n shadow: true,\n})\nexport class ZMenuSection {\n @Element() host: HTMLZMenuSectionElement;\n\n /** Active state */\n @Prop({reflect: true})\n active?: boolean;\n\n /**\n * Tabindex value to set on the label button.\n * Useful to manage keyboard navigation focus with roving tabindex handled by this component's parent (usually ZMenu).\n */\n @Prop()\n htmlTabindex = -1;\n\n /** The opening state of the section. */\n @Prop({mutable: true})\n open: boolean;\n\n @State()\n hasItems: boolean;\n\n @State()\n items: HTMLElement[];\n\n /** The section has been opened. */\n @Event()\n opened: EventEmitter;\n\n /** The section has been closed. */\n @Event()\n closed: EventEmitter;\n\n private label: HTMLButtonElement;\n\n private get focusableItem(): HTMLElement {\n return this.items.find(({tabIndex}) => tabIndex === 0);\n }\n\n private toggle(): void {\n if (!this.hasItems) {\n return;\n }\n\n this.open = !this.open;\n this.setFocus();\n }\n\n private setItemsA11yAttrs(): void {\n if (!this.hasItems) {\n return;\n }\n\n this.items.forEach((item, index) => {\n item.setAttribute(\"role\", \"menuitem\");\n item.setAttribute(\"tabindex\", index === 0 ? \"0\" : \"-1\");\n });\n }\n\n private onItemsChange(): void {\n this.items = Array.from(this.host.querySelectorAll('[slot=\"section\"]')) as HTMLElement[];\n this.hasItems = this.items.length > 0;\n this.setItemsA11yAttrs();\n }\n\n /**\n * Sets slotted item text as `data-text` attribute value, to let CSS use it through `attr()`.\n * @param ev Slotchange event\n */\n private onLabelSlotChange(ev: Event): void {\n const labelElement = (ev.target as HTMLSlotElement).assignedElements()[0] as HTMLElement;\n labelElement.dataset.text = labelElement?.textContent;\n }\n\n private onLabelKeydown(ev: KeyboardEvent): void {\n if (ev.key === KeyboardCode.ENTER || ev.key === KeyboardCode.SPACE) {\n ev.preventDefault();\n ev.stopPropagation();\n this.toggle();\n }\n }\n\n /**\n * Move focus and adjust the tabindex value of `receiver` and `current` elements,\n * setting -1 to the `current` and 0 to the `receiver`, then focus the `receiver` element.\n */\n private moveFocus(receiver: HTMLElement, current?: HTMLElement): void {\n receiver.tabIndex = 0;\n setTimeout(() => {\n receiver.focus();\n }, 100);\n if (current) {\n current.tabIndex = -1;\n }\n }\n\n /** Set tabindex of the label to 0, then focus it. */\n @Method()\n async setFocus(): Promise<void> {\n this.htmlTabindex = 0;\n setTimeout(() => {\n this.label.focus();\n }, 100);\n }\n\n /** Focus the last item. */\n @Method()\n async focusLastItem(): Promise<void> {\n this.htmlTabindex = 0;\n this.moveFocus(this.items[this.items.length - 1]);\n }\n\n @Watch(\"open\")\n onOpenChange(): void {\n if (!this.open) {\n this.closed.emit();\n this.setItemsA11yAttrs();\n } else {\n this.opened.emit();\n }\n }\n\n @Watch(\"htmlTabindex\")\n onTabindexChange(): void {\n this.label.tabIndex = this.htmlTabindex;\n }\n\n @Listen(\"keydown\")\n private onItemsKeydown(ev: KeyboardEvent): void {\n switch (ev.key) {\n case KeyboardCode.ESC:\n case KeyboardCode.ARROW_LEFT:\n if (!this.open) {\n break;\n }\n ev.preventDefault();\n ev.stopPropagation();\n this.label.focus();\n this.open = false;\n break;\n case KeyboardCode.ARROW_RIGHT:\n if (this.open) {\n break;\n }\n ev.preventDefault();\n ev.stopPropagation();\n this.open = true;\n break;\n case KeyboardCode.ARROW_DOWN: {\n if (!this.open) {\n break;\n }\n if (document.activeElement === this.host) {\n ev.preventDefault();\n ev.stopPropagation();\n this.moveFocus(this.items[0]);\n break;\n }\n const currentIndex = this.items.indexOf(this.focusableItem);\n const receiver = this.items[currentIndex + 1];\n if (receiver) {\n ev.preventDefault();\n ev.stopPropagation();\n this.moveFocus(receiver, this.focusableItem);\n }\n break;\n }\n case KeyboardCode.ARROW_UP: {\n if (!this.open || document.activeElement === this.host) {\n break;\n }\n const currentIndex = this.items.indexOf(this.focusableItem);\n const receiver = this.items[currentIndex - 1];\n ev.preventDefault();\n ev.stopPropagation();\n if (receiver) {\n this.moveFocus(receiver, this.focusableItem);\n } else {\n // since there isn't a previous item to focus, give the focus to the label element\n this.setFocus();\n }\n break;\n }\n }\n }\n\n constructor() {\n this.toggle = this.toggle.bind(this);\n this.onItemsChange = this.onItemsChange.bind(this);\n this.onLabelSlotChange = this.onLabelSlotChange.bind(this);\n this.onLabelKeydown = this.onLabelKeydown.bind(this);\n this.onItemsKeydown = this.onItemsKeydown.bind(this);\n }\n\n connectedCallback(): void {\n this.onItemsChange();\n }\n\n render(): HTMLZMenuSectionElement {\n return (\n <Host open={this.open}>\n <button\n ref={(el) => (this.label = el)}\n class=\"label\"\n aria-haspopup={`${this.hasItems}`}\n aria-expanded={`${!!this.open}`}\n role=\"menuitem\"\n tabindex={this.htmlTabindex}\n onClick={this.toggle}\n onKeyDown={this.onLabelKeydown}\n >\n <slot onSlotchange={this.onLabelSlotChange} />\n {this.hasItems && <z-icon name={this.open ? \"chevron-up\" : \"chevron-down\"} />}\n </button>\n {this.open && (\n <div\n class=\"items\"\n role=\"menu\"\n >\n <slot\n name=\"section\"\n onSlotchange={this.onItemsChange}\n />\n </div>\n )}\n </Host>\n );\n }\n}\n"],"version":3}
1
+ {"file":"z-menu-section.js","mappings":"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","names":["ZMenuSection"],"sources":["src/components/z-menu-section/styles.css?tag=z-menu-section&encapsulation=shadow","src/components/z-menu-section/index.tsx"],"sourcesContent":[":host {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n justify-content: center;\n padding: 0;\n font-family: var(--font-family-sans);\n}\n\n:host,\n::slotted(*),\n* {\n box-sizing: border-box;\n}\n\n::slotted(a) {\n text-decoration: none;\n}\n\n::slotted(*) {\n color: var(--color-default-text);\n font-family: var(--font-family-sans);\n font-weight: var(--font-rg);\n}\n\n.label {\n display: flex;\n width: 100%;\n align-items: center;\n padding: var(--space-unit) 0;\n border: 0;\n border-bottom: var(--border-size-small) solid var(--color-surface03);\n margin: 0;\n background: transparent;\n border-radius: 0;\n cursor: pointer;\n text-align: left;\n}\n\n:host(:last-child:not([open])) .label {\n border-bottom: none;\n}\n\n:host(:is([active], [open])) .label,\n.label:focus:focus-visible,\n.label:hover {\n border-color: var(--color-secondary01);\n}\n\n.label:focus:focus-visible {\n box-shadow: var(--shadow-focus-primary);\n outline: none;\n}\n\n:host(:is([active], [open])) .label ::slotted(*),\n.label:focus:focus-visible ::slotted(*),\n.label:hover ::slotted(*) {\n font-weight: var(--font-bd);\n}\n\n::slotted([data-text]) {\n display: inline-flex;\n flex-direction: column;\n}\n\n/* Trick to prevent layout shifts on font-weight changes.\nThe trick is to put an hidden copy of the text already set to bold,\nso the needed space is correctly calculated before any hover/active state changes the\nfont-weight of the real text.\nThe hidden text has an height of 0px so it can expand the width without changing the height\nwhen placed below the real text using `flex-direction: column`. */\n::slotted([data-text])::after {\n overflow: hidden;\n height: 0;\n content: attr(data-text);\n content: attr(data-text) / \"\";\n font-weight: var(--font-bd);\n pointer-events: none;\n user-select: none;\n visibility: hidden;\n}\n\n@media speech {\n ::slotted([data-text])::after {\n display: none;\n }\n}\n\n.label ::slotted(*) {\n width: 100%;\n margin: 0;\n font-size: var(--font-size-3);\n line-height: 1.5;\n}\n\n.label z-icon {\n margin-left: calc(var(--space-unit) * 4);\n fill: var(--color-default-icon);\n}\n\n.items {\n display: flex;\n width: 100%;\n flex-direction: column;\n padding: calc(var(--space-unit) / 2);\n padding-bottom: calc(var(--space-unit) * 1.5);\n}\n\n.items[hidden] {\n display: none;\n}\n\n::slotted([slot=\"section\"]) {\n display: inline-flex;\n padding: calc(var(--space-unit) / 2);\n margin: 0;\n font-size: var(--font-size-1);\n line-height: 1.333;\n outline: none;\n}\n\n::slotted([slot=\"section\"]:last-of-type) {\n border: none;\n}\n\n::slotted([slot=\"section\"]:focus:focus-visible) {\n box-shadow: var(--shadow-focus-primary);\n color: var(--color-secondary01);\n}\n\n::slotted([slot=\"section\"]:hover),\n::slotted([slot=\"section\"]:focus:focus-visible),\n::slotted([slot=\"section\"][active]) {\n color: var(--color-secondary01);\n font-weight: var(--font-bd);\n}\n","import {Component, Element, Event, EventEmitter, Host, Listen, Method, Prop, State, Watch, h} from \"@stencil/core\";\nimport {KeyboardCode} from \"../../beans\";\n\n/**\n * A component to create submenus inside the ZMenu.\n * @slot - Label of the menu section.\n * @slot item - Single entry of the section. Set the same slot name to different items to put many of them. Add the `active` attribute to a slotted item to highlight it.\n */\n@Component({\n tag: \"z-menu-section\",\n styleUrl: \"styles.css\",\n shadow: true,\n})\nexport class ZMenuSection {\n @Element() host: HTMLZMenuSectionElement;\n\n /** Active state */\n @Prop({reflect: true})\n active?: boolean;\n\n /**\n * Tabindex value to set on the label button.\n * Useful to manage keyboard navigation focus with roving tabindex handled by this component's parent (usually ZMenu).\n */\n @Prop()\n htmlTabindex = -1;\n\n /** The opening state of the section. */\n @Prop({mutable: true})\n open: boolean;\n\n @State()\n hasItems: boolean;\n\n @State()\n items: HTMLElement[];\n\n /** The section has been opened. */\n @Event()\n opened: EventEmitter;\n\n /** The section has been closed. */\n @Event()\n closed: EventEmitter;\n\n private label: HTMLButtonElement;\n\n private get focusableItem(): HTMLElement {\n return this.items.find(({tabIndex}) => tabIndex === 0);\n }\n\n private toggle(): void {\n if (!this.hasItems) {\n return;\n }\n\n this.open = !this.open;\n }\n\n private setItemsA11yAttrs(): void {\n if (!this.hasItems) {\n return;\n }\n\n this.items.forEach((item) => {\n item.setAttribute(\"role\", \"menuitem\");\n item.tabIndex = -1;\n });\n }\n\n private onItemsChange(): void {\n this.items = Array.from(this.host.querySelectorAll('[slot=\"section\"]')) as HTMLElement[];\n this.hasItems = this.items.length > 0;\n this.setItemsA11yAttrs();\n }\n\n /**\n * Sets slotted item text as `data-text` attribute value, to let CSS use it through `attr()`.\n * @param ev Slotchange event\n */\n private onLabelSlotChange(ev: Event): void {\n const labelElement = (ev.target as HTMLSlotElement).assignedElements()[0] as HTMLElement;\n labelElement.dataset.text = labelElement?.textContent;\n }\n\n private onLabelClick(): void {\n this.toggle();\n this.setFocus();\n }\n\n private onLabelKeydown(ev: KeyboardEvent): void {\n if (ev.key === KeyboardCode.ENTER || ev.key === KeyboardCode.SPACE) {\n ev.preventDefault();\n ev.stopPropagation();\n this.toggle();\n if (this.open) {\n this.focustFirstItem();\n }\n }\n }\n\n /**\n * Move focus and adjust the tabindex value of `receiver` and `current` elements,\n * setting -1 to the `current` and 0 to the `receiver`, then focus the `receiver` element.\n */\n private moveFocus(receiver: HTMLElement, current?: HTMLElement): void {\n receiver.tabIndex = 0;\n setTimeout(() => {\n receiver.focus();\n }, 100);\n if (current) {\n current.tabIndex = -1;\n }\n }\n\n private focustFirstItem(): void {\n this.moveFocus(this.items[0]);\n }\n\n /** Focus the last item. */\n @Method()\n async focusLastItem(): Promise<void> {\n this.moveFocus(this.items[this.items.length - 1]);\n }\n\n /** Set tabindex of the label to 0, then focus it. */\n @Method()\n async setFocus(): Promise<void> {\n this.htmlTabindex = 0;\n setTimeout(() => {\n this.label.focus();\n }, 100);\n }\n\n @Watch(\"open\")\n onOpenChange(): void {\n if (!this.open) {\n this.setItemsA11yAttrs();\n this.closed.emit();\n } else {\n this.opened.emit();\n }\n }\n\n @Watch(\"htmlTabindex\")\n onTabindexChange(): void {\n this.label.tabIndex = this.htmlTabindex;\n }\n\n @Listen(\"keydown\")\n private onItemsKeydown(ev: KeyboardEvent): void {\n switch (ev.key) {\n case KeyboardCode.ESC:\n case KeyboardCode.ARROW_LEFT:\n if (!this.open) {\n break;\n }\n ev.preventDefault();\n ev.stopPropagation();\n this.moveFocus(this.label, this.focusableItem);\n this.open = false;\n break;\n case KeyboardCode.ARROW_RIGHT:\n if (this.open) {\n break;\n }\n ev.preventDefault();\n ev.stopPropagation();\n this.open = true;\n this.focustFirstItem();\n break;\n case KeyboardCode.ARROW_DOWN: {\n if (!this.open) {\n break;\n }\n if (document.activeElement === this.host) {\n ev.preventDefault();\n ev.stopPropagation();\n this.focustFirstItem();\n break;\n }\n const currentIndex = this.items.indexOf(this.focusableItem);\n const receiver = this.items[currentIndex + 1];\n if (receiver) {\n ev.preventDefault();\n ev.stopPropagation();\n this.moveFocus(receiver, this.focusableItem);\n } else {\n this.htmlTabindex = 0;\n this.focusableItem.tabIndex = -1;\n }\n break;\n }\n case KeyboardCode.ARROW_UP: {\n if (!this.open || document.activeElement === this.host) {\n break;\n }\n const currentIndex = this.items.indexOf(this.focusableItem);\n const receiver = this.items[currentIndex - 1];\n ev.preventDefault();\n ev.stopPropagation();\n if (receiver) {\n this.moveFocus(receiver, this.focusableItem);\n } else {\n // since there isn't a previous item to focus, give the focus to the label element\n this.focusableItem.tabIndex = -1;\n this.setFocus();\n }\n break;\n }\n }\n }\n\n constructor() {\n this.toggle = this.toggle.bind(this);\n this.onItemsChange = this.onItemsChange.bind(this);\n this.onLabelSlotChange = this.onLabelSlotChange.bind(this);\n this.onLabelClick = this.onLabelClick.bind(this);\n this.onLabelKeydown = this.onLabelKeydown.bind(this);\n this.onItemsKeydown = this.onItemsKeydown.bind(this);\n }\n\n connectedCallback(): void {\n this.onItemsChange();\n }\n\n render(): HTMLZMenuSectionElement {\n return (\n <Host open={this.open}>\n <button\n ref={(el) => (this.label = el)}\n class=\"label\"\n aria-haspopup={`${!!this.hasItems}`}\n aria-expanded={`${!!this.open}`}\n role=\"menuitem\"\n tabindex={this.htmlTabindex}\n onClick={this.onLabelClick}\n onKeyDown={this.onLabelKeydown}\n >\n <slot onSlotchange={this.onLabelSlotChange} />\n {this.hasItems && <z-icon name={this.open ? \"chevron-up\" : \"chevron-down\"} />}\n </button>\n <div\n class=\"items\"\n role=\"menu\"\n hidden={!this.open}\n >\n <slot\n name=\"section\"\n onSlotchange={this.onItemsChange}\n />\n </div>\n </Host>\n );\n }\n}\n"],"version":3}
@@ -1,8 +1,9 @@
1
1
  import { proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/core/internal/client';
2
2
  import { g as KeyboardCode } from './index2.js';
3
+ import { a as containsElement } from './utils.js';
3
4
  import { d as defineCustomElement$2 } from './index9.js';
4
5
 
5
- const stylesCss = ":host,::slotted(*),*{box-sizing:border-box;outline:none}:host{position:relative;display:inline-flex;height:fit-content;flex-direction:column}::slotted(a){text-decoration:none}::slotted(*){color:var(--color-default-text);font-family:var(--font-family-sans);font-weight:var(--font-rg)}.menu-label{position:relative;width:100%;padding:0;border:0;margin:0;background:transparent;border-radius:0;color:inherit;text-align:left}.menu-wrapper{display:flex;align-items:center}button.menu-label{cursor:pointer}.menu-label:focus-within{box-shadow:var(--shadow-focus-primary)}.menu-label .menu-label-content{position:relative;display:flex;align-items:center;border-bottom:var(--border-size-large) solid transparent}:host(:is([active],[open])) .menu-label-content,.menu-label:focus-within .menu-label-content{color:var(--color-primary01);font-weight:var(--font-bd)}:host(:is([active],[open])) .menu-label-content ::slotted(*),.menu-label:focus-within .menu-label-content ::slotted(*),.menu-label:focus-within .menu-label-content z-icon{color:var(--color-primary01);letter-spacing:normal}:host([vertical-context]) .menu-label-content{padding:var(--space-unit) 0;border-width:var(--border-size-small);border-color:var(--color-surface03)}:host([vertical-context]) .menu-label-content ::slotted(*){padding:0}:host(:is([active],[open])) .menu-label .menu-label-content,.menu-label .menu-label-content:hover,.menu-label:focus-within .menu-label-content{border-color:var(--color-secondary01)}:host([vertical-context]:is([active],[open])) .menu-label .menu-label-content::after,:host([vertical-context]) .menu-label:hover::after,:host([vertical-context]) .menu-label:focus-within .menu-label-content::after{position:absolute;bottom:0;left:0;width:100%;height:var(--border-size-large);background-color:var(--color-secondary01);content:\"\"}::slotted([data-text]:not([slot]))::after{height:0;content:attr(data-text);content:attr(data-text) / \"\";font-weight:var(--font-bd);letter-spacing:normal;pointer-events:none;user-select:none;visibility:hidden}@media speech{::slotted([data-text]:not([slot]))::after{display:none}}::slotted([data-text]:not([slot])){display:inline-flex;flex-direction:column}.menu-label .menu-label-content ::slotted(*){display:inline-flex;width:100%;min-width:fit-content;padding-bottom:2px;margin:0;appearance:none;color:var(--z-menu-label-color, var(--color-default-text));font-family:var(--font-family-sans);font-size:var(--font-size-3);font-weight:inherit;line-height:1.5}.menu-label .menu-label-content z-icon{margin-left:calc(var(--space-unit) * 1.5);fill:currentcolor}.content{background:var(--color-surface01)}:host(:not([open])) .content{display:none}:host([floating]:not([vertical-context])) .content{position:absolute;top:100%;left:0;width:375px;min-width:100%;max-width:100vw;padding:0 calc(var(--space-unit) * 2);box-shadow:var(--shadow-2)}:host(:not([floating])) .content{width:100%}.header{display:flex;align-items:center;padding:var(--space-unit) 0 calc(var(--space-unit) * 2)}.header ::slotted(img[slot=\"header\"]){width:calc(var(--space-unit) * 11.25);height:auto;object-fit:contain}.header ::slotted([slot=\"header\"]:not(:first-child)){margin:auto 0;margin-left:calc(var(--space-unit) * 2.5);font-size:var(--font-size-3);font-weight:var(--font-sb);line-height:1.5}.items{display:flex;flex-direction:column;align-items:flex-start;background:inherit}.items>::slotted([slot=\"item\"]){width:100%;margin:0;font-size:var(--font-size-3);line-height:1.5}.items>::slotted([slot=\"item\"]:focus:focus-visible){box-shadow:var(--shadow-focus-primary)}.items>::slotted([slot=\"item\"]:not(z-menu-section)){padding:var(--space-unit) 0;border-bottom:var(--border-size-small) solid var(--color-surface03)}:host(:not([vertical-context])) .items>::slotted([slot=\"item\"]:not(z-menu-section):last-of-type){border-bottom:0}.items>::slotted([slot=\"item\"]:hover),.items>::slotted([slot=\"item\"]:focus:focus-visible),.items>::slotted([slot=\"item\"]:active){border-color:var(--color-secondary01);font-weight:var(--font-bd)}";
6
+ const stylesCss = ":host,::slotted(*),*{box-sizing:border-box;outline:none}:host{position:relative;display:inline-flex;height:fit-content;flex-direction:column}::slotted(a){text-decoration:none}::slotted(*){color:var(--color-default-text);font-family:var(--font-family-sans);font-weight:var(--font-rg)}.menu-label{position:relative;display:flex;width:100%;align-items:center;padding:0;border:0;border-bottom:var(--border-size-large) solid transparent;margin:0;background:transparent;border-radius:0;color:inherit;text-align:left}button.menu-label{cursor:pointer}.menu-label:focus-visible,div.menu-label:focus-within{box-shadow:var(--shadow-focus-primary)}:host(:is([active],[open])) .menu-label ::slotted(*),.menu-label:focus-visible ::slotted(*),div.menu-label:focus-within ::slotted(*){color:var(--color-primary01);font-weight:var(--font-bd)}:host([vertical-context]) .menu-label{padding:var(--space-unit) 0;border-width:var(--border-size-small);border-color:var(--color-surface03)}:host(:is([active],[open])) .menu-label,.menu-label:hover,.menu-label:focus-visible,div.menu-label:focus-within{border-color:var(--color-secondary01)}:host([vertical-context]:is([active],[open])) .menu-label::after,:host([vertical-context]) .menu-label:hover::after,:host([vertical-context]) .menu-label:focus-visible::after,:host([vertical-context]) div.menu-label:focus-within::after{position:absolute;bottom:0;left:0;width:100%;height:var(--border-size-large);background-color:var(--color-secondary01);content:\"\"}:host([vertical-context]) .menu-label ::slotted(*){padding:0}.menu-label ::slotted(*){display:inline-flex;width:100%;min-width:fit-content;padding-bottom:2px;margin:0;appearance:none;color:var(--z-menu-label-color, var(--color-default-text));font-family:var(--font-family-sans);font-size:var(--font-size-3);font-weight:inherit;line-height:1.5}.menu-label z-icon{margin-left:calc(var(--space-unit) * 1.5);fill:var(--color-default-icon)}::slotted([data-text]:not([slot]))::after{height:0;content:attr(data-text);content:attr(data-text) / \"\";font-weight:var(--font-bd);letter-spacing:normal;pointer-events:none;user-select:none;visibility:hidden}@media speech{::slotted([data-text]:not([slot]))::after{display:none}}::slotted([data-text]:not([slot])){display:inline-flex;flex-direction:column}.content{background:var(--color-surface01)}:host(:not([open])) .content{display:none}:host([floating]:not([vertical-context])) .content{position:absolute;top:100%;left:0;width:375px;min-width:100%;max-width:100vw;padding:0 calc(var(--space-unit) * 2);box-shadow:var(--shadow-2)}:host(:not([floating])) .content{width:100%}.header{display:flex;align-items:center;padding:var(--space-unit) 0 calc(var(--space-unit) * 2)}.header ::slotted(img[slot=\"header\"]){width:calc(var(--space-unit) * 11.25);height:auto;object-fit:contain}.header ::slotted([slot=\"header\"]:not(:first-child)){margin:auto 0;margin-left:calc(var(--space-unit) * 2.5);font-size:var(--font-size-3);font-weight:var(--font-sb);line-height:1.5}.items{display:flex;flex-direction:column;align-items:flex-start;background:inherit}.items>::slotted([slot=\"item\"]){width:100%;margin:0;font-size:var(--font-size-3);line-height:1.5}.items>::slotted([slot=\"item\"]:focus:focus-visible){box-shadow:var(--shadow-focus-primary)}.items>::slotted([slot=\"item\"]:not(z-menu-section)){padding:var(--space-unit) 0;border-bottom:var(--border-size-small) solid var(--color-surface03)}:host(:not([vertical-context])) .items>::slotted([slot=\"item\"]:last-child){border-bottom:0}.items>::slotted([slot=\"item\"]:hover),.items>::slotted([slot=\"item\"]:focus:focus-visible),.items>::slotted([slot=\"item\"]:active){border-color:var(--color-secondary01);font-weight:var(--font-bd)}";
6
7
  const ZMenuStyle0 = stylesCss;
7
8
 
8
9
  const isZMenuSection = (el) => (el === null || el === void 0 ? void 0 : el.tagName) === "Z-MENU-SECTION";
@@ -56,12 +57,9 @@ const ZMenu$1 = /*@__PURE__*/ proxyCustomElement(class ZMenu extends HTMLElement
56
57
  setItemsA11yAttrs() {
57
58
  this.items.forEach((item, index) => {
58
59
  const tabindex = index === 0 ? 0 : -1;
59
- if (isZMenuSection(item)) {
60
- item.htmlTabindex = tabindex;
61
- }
62
- else {
60
+ this.setItemTabindex(item, tabindex);
61
+ if (!isZMenuSection(item)) {
63
62
  item.setAttribute("role", "menuitem");
64
- item.tabIndex = tabindex;
65
63
  }
66
64
  });
67
65
  }
@@ -75,6 +73,14 @@ const ZMenu$1 = /*@__PURE__*/ proxyCustomElement(class ZMenu extends HTMLElement
75
73
  }
76
74
  });
77
75
  }
76
+ setItemTabindex(item, tabIndex) {
77
+ if (isZMenuSection(item)) {
78
+ item.htmlTabindex = tabIndex;
79
+ }
80
+ else {
81
+ item.tabIndex = tabIndex;
82
+ }
83
+ }
78
84
  /**
79
85
  * Move focus and adjust the tabindex value of `receiver` and `current` elements,
80
86
  * setting -1 to the `current` and 0 to the `receiver`, then focus the `receiver` element.
@@ -93,18 +99,21 @@ const ZMenu$1 = /*@__PURE__*/ proxyCustomElement(class ZMenu extends HTMLElement
93
99
  if (!current) {
94
100
  return;
95
101
  }
96
- if (isZMenuSection(current)) {
97
- current.htmlTabindex = -1;
98
- }
99
- else {
100
- current.tabIndex = -1;
101
- }
102
+ this.setItemTabindex(current, -1);
103
+ }
104
+ onLabelClick() {
105
+ this.toggle();
106
+ this.setFocus();
102
107
  }
103
108
  onLabelKeydown(ev) {
104
109
  if (ev.key === KeyboardCode.ENTER || ev.key === KeyboardCode.SPACE) {
105
110
  ev.preventDefault();
106
111
  ev.stopPropagation();
107
112
  this.toggle();
113
+ if (this.open) {
114
+ this.moveFocus(this.items[0]);
115
+ }
116
+ return;
108
117
  }
109
118
  if (!this.verticalContext) {
110
119
  return;
@@ -113,12 +122,7 @@ const ZMenu$1 = /*@__PURE__*/ proxyCustomElement(class ZMenu extends HTMLElement
113
122
  ev.preventDefault();
114
123
  ev.stopPropagation();
115
124
  this.open = true;
116
- return;
117
- }
118
- if (ev.key === KeyboardCode.ARROW_LEFT && this.open) {
119
- ev.preventDefault();
120
- ev.stopPropagation();
121
- this.open = false;
125
+ this.moveFocus(this.items[0]);
122
126
  }
123
127
  }
124
128
  /** Set tabindex of the label to 0, then focus it. */
@@ -127,13 +131,18 @@ const ZMenu$1 = /*@__PURE__*/ proxyCustomElement(class ZMenu extends HTMLElement
127
131
  const label = this.hasContent ? this.labelButton : this.host.firstElementChild;
128
132
  label.focus();
129
133
  }
130
- /** Focus the last item. */
134
+ /**
135
+ * Focus the last item.
136
+ */
131
137
  async focusLastItem() {
132
- this.htmlTabindex = 0;
133
- this.moveFocus(this.items[this.items.length - 1]);
138
+ const lastItem = this.items[this.items.length - 1];
139
+ if (isZMenuSection(lastItem) && lastItem.open) {
140
+ lastItem.focusLastItem();
141
+ return;
142
+ }
143
+ this.moveFocus(lastItem);
134
144
  }
135
145
  onOpenChanged() {
136
- this.setItemsA11yAttrs();
137
146
  if (!this.open) {
138
147
  cancelAnimationFrame(this.raf);
139
148
  this.closed.emit();
@@ -144,6 +153,7 @@ const ZMenu$1 = /*@__PURE__*/ proxyCustomElement(class ZMenu extends HTMLElement
144
153
  });
145
154
  return;
146
155
  }
156
+ this.setItemsA11yAttrs();
147
157
  this.opened.emit();
148
158
  if (this.floating) {
149
159
  this.reflow(true);
@@ -161,74 +171,108 @@ const ZMenu$1 = /*@__PURE__*/ proxyCustomElement(class ZMenu extends HTMLElement
161
171
  slottedLabel.role = "menuitem";
162
172
  slottedLabel.tabIndex = this.htmlTabindex;
163
173
  }
174
+ /**
175
+ * Set tabindex to -1 to all siblings of the clicked item.
176
+ */
177
+ onItemClick(ev) {
178
+ const clickedItem = this.items.find((item) => containsElement(item, ev.target));
179
+ if (clickedItem) {
180
+ this.items.forEach((item) => {
181
+ if (item === clickedItem) {
182
+ return;
183
+ }
184
+ if (isZMenuSection(item)) {
185
+ item.htmlTabindex = -1;
186
+ }
187
+ else {
188
+ item.tabIndex = -1;
189
+ }
190
+ });
191
+ }
192
+ }
164
193
  onKeyDown(ev) {
194
+ var _a;
165
195
  if (!this.hasContent) {
166
196
  return;
167
197
  }
168
198
  switch (ev.key) {
169
199
  case KeyboardCode.ESC:
200
+ if (!this.open) {
201
+ break;
202
+ }
170
203
  ev.stopPropagation();
171
204
  ev.preventDefault();
172
205
  this.open = false;
173
206
  this.setFocus();
174
207
  break;
175
208
  case KeyboardCode.ARROW_DOWN: {
176
- if (this.verticalContext && document.activeElement === this.host && !this.open) {
177
- break;
178
- }
179
209
  if (document.activeElement === this.host) {
180
- if (!this.open) {
181
- this.open = true;
210
+ if (this.verticalContext && !this.open) {
211
+ break;
182
212
  }
183
213
  ev.stopPropagation();
184
214
  ev.preventDefault();
215
+ if (!this.open) {
216
+ this.open = true;
217
+ }
185
218
  this.moveFocus(this.items[0]);
186
219
  break;
187
220
  }
188
221
  const currentIndex = this.items.indexOf(this.focusableItem);
189
- const receiver = this.items[currentIndex + 1];
190
- if (this.verticalContext && !receiver) {
222
+ if (this.verticalContext && currentIndex === this.items.length - 1) {
223
+ // navigation is going to leave this menu. restore tabindex to the label and let the parent handle it
224
+ this.setItemTabindex(this.items[currentIndex], -1);
225
+ this.htmlTabindex = 0;
191
226
  break;
192
227
  }
193
228
  ev.stopPropagation();
194
229
  ev.preventDefault();
230
+ const receiver = this.items[currentIndex + 1];
195
231
  // if the last item is already focused, navigate to the first one
196
232
  this.moveFocus(receiver !== null && receiver !== void 0 ? receiver : this.items[0], this.focusableItem);
197
233
  break;
198
234
  }
199
235
  case KeyboardCode.ARROW_UP: {
200
- if (this.verticalContext && document.activeElement === this.host) {
201
- break;
202
- }
203
236
  if (document.activeElement === this.host) {
237
+ if (this.verticalContext) {
238
+ break;
239
+ }
240
+ ev.stopPropagation();
241
+ ev.preventDefault();
204
242
  // open the menu and focus the last item
205
243
  if (!this.open) {
206
244
  this.open = true;
207
245
  }
208
- ev.stopPropagation();
209
- ev.preventDefault();
210
246
  this.moveFocus(this.items[this.items.length - 1], this.focusableItem);
211
247
  break;
212
248
  }
213
249
  ev.stopPropagation();
214
250
  ev.preventDefault();
215
251
  const currentIndex = this.items.indexOf(this.focusableItem);
216
- const receiver = this.items[currentIndex - 1];
217
- if (!receiver && this.verticalContext) {
252
+ if (currentIndex === 0 && this.verticalContext) {
253
+ this.setItemTabindex(this.focusableItem, -1);
218
254
  this.setFocus();
219
255
  break;
220
256
  }
257
+ const receiver = (_a = this.items[currentIndex - 1]) !== null && _a !== void 0 ? _a : this.items[this.items.length - 1];
258
+ // if the receiver is a ZMenuSection and it's open, focus its last item
221
259
  if (isZMenuSection(receiver) && receiver.open) {
222
- isZMenuSection(this.focusableItem)
223
- ? (this.focusableItem.htmlTabindex = -1)
224
- : (this.focusableItem.tabIndex = -1);
260
+ this.setItemTabindex(this.focusableItem, -1);
225
261
  receiver.focusLastItem();
226
262
  break;
227
263
  }
228
- // if the first item is already focused, navigate to the last one
229
- this.moveFocus(receiver !== null && receiver !== void 0 ? receiver : this.items[this.items.length - 1], this.focusableItem);
264
+ this.moveFocus(receiver, this.focusableItem);
230
265
  break;
231
266
  }
267
+ case KeyboardCode.ARROW_LEFT:
268
+ if (!this.open || !this.verticalContext) {
269
+ break;
270
+ }
271
+ // close the menu and focus the label
272
+ ev.preventDefault();
273
+ ev.stopPropagation();
274
+ this.open = false;
275
+ this.setFocus();
232
276
  }
233
277
  }
234
278
  constructor() {
@@ -247,6 +291,7 @@ const ZMenu$1 = /*@__PURE__*/ proxyCustomElement(class ZMenu extends HTMLElement
247
291
  this.toggle = this.toggle.bind(this);
248
292
  this.checkContent = this.checkContent.bind(this);
249
293
  this.onLabelSlotChange = this.onLabelSlotChange.bind(this);
294
+ this.onLabelClick = this.onLabelClick.bind(this);
250
295
  this.onItemsChange = this.onItemsChange.bind(this);
251
296
  this.onLabelKeydown = this.onLabelKeydown.bind(this);
252
297
  }
@@ -256,9 +301,9 @@ const ZMenu$1 = /*@__PURE__*/ proxyCustomElement(class ZMenu extends HTMLElement
256
301
  }
257
302
  render() {
258
303
  if (!this.hasContent) {
259
- return (h("div", { class: "menu-wrapper" }, h("div", { class: "menu-label" }, h("div", { class: "menu-label-content" }, h("slot", { onSlotchange: this.onLabelSlotChange })))));
304
+ return (h("div", { class: "menu-label" }, h("slot", { onSlotchange: this.onLabelSlotChange })));
260
305
  }
261
- return (h(Host, null, h("div", { class: "menu-wrapper" }, h("button", { ref: (el) => (this.labelButton = el), class: "menu-label", "aria-expanded": `${!!this.open}`, "aria-haspopup": `${this.hasContent}`, "aria-label": this.open ? "Chiudi menù" : "Apri menù", role: "menuitem", tabindex: this.htmlTabindex, onClick: this.toggle, onKeyDown: this.onLabelKeydown }, h("div", { class: "menu-label-content" }, h("slot", { onSlotchange: this.onLabelSlotChange }), h("z-icon", { name: this.open ? "chevron-up" : "chevron-down" })))), h("div", { class: "content", ref: (el) => (this.content = el) }, this.hasHeader && (h("header", { class: "header" }, h("slot", { name: "header", onSlotchange: this.checkContent }))), h("div", { class: "items", role: "menu" }, h("slot", { name: "item", onSlotchange: this.onItemsChange })))));
306
+ return (h(Host, null, h("button", { ref: (el) => (this.labelButton = el), class: "menu-label", "aria-expanded": `${!!this.open}`, "aria-haspopup": `${this.hasContent}`, "aria-label": this.open ? "Chiudi menù" : "Apri menù", role: "menuitem", tabIndex: this.htmlTabindex, onClick: this.onLabelClick, onKeyDown: this.onLabelKeydown }, h("slot", { onSlotchange: this.onLabelSlotChange }), h("z-icon", { name: this.open ? "chevron-up" : "chevron-down" })), h("div", { class: "content", ref: (el) => (this.content = el) }, this.hasHeader && (h("header", { class: "header" }, h("slot", { name: "header", onSlotchange: this.checkContent }))), h("div", { class: "items", role: "menu" }, h("slot", { name: "item", onSlotchange: this.onItemsChange })))));
262
307
  }
263
308
  get host() { return this; }
264
309
  static get watchers() { return {
@@ -276,7 +321,7 @@ const ZMenu$1 = /*@__PURE__*/ proxyCustomElement(class ZMenu extends HTMLElement
276
321
  "hasContent": [32],
277
322
  "setFocus": [64],
278
323
  "focusLastItem": [64]
279
- }, [[0, "keydown", "onKeyDown"]], {
324
+ }, [[4, "click", "onItemClick"], [0, "keydown", "onKeyDown"]], {
280
325
  "open": ["onOpenChanged"],
281
326
  "htmlTabindex": ["setLabelA11yAttrs"]
282
327
  }]);