@zanichelli/albe-web-components 16.3.1 → 16.3.3

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 (90) hide show
  1. package/CHANGELOG.md +4 -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 +72 -19
  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 +96 -49
  9. package/dist/cjs/z-menu.cjs.entry.js.map +1 -1
  10. package/dist/cjs/z-navigation-tabs.cjs.entry.js +9 -5
  11. package/dist/cjs/z-navigation-tabs.cjs.entry.js.map +1 -1
  12. package/dist/collection/components/z-app-header/index.js +77 -15
  13. package/dist/collection/components/z-app-header/index.js.map +1 -1
  14. package/dist/collection/components/z-app-header/index.stories.js +50 -116
  15. package/dist/collection/components/z-app-header/index.stories.js.map +1 -1
  16. package/dist/collection/components/z-app-header/styles.css +39 -27
  17. package/dist/collection/components/z-menu/index.js +100 -48
  18. package/dist/collection/components/z-menu/index.js.map +1 -1
  19. package/dist/collection/components/z-menu/styles.css +40 -52
  20. package/dist/collection/components/z-menu-section/index.js +31 -16
  21. package/dist/collection/components/z-menu-section/index.js.map +1 -1
  22. package/dist/collection/components/z-menu-section/styles.css +8 -0
  23. package/dist/collection/components/z-navigation-tabs/index.js +9 -5
  24. package/dist/collection/components/z-navigation-tabs/index.js.map +1 -1
  25. package/dist/collection/components/z-offcanvas/styles.css +4 -4
  26. package/dist/collection/components/z-searchbar/index.js +14 -5
  27. package/dist/collection/components/z-searchbar/index.js.map +1 -1
  28. package/dist/components/index21.js +1 -1
  29. package/dist/components/index21.js.map +1 -1
  30. package/dist/components/index23.js +14 -5
  31. package/dist/components/index23.js.map +1 -1
  32. package/dist/components/z-app-header.js +61 -16
  33. package/dist/components/z-app-header.js.map +1 -1
  34. package/dist/components/z-menu-section.js +30 -15
  35. package/dist/components/z-menu-section.js.map +1 -1
  36. package/dist/components/z-menu.js +96 -50
  37. package/dist/components/z-menu.js.map +1 -1
  38. package/dist/components/z-navigation-tabs.js +9 -5
  39. package/dist/components/z-navigation-tabs.js.map +1 -1
  40. package/dist/esm/loader.js +1 -1
  41. package/dist/esm/web-components-library.js +1 -1
  42. package/dist/esm/z-app-header_12.entry.js +72 -19
  43. package/dist/esm/z-app-header_12.entry.js.map +1 -1
  44. package/dist/esm/z-menu-section.entry.js +28 -13
  45. package/dist/esm/z-menu-section.entry.js.map +1 -1
  46. package/dist/esm/z-menu.entry.js +96 -49
  47. package/dist/esm/z-menu.entry.js.map +1 -1
  48. package/dist/esm/z-navigation-tabs.entry.js +9 -5
  49. package/dist/esm/z-navigation-tabs.entry.js.map +1 -1
  50. package/dist/types/components/z-app-header/index.d.ts +8 -7
  51. package/dist/types/components/z-menu/index.d.ts +10 -2
  52. package/dist/types/components/z-menu-section/index.d.ts +4 -2
  53. package/dist/types/components/z-searchbar/index.d.ts +1 -0
  54. package/dist/types/components.d.ts +8 -0
  55. package/dist/web-components-library/p-02418303.entry.js +2 -0
  56. package/dist/web-components-library/p-02418303.entry.js.map +1 -0
  57. package/dist/web-components-library/p-587aa850.entry.js +2 -0
  58. package/dist/web-components-library/p-587aa850.entry.js.map +1 -0
  59. package/dist/web-components-library/p-8e5f1ae0.entry.js +2 -0
  60. package/dist/web-components-library/p-8e5f1ae0.entry.js.map +1 -0
  61. package/dist/web-components-library/{p-6db2fd46.entry.js → p-f9aa2d11.entry.js} +2 -2
  62. package/dist/web-components-library/{p-6db2fd46.entry.js.map → p-f9aa2d11.entry.js.map} +1 -1
  63. package/dist/web-components-library/web-components-library.esm.js +1 -1
  64. package/dist/web-components-library/web-components-library.esm.js.map +1 -1
  65. package/package.json +1 -1
  66. package/www/build/p-02418303.entry.js +2 -0
  67. package/www/build/p-02418303.entry.js.map +1 -0
  68. package/www/build/p-587aa850.entry.js +2 -0
  69. package/www/build/p-587aa850.entry.js.map +1 -0
  70. package/www/build/p-8e5f1ae0.entry.js +2 -0
  71. package/www/build/p-8e5f1ae0.entry.js.map +1 -0
  72. package/www/build/p-f7420b16.js +2 -0
  73. package/www/build/{p-6db2fd46.entry.js → p-f9aa2d11.entry.js} +2 -2
  74. package/www/build/{p-6db2fd46.entry.js.map → p-f9aa2d11.entry.js.map} +1 -1
  75. package/www/build/web-components-library.esm.js +1 -1
  76. package/www/build/web-components-library.esm.js.map +1 -1
  77. package/www/index.html +1 -1
  78. package/dist/web-components-library/p-04c39e8a.entry.js +0 -2
  79. package/dist/web-components-library/p-04c39e8a.entry.js.map +0 -1
  80. package/dist/web-components-library/p-0542a3c9.entry.js +0 -2
  81. package/dist/web-components-library/p-0542a3c9.entry.js.map +0 -1
  82. package/dist/web-components-library/p-16d625b3.entry.js +0 -2
  83. package/dist/web-components-library/p-16d625b3.entry.js.map +0 -1
  84. package/www/build/p-04c39e8a.entry.js +0 -2
  85. package/www/build/p-04c39e8a.entry.js.map +0 -1
  86. package/www/build/p-0542a3c9.entry.js +0 -2
  87. package/www/build/p-0542a3c9.entry.js.map +0 -1
  88. package/www/build/p-16d625b3.entry.js +0 -2
  89. package/www/build/p-16d625b3.entry.js.map +0 -1
  90. package/www/build/p-ae5cec65.js +0 -2
@@ -5,7 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  const index$1 = require('./index-96af6326.js');
6
6
  const index = require('./index-bab7a651.js');
7
7
 
8
- 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)}";
8
+ 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)}";
9
9
  const ZMenuSectionStyle0 = stylesCss;
10
10
 
11
11
  const ZMenuSection = class {
@@ -17,15 +17,14 @@ const ZMenuSection = class {
17
17
  return;
18
18
  }
19
19
  this.open = !this.open;
20
- this.setFocus();
21
20
  }
22
21
  setItemsA11yAttrs() {
23
22
  if (!this.hasItems) {
24
23
  return;
25
24
  }
26
- this.items.forEach((item, index) => {
25
+ this.items.forEach((item) => {
27
26
  item.setAttribute("role", "menuitem");
28
- item.setAttribute("tabindex", index === 0 ? "0" : "-1");
27
+ item.tabIndex = -1;
29
28
  });
30
29
  }
31
30
  onItemsChange() {
@@ -41,11 +40,18 @@ const ZMenuSection = class {
41
40
  const labelElement = ev.target.assignedElements()[0];
42
41
  labelElement.dataset.text = labelElement === null || labelElement === void 0 ? void 0 : labelElement.textContent;
43
42
  }
43
+ onLabelClick() {
44
+ this.toggle();
45
+ this.setFocus();
46
+ }
44
47
  onLabelKeydown(ev) {
45
48
  if (ev.key === index.KeyboardCode.ENTER || ev.key === index.KeyboardCode.SPACE) {
46
49
  ev.preventDefault();
47
50
  ev.stopPropagation();
48
51
  this.toggle();
52
+ if (this.open) {
53
+ this.focustFirstItem();
54
+ }
49
55
  }
50
56
  }
51
57
  /**
@@ -61,6 +67,13 @@ const ZMenuSection = class {
61
67
  current.tabIndex = -1;
62
68
  }
63
69
  }
70
+ focustFirstItem() {
71
+ this.moveFocus(this.items[0]);
72
+ }
73
+ /** Focus the last item. */
74
+ async focusLastItem() {
75
+ this.moveFocus(this.items[this.items.length - 1]);
76
+ }
64
77
  /** Set tabindex of the label to 0, then focus it. */
65
78
  async setFocus() {
66
79
  this.htmlTabindex = 0;
@@ -68,15 +81,10 @@ const ZMenuSection = class {
68
81
  this.label.focus();
69
82
  }, 100);
70
83
  }
71
- /** Focus the last item. */
72
- async focusLastItem() {
73
- this.htmlTabindex = 0;
74
- this.moveFocus(this.items[this.items.length - 1]);
75
- }
76
84
  onOpenChange() {
77
85
  if (!this.open) {
78
- this.closed.emit();
79
86
  this.setItemsA11yAttrs();
87
+ this.closed.emit();
80
88
  }
81
89
  else {
82
90
  this.opened.emit();
@@ -94,7 +102,7 @@ const ZMenuSection = class {
94
102
  }
95
103
  ev.preventDefault();
96
104
  ev.stopPropagation();
97
- this.label.focus();
105
+ this.moveFocus(this.label, this.focusableItem);
98
106
  this.open = false;
99
107
  break;
100
108
  case index.KeyboardCode.ARROW_RIGHT:
@@ -104,6 +112,7 @@ const ZMenuSection = class {
104
112
  ev.preventDefault();
105
113
  ev.stopPropagation();
106
114
  this.open = true;
115
+ this.focustFirstItem();
107
116
  break;
108
117
  case index.KeyboardCode.ARROW_DOWN: {
109
118
  if (!this.open) {
@@ -112,7 +121,7 @@ const ZMenuSection = class {
112
121
  if (document.activeElement === this.host) {
113
122
  ev.preventDefault();
114
123
  ev.stopPropagation();
115
- this.moveFocus(this.items[0]);
124
+ this.focustFirstItem();
116
125
  break;
117
126
  }
118
127
  const currentIndex = this.items.indexOf(this.focusableItem);
@@ -122,6 +131,10 @@ const ZMenuSection = class {
122
131
  ev.stopPropagation();
123
132
  this.moveFocus(receiver, this.focusableItem);
124
133
  }
134
+ else {
135
+ this.htmlTabindex = 0;
136
+ this.focusableItem.tabIndex = -1;
137
+ }
125
138
  break;
126
139
  }
127
140
  case index.KeyboardCode.ARROW_UP: {
@@ -137,6 +150,7 @@ const ZMenuSection = class {
137
150
  }
138
151
  else {
139
152
  // since there isn't a previous item to focus, give the focus to the label element
153
+ this.focusableItem.tabIndex = -1;
140
154
  this.setFocus();
141
155
  }
142
156
  break;
@@ -155,6 +169,7 @@ const ZMenuSection = class {
155
169
  this.toggle = this.toggle.bind(this);
156
170
  this.onItemsChange = this.onItemsChange.bind(this);
157
171
  this.onLabelSlotChange = this.onLabelSlotChange.bind(this);
172
+ this.onLabelClick = this.onLabelClick.bind(this);
158
173
  this.onLabelKeydown = this.onLabelKeydown.bind(this);
159
174
  this.onItemsKeydown = this.onItemsKeydown.bind(this);
160
175
  }
@@ -162,7 +177,7 @@ const ZMenuSection = class {
162
177
  this.onItemsChange();
163
178
  }
164
179
  render() {
165
- return (index$1.h(index$1.Host, { key: '387e43b42ac8233f88d329a592bef924ebcf9ee9', open: this.open }, index$1.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 }, index$1.h("slot", { key: 'd0065cf62f83d83df43b5c2413d3e13b23a1bb6a', onSlotchange: this.onLabelSlotChange }), this.hasItems && index$1.h("z-icon", { key: 'e6adc51de79f1fbcb76b025cd6226388ff4d90f0', name: this.open ? "chevron-up" : "chevron-down" })), this.open && (index$1.h("div", { key: '151f31f24ec306ce4cb45b70b8ae5a6023fd063d', class: "items", role: "menu" }, index$1.h("slot", { key: 'd4d67539788121360de0e4dabf51ba22086c1345', name: "section", onSlotchange: this.onItemsChange })))));
180
+ return (index$1.h(index$1.Host, { key: '4d9223bebf25df5eb224a7674c920ebc17470826', open: this.open }, index$1.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 }, index$1.h("slot", { key: '0a3b20723371deac12792436d977c343c237720b', onSlotchange: this.onLabelSlotChange }), this.hasItems && index$1.h("z-icon", { key: '7fe5e9dc4a9eac28f0f3a381fedbe0ec3e7ca99d', name: this.open ? "chevron-up" : "chevron-down" })), index$1.h("div", { key: '80e167ce90df12c27eddc1e28b6bf6dd3b5d0dd7', class: "items", role: "menu", hidden: !this.open }, index$1.h("slot", { key: 'a0e88a56848abf198ced22e4fc390267aea6114e', name: "section", onSlotchange: this.onItemsChange }))));
166
181
  }
167
182
  get host() { return index$1.getElement(this); }
168
183
  static get watchers() { return {
@@ -1 +1 @@
1
- {"file":"z-menu-section.entry.cjs.js","mappings":"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","names":["KeyboardCode","h","Host"],"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.entry.cjs.js","mappings":"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","names":["KeyboardCode","h","Host"],"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}
@@ -4,8 +4,10 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  const index$1 = require('./index-96af6326.js');
6
6
  const index = require('./index-bab7a651.js');
7
+ const utils = require('./utils-257558ff.js');
8
+ require('./breakpoints-8a1e87e0.js');
7
9
 
8
- 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)}";
10
+ 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)}";
9
11
  const ZMenuStyle0 = stylesCss;
10
12
 
11
13
  const isZMenuSection = (el) => (el === null || el === void 0 ? void 0 : el.tagName) === "Z-MENU-SECTION";
@@ -33,6 +35,9 @@ const ZMenu = class {
33
35
  * @param live Should run the method on every refresh frame.
34
36
  */
35
37
  reflow(live = false) {
38
+ if (!this.floating) {
39
+ return;
40
+ }
36
41
  if (this.content && this.hasContent) {
37
42
  const { style } = this.content;
38
43
  const { left } = this.host.getBoundingClientRect();
@@ -52,6 +57,14 @@ const ZMenu = class {
52
57
  this.hasHeader = !!this.host.querySelectorAll("[slot=header]").length;
53
58
  this.hasContent = !!this.host.querySelectorAll("[slot=item]").length || this.hasHeader;
54
59
  }
60
+ setItemTabindex(item, tabIndex) {
61
+ if (isZMenuSection(item)) {
62
+ item.htmlTabindex = tabIndex;
63
+ }
64
+ else {
65
+ item.tabIndex = tabIndex;
66
+ }
67
+ }
55
68
  /**
56
69
  * Set `menuitem` role to all menu items (ZMenuSection items already have it).
57
70
  * Set -1 to the tabindex of the items and 0 to the first one.
@@ -59,12 +72,9 @@ const ZMenu = class {
59
72
  setItemsA11yAttrs() {
60
73
  this.items.forEach((item, index) => {
61
74
  const tabindex = index === 0 ? 0 : -1;
62
- if (isZMenuSection(item)) {
63
- item.htmlTabindex = tabindex;
64
- }
65
- else {
75
+ this.setItemTabindex(item, tabindex);
76
+ if (!isZMenuSection(item)) {
66
77
  item.setAttribute("role", "menuitem");
67
- item.tabIndex = tabindex;
68
78
  }
69
79
  });
70
80
  }
@@ -96,18 +106,21 @@ const ZMenu = class {
96
106
  if (!current) {
97
107
  return;
98
108
  }
99
- if (isZMenuSection(current)) {
100
- current.htmlTabindex = -1;
101
- }
102
- else {
103
- current.tabIndex = -1;
104
- }
109
+ this.setItemTabindex(current, -1);
110
+ }
111
+ onLabelClick() {
112
+ this.toggle();
113
+ this.setFocus();
105
114
  }
106
115
  onLabelKeydown(ev) {
107
116
  if (ev.key === index.KeyboardCode.ENTER || ev.key === index.KeyboardCode.SPACE) {
108
117
  ev.preventDefault();
109
118
  ev.stopPropagation();
110
119
  this.toggle();
120
+ if (this.open) {
121
+ this.moveFocus(this.items[0]);
122
+ }
123
+ return;
111
124
  }
112
125
  if (!this.verticalContext) {
113
126
  return;
@@ -116,12 +129,7 @@ const ZMenu = class {
116
129
  ev.preventDefault();
117
130
  ev.stopPropagation();
118
131
  this.open = true;
119
- return;
120
- }
121
- if (ev.key === index.KeyboardCode.ARROW_LEFT && this.open) {
122
- ev.preventDefault();
123
- ev.stopPropagation();
124
- this.open = false;
132
+ this.moveFocus(this.items[0]);
125
133
  }
126
134
  }
127
135
  /** Set tabindex of the label to 0, then focus it. */
@@ -130,13 +138,18 @@ const ZMenu = class {
130
138
  const label = this.hasContent ? this.labelButton : this.host.firstElementChild;
131
139
  label.focus();
132
140
  }
133
- /** Focus the last item. */
141
+ /**
142
+ * Focus the last item.
143
+ */
134
144
  async focusLastItem() {
135
- this.htmlTabindex = 0;
136
- this.moveFocus(this.items[this.items.length - 1]);
145
+ const lastItem = this.items[this.items.length - 1];
146
+ if (isZMenuSection(lastItem) && lastItem.open) {
147
+ lastItem.focusLastItem();
148
+ return;
149
+ }
150
+ this.moveFocus(lastItem);
137
151
  }
138
152
  onOpenChanged() {
139
- this.setItemsA11yAttrs();
140
153
  if (!this.open) {
141
154
  cancelAnimationFrame(this.raf);
142
155
  this.closed.emit();
@@ -147,16 +160,14 @@ const ZMenu = class {
147
160
  });
148
161
  return;
149
162
  }
163
+ this.setItemsA11yAttrs();
150
164
  this.opened.emit();
151
165
  if (this.floating) {
152
166
  this.reflow(true);
153
167
  }
154
168
  }
155
169
  setLabelA11yAttrs() {
156
- if (this.hasContent && !this.labelButton) {
157
- return;
158
- }
159
- if (this.hasContent) {
170
+ if (this.hasContent && this.labelButton) {
160
171
  this.labelButton.tabIndex = this.htmlTabindex;
161
172
  return;
162
173
  }
@@ -164,80 +175,115 @@ const ZMenu = class {
164
175
  slottedLabel.role = "menuitem";
165
176
  slottedLabel.tabIndex = this.htmlTabindex;
166
177
  }
178
+ /**
179
+ * Set tabindex to -1 to all siblings of the clicked item.
180
+ */
181
+ onItemClick(ev) {
182
+ const clickedItem = this.items.find((item) => utils.containsElement(item, ev.target));
183
+ if (clickedItem) {
184
+ this.items.forEach((item) => {
185
+ if (item === clickedItem) {
186
+ return;
187
+ }
188
+ if (isZMenuSection(item)) {
189
+ item.htmlTabindex = -1;
190
+ }
191
+ else {
192
+ item.tabIndex = -1;
193
+ }
194
+ });
195
+ }
196
+ }
167
197
  onKeyDown(ev) {
198
+ var _a;
168
199
  if (!this.hasContent) {
169
200
  return;
170
201
  }
171
202
  switch (ev.key) {
172
203
  case index.KeyboardCode.ESC:
204
+ if (!this.open) {
205
+ break;
206
+ }
173
207
  ev.stopPropagation();
174
208
  ev.preventDefault();
175
209
  this.open = false;
176
210
  this.setFocus();
177
211
  break;
178
212
  case index.KeyboardCode.ARROW_DOWN: {
179
- if (this.verticalContext && document.activeElement === this.host && !this.open) {
180
- break;
181
- }
182
213
  if (document.activeElement === this.host) {
183
- if (!this.open) {
184
- this.open = true;
214
+ if (this.verticalContext && !this.open) {
215
+ break;
185
216
  }
186
217
  ev.stopPropagation();
187
218
  ev.preventDefault();
219
+ if (!this.open) {
220
+ this.open = true;
221
+ }
188
222
  this.moveFocus(this.items[0]);
189
223
  break;
190
224
  }
191
225
  const currentIndex = this.items.indexOf(this.focusableItem);
192
- const receiver = this.items[currentIndex + 1];
193
- if (this.verticalContext && !receiver) {
226
+ if (this.verticalContext && currentIndex === this.items.length - 1) {
227
+ // navigation is going to leave this menu. restore tabindex to the label and let the parent handle it
228
+ this.setItemTabindex(this.items[currentIndex], -1);
229
+ this.htmlTabindex = 0;
194
230
  break;
195
231
  }
196
232
  ev.stopPropagation();
197
233
  ev.preventDefault();
234
+ const receiver = this.items[currentIndex + 1];
198
235
  // if the last item is already focused, navigate to the first one
199
236
  this.moveFocus(receiver !== null && receiver !== void 0 ? receiver : this.items[0], this.focusableItem);
200
237
  break;
201
238
  }
202
239
  case index.KeyboardCode.ARROW_UP: {
203
- if (this.verticalContext && document.activeElement === this.host) {
204
- break;
205
- }
206
240
  if (document.activeElement === this.host) {
241
+ if (this.verticalContext) {
242
+ break;
243
+ }
244
+ ev.stopPropagation();
245
+ ev.preventDefault();
207
246
  // open the menu and focus the last item
208
247
  if (!this.open) {
209
248
  this.open = true;
210
249
  }
211
- ev.stopPropagation();
212
- ev.preventDefault();
213
250
  this.moveFocus(this.items[this.items.length - 1], this.focusableItem);
214
251
  break;
215
252
  }
216
253
  ev.stopPropagation();
217
254
  ev.preventDefault();
218
255
  const currentIndex = this.items.indexOf(this.focusableItem);
219
- const receiver = this.items[currentIndex - 1];
220
- if (!receiver && this.verticalContext) {
256
+ if (currentIndex === 0 && this.verticalContext) {
257
+ this.setItemTabindex(this.focusableItem, -1);
221
258
  this.setFocus();
222
259
  break;
223
260
  }
261
+ const receiver = (_a = this.items[currentIndex - 1]) !== null && _a !== void 0 ? _a : this.items[this.items.length - 1];
262
+ // if the receiver is a ZMenuSection and it's open, focus its last item
224
263
  if (isZMenuSection(receiver) && receiver.open) {
225
- isZMenuSection(this.focusableItem)
226
- ? (this.focusableItem.htmlTabindex = -1)
227
- : (this.focusableItem.tabIndex = -1);
264
+ this.setItemTabindex(this.focusableItem, -1);
228
265
  receiver.focusLastItem();
229
266
  break;
230
267
  }
231
- // if the first item is already focused, navigate to the last one
232
- this.moveFocus(receiver !== null && receiver !== void 0 ? receiver : this.items[this.items.length - 1], this.focusableItem);
268
+ this.moveFocus(receiver, this.focusableItem);
233
269
  break;
234
270
  }
271
+ case index.KeyboardCode.ARROW_LEFT:
272
+ if (!this.open || !this.verticalContext) {
273
+ break;
274
+ }
275
+ // close the menu and focus the label
276
+ ev.preventDefault();
277
+ ev.stopPropagation();
278
+ this.open = false;
279
+ this.setFocus();
235
280
  }
236
281
  }
237
282
  constructor(hostRef) {
238
283
  index$1.registerInstance(this, hostRef);
239
284
  this.opened = index$1.createEvent(this, "opened", 7);
240
285
  this.closed = index$1.createEvent(this, "closed", 7);
286
+ this.items = [];
241
287
  this.active = undefined;
242
288
  this.floating = true;
243
289
  this.open = false;
@@ -248,18 +294,19 @@ const ZMenu = class {
248
294
  this.toggle = this.toggle.bind(this);
249
295
  this.checkContent = this.checkContent.bind(this);
250
296
  this.onLabelSlotChange = this.onLabelSlotChange.bind(this);
297
+ this.onLabelClick = this.onLabelClick.bind(this);
251
298
  this.onItemsChange = this.onItemsChange.bind(this);
252
299
  this.onLabelKeydown = this.onLabelKeydown.bind(this);
253
300
  }
254
- connectedCallback() {
255
- this.onItemsChange();
301
+ componentWillLoad() {
256
302
  this.setLabelA11yAttrs();
303
+ this.onItemsChange();
257
304
  }
258
305
  render() {
259
306
  if (!this.hasContent) {
260
- return (index$1.h("div", { class: "menu-wrapper" }, index$1.h("div", { class: "menu-label" }, index$1.h("div", { class: "menu-label-content" }, index$1.h("slot", { onSlotchange: this.onLabelSlotChange })))));
307
+ return (index$1.h("div", { class: "menu-label" }, index$1.h("slot", { onSlotchange: this.onLabelSlotChange })));
261
308
  }
262
- return (index$1.h(index$1.Host, null, index$1.h("div", { class: "menu-wrapper" }, index$1.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 }, index$1.h("div", { class: "menu-label-content" }, index$1.h("slot", { onSlotchange: this.onLabelSlotChange }), index$1.h("z-icon", { name: this.open ? "chevron-up" : "chevron-down" })))), index$1.h("div", { class: "content", ref: (el) => (this.content = el) }, this.hasHeader && (index$1.h("header", { class: "header" }, index$1.h("slot", { name: "header", onSlotchange: this.checkContent }))), index$1.h("div", { class: "items", role: "menu" }, index$1.h("slot", { name: "item", onSlotchange: this.onItemsChange })))));
309
+ return (index$1.h(index$1.Host, null, index$1.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 }, index$1.h("slot", { onSlotchange: this.onLabelSlotChange }), index$1.h("z-icon", { name: this.open ? "chevron-up" : "chevron-down" })), index$1.h("div", { class: "content", ref: (el) => (this.content = el) }, this.hasHeader && (index$1.h("header", { class: "header" }, index$1.h("slot", { name: "header", onSlotchange: this.checkContent }))), index$1.h("div", { class: "items", role: "menu" }, index$1.h("slot", { name: "item", onSlotchange: this.onItemsChange })))));
263
310
  }
264
311
  get host() { return index$1.getElement(this); }
265
312
  static get watchers() { return {