@y14e/menu 1.4.1 → 1.4.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 CHANGED
@@ -10,14 +10,14 @@ npm i @y14e/menu
10
10
 
11
11
  ```ts
12
12
  // npm
13
- import Menu from '@y14e/menu@1.4.1';
13
+ import Menu from '@y14e/menu@1.4.3';
14
14
 
15
15
  // CDNs
16
- import Menu from 'https://esm.sh/@y14e/menu@1.4.1';
16
+ import Menu from 'https://esm.sh/@y14e/menu@1.4.3';
17
17
  // or
18
- import Menu from 'https://cdn.jsdelivr.net/npm/@y14e/menu@1.4.1/+esm';
18
+ import Menu from 'https://cdn.jsdelivr.net/npm/@y14e/menu@1.4.3/+esm';
19
19
  // or
20
- import Menu from 'https://esm.unpkg.com/@y14e/menu@1.4.1';
20
+ import Menu from 'https://esm.unpkg.com/@y14e/menu@1.4.3';
21
21
  ```
22
22
 
23
23
  ## Usage
package/dist/index.cjs CHANGED
@@ -2659,8 +2659,8 @@ var Menu = class _Menu {
2659
2659
  }
2660
2660
  this.#initialize();
2661
2661
  }
2662
- open() {
2663
- this.#toggle(true);
2662
+ open(focusLastItem = false) {
2663
+ this.#toggle(true, focusLastItem);
2664
2664
  }
2665
2665
  close() {
2666
2666
  this.#toggle(false);
@@ -2719,7 +2719,7 @@ var Menu = class _Menu {
2719
2719
  signal
2720
2720
  });
2721
2721
  if (!this.#listElement) {
2722
- throw new Error("Unreachable");
2722
+ return;
2723
2723
  }
2724
2724
  saveAttributes([this.#listElement], ["aria-labelledby", "id", "role"]);
2725
2725
  if (this.#triggerElement) {
@@ -2745,12 +2745,9 @@ var Menu = class _Menu {
2745
2745
  this.#triggerElement.setAttribute("aria-expanded", "false");
2746
2746
  this.#triggerElement.setAttribute("aria-haspopup", "true");
2747
2747
  this.#triggerElement.id ||= `menu-trigger-${id}`;
2748
- this.#triggerElement.setAttribute(
2749
- "tabindex",
2750
- isFocusable3(this.#triggerElement) && !this.#isSubmenu ? "0" : "-1"
2751
- );
2752
2748
  if (!isFocusable3(this.#triggerElement)) {
2753
2749
  this.#triggerElement.setAttribute("aria-disabled", "true");
2750
+ this.#triggerElement.setAttribute("tabindex", "-1");
2754
2751
  this.#triggerElement.style.setProperty("pointer-events", "none");
2755
2752
  }
2756
2753
  this.#triggerElement.addEventListener("click", this.#onTriggerClick, {
@@ -2949,7 +2946,7 @@ var Menu = class _Menu {
2949
2946
  i.setAttribute("aria-checked", String(i === item));
2950
2947
  });
2951
2948
  };
2952
- #toggle(isOpen) {
2949
+ #toggle(isOpen, isFocusLastItem = false) {
2953
2950
  if (this.#triggerElement?.ariaExpanded === String(isOpen)) {
2954
2951
  return;
2955
2952
  }
@@ -2959,7 +2956,7 @@ var Menu = class _Menu {
2959
2956
  menu.close();
2960
2957
  });
2961
2958
  if (!this.#listElement) {
2962
- throw new Error("Unreachable");
2959
+ return;
2963
2960
  }
2964
2961
  if (!this.#isSubmenu && this.#triggerElement || !this.#isPortal) {
2965
2962
  const style2 = this.#listElement.style;
@@ -2974,7 +2971,7 @@ var Menu = class _Menu {
2974
2971
  style.setProperty("display", "block");
2975
2972
  style.setProperty("opacity", "0");
2976
2973
  this.#triggerElement && this.#updatePopover();
2977
- this.#itemElements.find(isFocusable3)?.focus();
2974
+ this.#itemElements.filter(isFocusable3).at(isFocusLastItem ? -1 : 0)?.focus();
2978
2975
  } else {
2979
2976
  this.#clearSubmenuTimer();
2980
2977
  const active = getActiveElement4();
@@ -2987,7 +2984,7 @@ var Menu = class _Menu {
2987
2984
  return;
2988
2985
  }
2989
2986
  if (!this.#listElement) {
2990
- throw new Error("Unreachable");
2987
+ return;
2991
2988
  }
2992
2989
  if (!isOpen) {
2993
2990
  this.#listElement.removeAttribute("data-menu-open");
@@ -3015,7 +3012,7 @@ var Menu = class _Menu {
3015
3012
  () => {
3016
3013
  cleanupAnimation();
3017
3014
  if (!this.#listElement) {
3018
- throw new Error("Unreachable");
3015
+ return;
3019
3016
  }
3020
3017
  const { style } = this.#listElement;
3021
3018
  if (!isOpen) {
@@ -3118,7 +3115,7 @@ var Menu = class _Menu {
3118
3115
  middlewareData
3119
3116
  }) => {
3120
3117
  if (!this.#listElement) {
3121
- throw new Error("Unreachable");
3118
+ return;
3122
3119
  }
3123
3120
  const { style: listStyle } = this.#listElement;
3124
3121
  listStyle.setProperty("left", `${listX}px`);
@@ -3200,7 +3197,7 @@ function isFocusable3(element) {
3200
3197
  * WAI-ARIA compliant menu (menu button) pattern implementation in TypeScript.
3201
3198
  * Supports checkbox item, radio item, and infinitely nested menus.
3202
3199
  *
3203
- * @version 1.4.0
3200
+ * @version 1.4.3
3204
3201
  * @author Yusuke Kamiyamane
3205
3202
  * @license MIT
3206
3203
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.d.cts CHANGED
@@ -5,7 +5,7 @@ import { Middleware, Placement } from '@floating-ui/dom';
5
5
  * WAI-ARIA compliant menu (menu button) pattern implementation in TypeScript.
6
6
  * Supports checkbox item, radio item, and infinitely nested menus.
7
7
  *
8
- * @version 1.4.0
8
+ * @version 1.4.3
9
9
  * @author Yusuke Kamiyamane
10
10
  * @license MIT
11
11
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -48,7 +48,7 @@ declare class Menu {
48
48
  * @internal Internal constructor
49
49
  */
50
50
  constructor(root: HTMLElement, options?: MenuOptions, _internal?: InternalOptions);
51
- open(): void;
51
+ open(focusLastItem?: boolean): void;
52
52
  close(): void;
53
53
  destroy(force?: boolean): Promise<void>;
54
54
  }
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@ import { Middleware, Placement } from '@floating-ui/dom';
5
5
  * WAI-ARIA compliant menu (menu button) pattern implementation in TypeScript.
6
6
  * Supports checkbox item, radio item, and infinitely nested menus.
7
7
  *
8
- * @version 1.4.0
8
+ * @version 1.4.3
9
9
  * @author Yusuke Kamiyamane
10
10
  * @license MIT
11
11
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -48,7 +48,7 @@ declare class Menu {
48
48
  * @internal Internal constructor
49
49
  */
50
50
  constructor(root: HTMLElement, options?: MenuOptions, _internal?: InternalOptions);
51
- open(): void;
51
+ open(focusLastItem?: boolean): void;
52
52
  close(): void;
53
53
  destroy(force?: boolean): Promise<void>;
54
54
  }
package/dist/index.js CHANGED
@@ -2657,8 +2657,8 @@ var Menu = class _Menu {
2657
2657
  }
2658
2658
  this.#initialize();
2659
2659
  }
2660
- open() {
2661
- this.#toggle(true);
2660
+ open(focusLastItem = false) {
2661
+ this.#toggle(true, focusLastItem);
2662
2662
  }
2663
2663
  close() {
2664
2664
  this.#toggle(false);
@@ -2717,7 +2717,7 @@ var Menu = class _Menu {
2717
2717
  signal
2718
2718
  });
2719
2719
  if (!this.#listElement) {
2720
- throw new Error("Unreachable");
2720
+ return;
2721
2721
  }
2722
2722
  saveAttributes([this.#listElement], ["aria-labelledby", "id", "role"]);
2723
2723
  if (this.#triggerElement) {
@@ -2743,12 +2743,9 @@ var Menu = class _Menu {
2743
2743
  this.#triggerElement.setAttribute("aria-expanded", "false");
2744
2744
  this.#triggerElement.setAttribute("aria-haspopup", "true");
2745
2745
  this.#triggerElement.id ||= `menu-trigger-${id}`;
2746
- this.#triggerElement.setAttribute(
2747
- "tabindex",
2748
- isFocusable3(this.#triggerElement) && !this.#isSubmenu ? "0" : "-1"
2749
- );
2750
2746
  if (!isFocusable3(this.#triggerElement)) {
2751
2747
  this.#triggerElement.setAttribute("aria-disabled", "true");
2748
+ this.#triggerElement.setAttribute("tabindex", "-1");
2752
2749
  this.#triggerElement.style.setProperty("pointer-events", "none");
2753
2750
  }
2754
2751
  this.#triggerElement.addEventListener("click", this.#onTriggerClick, {
@@ -2947,7 +2944,7 @@ var Menu = class _Menu {
2947
2944
  i.setAttribute("aria-checked", String(i === item));
2948
2945
  });
2949
2946
  };
2950
- #toggle(isOpen) {
2947
+ #toggle(isOpen, isFocusLastItem = false) {
2951
2948
  if (this.#triggerElement?.ariaExpanded === String(isOpen)) {
2952
2949
  return;
2953
2950
  }
@@ -2957,7 +2954,7 @@ var Menu = class _Menu {
2957
2954
  menu.close();
2958
2955
  });
2959
2956
  if (!this.#listElement) {
2960
- throw new Error("Unreachable");
2957
+ return;
2961
2958
  }
2962
2959
  if (!this.#isSubmenu && this.#triggerElement || !this.#isPortal) {
2963
2960
  const style2 = this.#listElement.style;
@@ -2972,7 +2969,7 @@ var Menu = class _Menu {
2972
2969
  style.setProperty("display", "block");
2973
2970
  style.setProperty("opacity", "0");
2974
2971
  this.#triggerElement && this.#updatePopover();
2975
- this.#itemElements.find(isFocusable3)?.focus();
2972
+ this.#itemElements.filter(isFocusable3).at(isFocusLastItem ? -1 : 0)?.focus();
2976
2973
  } else {
2977
2974
  this.#clearSubmenuTimer();
2978
2975
  const active = getActiveElement4();
@@ -2985,7 +2982,7 @@ var Menu = class _Menu {
2985
2982
  return;
2986
2983
  }
2987
2984
  if (!this.#listElement) {
2988
- throw new Error("Unreachable");
2985
+ return;
2989
2986
  }
2990
2987
  if (!isOpen) {
2991
2988
  this.#listElement.removeAttribute("data-menu-open");
@@ -3013,7 +3010,7 @@ var Menu = class _Menu {
3013
3010
  () => {
3014
3011
  cleanupAnimation();
3015
3012
  if (!this.#listElement) {
3016
- throw new Error("Unreachable");
3013
+ return;
3017
3014
  }
3018
3015
  const { style } = this.#listElement;
3019
3016
  if (!isOpen) {
@@ -3116,7 +3113,7 @@ var Menu = class _Menu {
3116
3113
  middlewareData
3117
3114
  }) => {
3118
3115
  if (!this.#listElement) {
3119
- throw new Error("Unreachable");
3116
+ return;
3120
3117
  }
3121
3118
  const { style: listStyle } = this.#listElement;
3122
3119
  listStyle.setProperty("left", `${listX}px`);
@@ -3198,7 +3195,7 @@ function isFocusable3(element) {
3198
3195
  * WAI-ARIA compliant menu (menu button) pattern implementation in TypeScript.
3199
3196
  * Supports checkbox item, radio item, and infinitely nested menus.
3200
3197
  *
3201
- * @version 1.4.0
3198
+ * @version 1.4.3
3202
3199
  * @author Yusuke Kamiyamane
3203
3200
  * @license MIT
3204
3201
  * @copyright Copyright (c) Yusuke Kamiyamane
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@y14e/menu",
3
- "version": "1.4.1",
3
+ "version": "1.4.3",
4
4
  "description": "WAI-ARIA compliant menu (menu button) pattern implementation in TypeScript",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",