@y14e/menu 1.5.2 → 1.5.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.
- package/README.md +5 -5
- package/dist/index.cjs +30 -32
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +30 -32
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,16 +10,16 @@ npm i @y14e/menu
|
|
|
10
10
|
|
|
11
11
|
```ts
|
|
12
12
|
// npm
|
|
13
|
-
import Menu from '@y14e/menu@1.5.
|
|
13
|
+
import Menu from '@y14e/menu@1.5.3';
|
|
14
14
|
// with middleware
|
|
15
|
-
import Menu, { flip, offset, shift } from '@y14e/menu@1.5.
|
|
15
|
+
import Menu, { flip, offset, shift } from '@y14e/menu@1.5.3';
|
|
16
16
|
|
|
17
17
|
// CDNs
|
|
18
|
-
import Menu from 'https://esm.sh/@y14e/menu@1.5.
|
|
18
|
+
import Menu from 'https://esm.sh/@y14e/menu@1.5.3';
|
|
19
19
|
// or
|
|
20
|
-
import Menu from 'https://cdn.jsdelivr.net/npm/@y14e/menu@1.5.
|
|
20
|
+
import Menu from 'https://cdn.jsdelivr.net/npm/@y14e/menu@1.5.3/+esm';
|
|
21
21
|
// or
|
|
22
|
-
import Menu from 'https://esm.unpkg.com/@y14e/menu@1.5.
|
|
22
|
+
import Menu from 'https://esm.unpkg.com/@y14e/menu@1.5.3';
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
## Usage
|
package/dist/index.cjs
CHANGED
|
@@ -2635,14 +2635,14 @@ var Menu = class _Menu {
|
|
|
2635
2635
|
#radioItemElementsByGroup = /* @__PURE__ */ new WeakMap();
|
|
2636
2636
|
#arrowElement;
|
|
2637
2637
|
#controller = null;
|
|
2638
|
+
#cleanupPopover = null;
|
|
2639
|
+
#cleanupPortal = null;
|
|
2640
|
+
#cleanupRovingTabIndex = null;
|
|
2638
2641
|
#animation = null;
|
|
2642
|
+
#buttons = [];
|
|
2639
2643
|
#submenus = [];
|
|
2640
2644
|
#submenuTimer;
|
|
2641
2645
|
#isDestroyed = false;
|
|
2642
|
-
#cleanupPortal = null;
|
|
2643
|
-
#cleanupRovingTabIndex = null;
|
|
2644
|
-
#cleanupPopover = null;
|
|
2645
|
-
#buttons = [];
|
|
2646
2646
|
constructor(root, options = {}, _internal = {}) {
|
|
2647
2647
|
if (!(root instanceof HTMLElement)) {
|
|
2648
2648
|
throw new TypeError("Invalid root element");
|
|
@@ -2752,15 +2752,16 @@ var Menu = class _Menu {
|
|
|
2752
2752
|
}
|
|
2753
2753
|
this.#animation?.cancel();
|
|
2754
2754
|
this.#animation = null;
|
|
2755
|
-
|
|
2755
|
+
const trigger = this.#getTrigger();
|
|
2756
2756
|
const elements = this.#itemElements;
|
|
2757
|
-
if (
|
|
2758
|
-
elements.push(
|
|
2757
|
+
if (trigger) {
|
|
2758
|
+
elements.push(trigger);
|
|
2759
2759
|
}
|
|
2760
2760
|
if (this.#listElement) {
|
|
2761
2761
|
elements.push(this.#listElement);
|
|
2762
2762
|
}
|
|
2763
2763
|
restoreAttributes(elements);
|
|
2764
|
+
this.#externalTrigger = null;
|
|
2764
2765
|
this.#triggerElement = null;
|
|
2765
2766
|
this.#listElement = null;
|
|
2766
2767
|
this.#itemElements.length = 0;
|
|
@@ -2786,9 +2787,10 @@ var Menu = class _Menu {
|
|
|
2786
2787
|
return;
|
|
2787
2788
|
}
|
|
2788
2789
|
saveAttributes([this.#listElement], ["aria-labelledby", "id", "role"]);
|
|
2789
|
-
|
|
2790
|
+
const trigger = this.#getTrigger();
|
|
2791
|
+
if (trigger && this.#triggerElement) {
|
|
2790
2792
|
saveAttributes(
|
|
2791
|
-
[
|
|
2793
|
+
[trigger],
|
|
2792
2794
|
[
|
|
2793
2795
|
"aria-controls",
|
|
2794
2796
|
"aria-disabled",
|
|
@@ -2801,18 +2803,14 @@ var Menu = class _Menu {
|
|
|
2801
2803
|
);
|
|
2802
2804
|
const id = Math.random().toString(36).slice(-8);
|
|
2803
2805
|
this.#listElement.id ||= `menu-list-${id}`;
|
|
2804
|
-
addTokenToAttribute(
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
)
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
if (!isFocusable3(this.#triggerElement)) {
|
|
2813
|
-
this.#triggerElement.setAttribute("aria-disabled", "true");
|
|
2814
|
-
this.#triggerElement.setAttribute("tabindex", "-1");
|
|
2815
|
-
this.#triggerElement.style.setProperty("pointer-events", "none");
|
|
2806
|
+
addTokenToAttribute(trigger, "aria-controls", this.#listElement.id);
|
|
2807
|
+
trigger.setAttribute("aria-expanded", "false");
|
|
2808
|
+
trigger.setAttribute("aria-haspopup", "true");
|
|
2809
|
+
trigger.id ||= `menu-trigger-${id}`;
|
|
2810
|
+
if (!isFocusable3(trigger)) {
|
|
2811
|
+
trigger.setAttribute("aria-disabled", "true");
|
|
2812
|
+
trigger.setAttribute("tabindex", "-1");
|
|
2813
|
+
trigger.style.setProperty("pointer-events", "none");
|
|
2816
2814
|
}
|
|
2817
2815
|
this.#triggerElement.addEventListener("click", this.#onTriggerClick, {
|
|
2818
2816
|
signal
|
|
@@ -2820,11 +2818,7 @@ var Menu = class _Menu {
|
|
|
2820
2818
|
this.#triggerElement.addEventListener("keydown", this.#onTriggerKeyDown, {
|
|
2821
2819
|
signal
|
|
2822
2820
|
});
|
|
2823
|
-
addTokenToAttribute(
|
|
2824
|
-
this.#listElement,
|
|
2825
|
-
"aria-labelledby",
|
|
2826
|
-
this.#triggerElement.id
|
|
2827
|
-
);
|
|
2821
|
+
addTokenToAttribute(this.#listElement, "aria-labelledby", trigger.id);
|
|
2828
2822
|
this.#buttons.push(new Button(this.#triggerElement));
|
|
2829
2823
|
}
|
|
2830
2824
|
this.#listElement.setAttribute("role", "menu");
|
|
@@ -2907,7 +2901,7 @@ var Menu = class _Menu {
|
|
|
2907
2901
|
#onTriggerClick = (event) => {
|
|
2908
2902
|
event.preventDefault();
|
|
2909
2903
|
this.#toggle(
|
|
2910
|
-
this.#isSubmenu ? event.currentTarget === this.#triggerElement : this.#
|
|
2904
|
+
this.#isSubmenu ? event.currentTarget === this.#triggerElement : this.#getTrigger()?.ariaExpanded !== "true"
|
|
2911
2905
|
);
|
|
2912
2906
|
};
|
|
2913
2907
|
#onTriggerKeyDown = (event) => {
|
|
@@ -3001,10 +2995,11 @@ var Menu = class _Menu {
|
|
|
3001
2995
|
});
|
|
3002
2996
|
};
|
|
3003
2997
|
#toggle(isOpen, options = {}) {
|
|
3004
|
-
|
|
2998
|
+
const trigger = this.#getTrigger();
|
|
2999
|
+
if (trigger?.ariaExpanded === String(isOpen)) {
|
|
3005
3000
|
return;
|
|
3006
3001
|
}
|
|
3007
|
-
|
|
3002
|
+
trigger?.setAttribute("aria-expanded", String(isOpen));
|
|
3008
3003
|
if (isOpen) {
|
|
3009
3004
|
_Menu.#menus.filter((m) => !m.#containsRoot(this.#rootElement)).forEach((menu) => {
|
|
3010
3005
|
menu.close();
|
|
@@ -3094,7 +3089,7 @@ var Menu = class _Menu {
|
|
|
3094
3089
|
#closeAndMoveFocus(direction) {
|
|
3095
3090
|
this.close();
|
|
3096
3091
|
requestAnimationFrame(
|
|
3097
|
-
() =>
|
|
3092
|
+
() => this.#getTrigger()?.dispatchEvent(
|
|
3098
3093
|
new KeyboardEvent("keydown", {
|
|
3099
3094
|
key: direction === "previous" ? "ArrowLeft" : "ArrowRight"
|
|
3100
3095
|
})
|
|
@@ -3109,7 +3104,10 @@ var Menu = class _Menu {
|
|
|
3109
3104
|
if (!(active instanceof HTMLElement)) {
|
|
3110
3105
|
return;
|
|
3111
3106
|
}
|
|
3112
|
-
this.#containsRoot(active) &&
|
|
3107
|
+
this.#containsRoot(active) && this.#getTrigger()?.focus();
|
|
3108
|
+
}
|
|
3109
|
+
#getTrigger() {
|
|
3110
|
+
return this.#externalTrigger ?? this.#triggerElement;
|
|
3113
3111
|
}
|
|
3114
3112
|
#includesRoot(event) {
|
|
3115
3113
|
const path = event.composedPath();
|
|
@@ -3265,7 +3263,7 @@ function isFocusable3(element) {
|
|
|
3265
3263
|
* WAI-ARIA compliant menu (menu button) pattern implementation in TypeScript.
|
|
3266
3264
|
* Supports checkbox item, radio item, and infinitely nested menus.
|
|
3267
3265
|
*
|
|
3268
|
-
* @version 1.5.
|
|
3266
|
+
* @version 1.5.3
|
|
3269
3267
|
* @author Yusuke Kamiyamane
|
|
3270
3268
|
* @license MIT
|
|
3271
3269
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.d.cts
CHANGED
|
@@ -6,7 +6,7 @@ export { flip, offset, shift } from '@floating-ui/dom';
|
|
|
6
6
|
* WAI-ARIA compliant menu (menu button) pattern implementation in TypeScript.
|
|
7
7
|
* Supports checkbox item, radio item, and infinitely nested menus.
|
|
8
8
|
*
|
|
9
|
-
* @version 1.5.
|
|
9
|
+
* @version 1.5.3
|
|
10
10
|
* @author Yusuke Kamiyamane
|
|
11
11
|
* @license MIT
|
|
12
12
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export { flip, offset, shift } from '@floating-ui/dom';
|
|
|
6
6
|
* WAI-ARIA compliant menu (menu button) pattern implementation in TypeScript.
|
|
7
7
|
* Supports checkbox item, radio item, and infinitely nested menus.
|
|
8
8
|
*
|
|
9
|
-
* @version 1.5.
|
|
9
|
+
* @version 1.5.3
|
|
10
10
|
* @author Yusuke Kamiyamane
|
|
11
11
|
* @license MIT
|
|
12
12
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.js
CHANGED
|
@@ -2631,14 +2631,14 @@ var Menu = class _Menu {
|
|
|
2631
2631
|
#radioItemElementsByGroup = /* @__PURE__ */ new WeakMap();
|
|
2632
2632
|
#arrowElement;
|
|
2633
2633
|
#controller = null;
|
|
2634
|
+
#cleanupPopover = null;
|
|
2635
|
+
#cleanupPortal = null;
|
|
2636
|
+
#cleanupRovingTabIndex = null;
|
|
2634
2637
|
#animation = null;
|
|
2638
|
+
#buttons = [];
|
|
2635
2639
|
#submenus = [];
|
|
2636
2640
|
#submenuTimer;
|
|
2637
2641
|
#isDestroyed = false;
|
|
2638
|
-
#cleanupPortal = null;
|
|
2639
|
-
#cleanupRovingTabIndex = null;
|
|
2640
|
-
#cleanupPopover = null;
|
|
2641
|
-
#buttons = [];
|
|
2642
2642
|
constructor(root, options = {}, _internal = {}) {
|
|
2643
2643
|
if (!(root instanceof HTMLElement)) {
|
|
2644
2644
|
throw new TypeError("Invalid root element");
|
|
@@ -2748,15 +2748,16 @@ var Menu = class _Menu {
|
|
|
2748
2748
|
}
|
|
2749
2749
|
this.#animation?.cancel();
|
|
2750
2750
|
this.#animation = null;
|
|
2751
|
-
|
|
2751
|
+
const trigger = this.#getTrigger();
|
|
2752
2752
|
const elements = this.#itemElements;
|
|
2753
|
-
if (
|
|
2754
|
-
elements.push(
|
|
2753
|
+
if (trigger) {
|
|
2754
|
+
elements.push(trigger);
|
|
2755
2755
|
}
|
|
2756
2756
|
if (this.#listElement) {
|
|
2757
2757
|
elements.push(this.#listElement);
|
|
2758
2758
|
}
|
|
2759
2759
|
restoreAttributes(elements);
|
|
2760
|
+
this.#externalTrigger = null;
|
|
2760
2761
|
this.#triggerElement = null;
|
|
2761
2762
|
this.#listElement = null;
|
|
2762
2763
|
this.#itemElements.length = 0;
|
|
@@ -2782,9 +2783,10 @@ var Menu = class _Menu {
|
|
|
2782
2783
|
return;
|
|
2783
2784
|
}
|
|
2784
2785
|
saveAttributes([this.#listElement], ["aria-labelledby", "id", "role"]);
|
|
2785
|
-
|
|
2786
|
+
const trigger = this.#getTrigger();
|
|
2787
|
+
if (trigger && this.#triggerElement) {
|
|
2786
2788
|
saveAttributes(
|
|
2787
|
-
[
|
|
2789
|
+
[trigger],
|
|
2788
2790
|
[
|
|
2789
2791
|
"aria-controls",
|
|
2790
2792
|
"aria-disabled",
|
|
@@ -2797,18 +2799,14 @@ var Menu = class _Menu {
|
|
|
2797
2799
|
);
|
|
2798
2800
|
const id = Math.random().toString(36).slice(-8);
|
|
2799
2801
|
this.#listElement.id ||= `menu-list-${id}`;
|
|
2800
|
-
addTokenToAttribute(
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
)
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
if (!isFocusable3(this.#triggerElement)) {
|
|
2809
|
-
this.#triggerElement.setAttribute("aria-disabled", "true");
|
|
2810
|
-
this.#triggerElement.setAttribute("tabindex", "-1");
|
|
2811
|
-
this.#triggerElement.style.setProperty("pointer-events", "none");
|
|
2802
|
+
addTokenToAttribute(trigger, "aria-controls", this.#listElement.id);
|
|
2803
|
+
trigger.setAttribute("aria-expanded", "false");
|
|
2804
|
+
trigger.setAttribute("aria-haspopup", "true");
|
|
2805
|
+
trigger.id ||= `menu-trigger-${id}`;
|
|
2806
|
+
if (!isFocusable3(trigger)) {
|
|
2807
|
+
trigger.setAttribute("aria-disabled", "true");
|
|
2808
|
+
trigger.setAttribute("tabindex", "-1");
|
|
2809
|
+
trigger.style.setProperty("pointer-events", "none");
|
|
2812
2810
|
}
|
|
2813
2811
|
this.#triggerElement.addEventListener("click", this.#onTriggerClick, {
|
|
2814
2812
|
signal
|
|
@@ -2816,11 +2814,7 @@ var Menu = class _Menu {
|
|
|
2816
2814
|
this.#triggerElement.addEventListener("keydown", this.#onTriggerKeyDown, {
|
|
2817
2815
|
signal
|
|
2818
2816
|
});
|
|
2819
|
-
addTokenToAttribute(
|
|
2820
|
-
this.#listElement,
|
|
2821
|
-
"aria-labelledby",
|
|
2822
|
-
this.#triggerElement.id
|
|
2823
|
-
);
|
|
2817
|
+
addTokenToAttribute(this.#listElement, "aria-labelledby", trigger.id);
|
|
2824
2818
|
this.#buttons.push(new Button(this.#triggerElement));
|
|
2825
2819
|
}
|
|
2826
2820
|
this.#listElement.setAttribute("role", "menu");
|
|
@@ -2903,7 +2897,7 @@ var Menu = class _Menu {
|
|
|
2903
2897
|
#onTriggerClick = (event) => {
|
|
2904
2898
|
event.preventDefault();
|
|
2905
2899
|
this.#toggle(
|
|
2906
|
-
this.#isSubmenu ? event.currentTarget === this.#triggerElement : this.#
|
|
2900
|
+
this.#isSubmenu ? event.currentTarget === this.#triggerElement : this.#getTrigger()?.ariaExpanded !== "true"
|
|
2907
2901
|
);
|
|
2908
2902
|
};
|
|
2909
2903
|
#onTriggerKeyDown = (event) => {
|
|
@@ -2997,10 +2991,11 @@ var Menu = class _Menu {
|
|
|
2997
2991
|
});
|
|
2998
2992
|
};
|
|
2999
2993
|
#toggle(isOpen, options = {}) {
|
|
3000
|
-
|
|
2994
|
+
const trigger = this.#getTrigger();
|
|
2995
|
+
if (trigger?.ariaExpanded === String(isOpen)) {
|
|
3001
2996
|
return;
|
|
3002
2997
|
}
|
|
3003
|
-
|
|
2998
|
+
trigger?.setAttribute("aria-expanded", String(isOpen));
|
|
3004
2999
|
if (isOpen) {
|
|
3005
3000
|
_Menu.#menus.filter((m) => !m.#containsRoot(this.#rootElement)).forEach((menu) => {
|
|
3006
3001
|
menu.close();
|
|
@@ -3090,7 +3085,7 @@ var Menu = class _Menu {
|
|
|
3090
3085
|
#closeAndMoveFocus(direction) {
|
|
3091
3086
|
this.close();
|
|
3092
3087
|
requestAnimationFrame(
|
|
3093
|
-
() =>
|
|
3088
|
+
() => this.#getTrigger()?.dispatchEvent(
|
|
3094
3089
|
new KeyboardEvent("keydown", {
|
|
3095
3090
|
key: direction === "previous" ? "ArrowLeft" : "ArrowRight"
|
|
3096
3091
|
})
|
|
@@ -3105,7 +3100,10 @@ var Menu = class _Menu {
|
|
|
3105
3100
|
if (!(active instanceof HTMLElement)) {
|
|
3106
3101
|
return;
|
|
3107
3102
|
}
|
|
3108
|
-
this.#containsRoot(active) &&
|
|
3103
|
+
this.#containsRoot(active) && this.#getTrigger()?.focus();
|
|
3104
|
+
}
|
|
3105
|
+
#getTrigger() {
|
|
3106
|
+
return this.#externalTrigger ?? this.#triggerElement;
|
|
3109
3107
|
}
|
|
3110
3108
|
#includesRoot(event) {
|
|
3111
3109
|
const path = event.composedPath();
|
|
@@ -3261,7 +3259,7 @@ function isFocusable3(element) {
|
|
|
3261
3259
|
* WAI-ARIA compliant menu (menu button) pattern implementation in TypeScript.
|
|
3262
3260
|
* Supports checkbox item, radio item, and infinitely nested menus.
|
|
3263
3261
|
*
|
|
3264
|
-
* @version 1.5.
|
|
3262
|
+
* @version 1.5.3
|
|
3265
3263
|
* @author Yusuke Kamiyamane
|
|
3266
3264
|
* @license MIT
|
|
3267
3265
|
* @copyright Copyright (c) Yusuke Kamiyamane
|