@nysds/nys-dropdownmenu 1.19.4 → 1.20.1

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.
@@ -0,0 +1,2 @@
1
+ export * from "./nys-dropdownmenu";
2
+ export * from "./nys-dropdownmenuitem";
@@ -0,0 +1,126 @@
1
+ import { NysElement } from "@nysds/internals";
2
+ import "./nys-dropdownmenuitem";
3
+ type Position = "bottom-start" | "bottom-end" | "top-start" | "top-end";
4
+ /**
5
+ * Dropdown menus enable users to select an action from a list of options.
6
+ * They’re commonly used to save space by grouping related actions, or to provide actions in a confined space.
7
+ *
8
+ * @summary Action menu with auto-positioning, keyboard support, and screen reader integration.
9
+ * @element nys-dropdownmenu
10
+ *
11
+ * @example Basic
12
+ * ```html
13
+ * <nys-button id="my-trigger-id" label="Open Menu"></nys-button>
14
+ * <nys-dropdownmenu id="my-dropdownmenu" for="my-trigger-id">
15
+ * <nys-dropdownmenuitem label="Profile" href="/profile"></nys-dropdownmenuitem>
16
+ * <nys-dropdownmenuitem label="Repositories & Github Pages" href="/repos"></nys-dropdownmenuitem>
17
+ * <nys-dropdownmenuitem label="Organizations" href="/organizations"></nys-dropdownmenuitem>
18
+ * <nys-dropdownmenuitem label="Sign out" href="/logout"></nys-dropdownmenuitem>
19
+ * </nys-dropdownmenu>
20
+ * </div>
21
+ * ```
22
+ *
23
+ * @render Basic
24
+ * ```html
25
+ * <div style="margin: 200px; display: flex; justify-content: center; align-items: center;">
26
+ * <nys-button id="my-trigger-id" label="Open Menu"></nys-button>
27
+ * <nys-dropdownmenu id="my-dropdownmenu" for="my-trigger-id">
28
+ * <nys-dropdownmenuitem label="Profile" href="/profile"></nys-dropdownmenuitem>
29
+ * <nys-dropdownmenuitem label="Repositories & Github Pages" href="/repos"></nys-dropdownmenuitem>
30
+ * <nys-dropdownmenuitem label="Organizations" href="/organizations"></nys-dropdownmenuitem>
31
+ * <nys-dropdownmenuitem label="Sign out" href="/logout"></nys-dropdownmenuitem>
32
+ * </nys-dropdownmenu>
33
+ * </div>
34
+ * ```
35
+ */
36
+ export declare class NysDropdownMenu extends NysElement {
37
+ static styles: import("lit").CSSResult;
38
+ for: string;
39
+ showDropdown: boolean;
40
+ /**
41
+ * Accessible label for the menu (`role="menu"`) container. Used as `aria-label`
42
+ * on the `<ul role="menu">` element. When empty, falls back to "Menu" so the
43
+ * menu always has an accessible name for screen readers.
44
+ * @default ""
45
+ */
46
+ label: string;
47
+ /**
48
+ * Preferred position relative to trigger.
49
+ * @default "bottom-end"
50
+ */
51
+ position: Position | null;
52
+ private _trigger;
53
+ private _menuElement;
54
+ private _ariaTarget;
55
+ private _lastFocusedIndex;
56
+ private readonly GAP;
57
+ private _resizeObserver;
58
+ /**
59
+ * Lifecycle Methods
60
+ * --------------------------------------------------------------------------
61
+ */
62
+ constructor();
63
+ connectedCallback(): void;
64
+ disconnectedCallback(): void;
65
+ firstUpdated(): Promise<void>;
66
+ /**
67
+ * Functions
68
+ * --------------------------------------------------------------------------
69
+ */
70
+ private _findTrigger;
71
+ private _connectTrigger;
72
+ private _toggleDropdown;
73
+ private _closeDropdown;
74
+ private _getMenuItems;
75
+ private _handleDocumentClick;
76
+ private _focusOnItem;
77
+ private applyInverseTransform;
78
+ /**
79
+ * Position Logic
80
+ * --------------------------------------------------------------------------
81
+ */
82
+ /**
83
+ * The controller function for positioning the dropdown menu.
84
+ * The logic diverts to if user sets position or we auto position the dropdown menu
85
+ */
86
+ private _positionMenu;
87
+ private _setUserPosition;
88
+ /**
89
+ * Auto Positioning of the dropdown menu relies on the best surrounding space available
90
+ * to select the desirable position.
91
+ */
92
+ private _autoPosition;
93
+ /**
94
+ * Checks if the dropdown menu fits inside the viewport on the given side of the trigger.
95
+ * Overrides user set position for auto-positioning if user's desire space is not available
96
+ */
97
+ private _checkSpaceAvailable;
98
+ private _checkPositionFits;
99
+ /**
100
+ * This position is called for when user's set position didn't fit OR auto positioning when default position doesn't fit
101
+ * We look for the best alternative positions in order of preference base on the set position (e.g. bottom-start => bottom-end).
102
+ * @param userPosition
103
+ * @param space
104
+ * @param menuRect
105
+ */
106
+ private _findBestAlternative;
107
+ private _findMostAvailableSpace;
108
+ /**
109
+ * A valid ideal position has been chosen.
110
+ * This function calculates the coordinate of the trigger to properly position the dropdown menu.
111
+ * @param position
112
+ * @returns
113
+ */
114
+ private _calculateCoordinates;
115
+ private _applyPosition;
116
+ /**
117
+ * Event Handlers
118
+ * --------------------------------------------------------------------------
119
+ */
120
+ private _handleMenuClick;
121
+ private _handleTriggerKeydown;
122
+ private _handleMenuKeydown;
123
+ private _handleWindowScroll;
124
+ render(): import("lit-html").TemplateResult<1>;
125
+ }
126
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -1,29 +1,55 @@
1
- import { LitElement as f, unsafeCSS as _, html as u } from "lit";
1
+ import { LitElement as y, unsafeCSS as b, html as u } from "lit";
2
2
  import { property as d } from "lit/decorators.js";
3
+ import "@nysds/nys-icon";
3
4
  /*!
4
5
  * █▄ █ █ █ █▀▀▀█ █▀▀▄ █▀▀▀█
5
6
  * █ █ █ █▄▄▄█ ▀▀▀▄▄ █ █ ▀▀▀▄▄
6
7
  * █ ▀█ █ █▄▄▄█ █▄▄▀ █▄▄▄█
7
8
  *
8
- * Dropdownmenu Component v1.19.4
9
+ * Dropdownmenu Component v1.20.1
9
10
  * Part of the New York State Design System
10
11
  * Repository: https://github.com/its-hcd/nysds
11
12
  * License: MIT
12
13
  */
13
- const g = ':host{--_nys-dropdownmenu-width: 180px;--_nys-dropdownmenu-height: 100%;--_nys-dropdownmenu-radius: var(--nys-radius-md, 4px);--_nys-dropdownmenu-border-width: var(--nys-border-width-sm, 1px);--_nys-dropdownmenu-border-color: var(--nys-color-neutral-100, #d0d0ce);--_nys-dropdownmenu-background-color: var(--nys-color-ink-reverse, #ffffff);--_nys-dropdownmenu-boxshadow-color-100: var( --nys-color-black-transparent-100, rgba(27, 27, 27, .1) );--_nys-dropdownmenu-boxshadow-color-50: var( --nys-color-black-transparent-50, rgba(27, 27, 27, .01) );--_nys-dropdownmenu-gap: var(--nys-space-2px, 2px);--_nys-dropdownmenu-padding: var(--nys-space-100, 8px);--_nys-dropdownmenu-font-size: var(--nys-font-size-ui-md, 16px);--_nys-dropdownmenu-font-weight: var(font-weight: 400);--_nys-dropdownmenu-line-height: var(--nys-font-lineheight-ui-md, 24px);--_nys-dropdownmenu-font-family: var( --nys-font-family-ui, var( --nys-font-family-sans, "Proxima Nova", "Helvetica Neue", "Helvetica", "Arial", sans-serif ) );--_nys-dropdownmenuitem-color: var(--nys-color-text, #1b1b1b);--_nys-dropdownmenuitem-gap: var(--nys-space-100, 8px);--_nys-dropdownmenuitem-padding: var(--nys-space-200, 16px) var(--nys-space-100, 8px);--_nys-dropdownmenuitem-border-radius: var(--nys-radius-md, 4px);--_nys-dropdownmenuitem-background-color: var(--nys-color-white, #ffffff);--_nys-dropdownmenuitem-background-color--hover: var( --nys-color-neutral-10, #f6f6f6 );--_nys-dropdownmenuitem-background-color--active: var( --nys-color-neutral-50, #ededed );--_nys-dropdownmenuitem-color--disabled: var( --nys-color-text-disabled, #bec0c1 );--_nys-dropdownmenuitem-outline-width: var(--nys-border-width-md, 2px);--_nys-dropdownmenuitem-outline-color: var(--nys-color-focus, #004dd1)}.nys-dropdownmenu{position:fixed;top:0;left:0;z-index:1776}.nys-dropdownmenu.active ul{display:flex}.nys-dropdownmenu ul{display:none;align-items:flex-start;flex-direction:column;gap:var(--_nys-dropdownmenu-gap);width:var(--_nys-dropdownmenu-width);height:var(--_nys-dropdownmenu-height);border-radius:var(--_nys-dropdownmenu-radius);border:var(--_nys-dropdownmenu-border-width) solid var(--_nys-dropdownmenu-border-color);background-color:var(--_nys-dropdownmenu-background-color);box-shadow:0 4px 6px -1px var(--_nys-dropdownmenu-boxshadow-color-100),0 4px 6px -1px var(--_nys-dropdownmenu-boxshadow-color-50);padding:var(--_nys-dropdownmenu-padding);font-family:var(--_nys-dropdownmenu-font-family);font-size:var(--_nys-dropdownmenu-font-size);font-weight:var(--_nys-dropdownmenu-font-weight);line-height:var(--_nys-dropdownmenu-line-height);overflow:hidden;margin:0}.nys-dropdownmenuitem{list-style:none;width:var(--_nys-dropdownmenu-width);padding:0;margin:0}.nys-dropdownmenuitem a,.nys-dropdownmenuitem button{display:flex;gap:var(--_nys-dropdownmenuitem-gap);padding:var(--_nys-dropdownmenuitem-padding);border-radius:var(--_nys-dropdownmenuitem-border-radius);background-color:var(--_nys-dropdownmenuitem-background-color);width:100%;box-sizing:border-box;text-decoration:none;text-wrap:wrap;color:var(--_nys-dropdownmenuitem-color);transition:.05s ease-in-out all;border:none;font-family:var(--_nys-dropdownmenu-font-family);font-size:var(--_nys-dropdownmenu-font-size);font-weight:var(--_nys-dropdownmenu-font-weight);line-height:var(--_nys-dropdownmenu-line-height);cursor:pointer}.nys-dropdownmenuitem a nys-icon,.nys-dropdownmenuitem button nys-icon{margin-top:2.5px}.nys-dropdownmenuitem a:hover:not(.disabled):not([aria-disabled=true]),.nys-dropdownmenuitem button:hover:not(.disabled):not([aria-disabled=true]){background-color:var(--_nys-dropdownmenuitem-background-color--hover)}.nys-dropdownmenuitem a:active:not(.disabled):not([aria-disabled=true]),.nys-dropdownmenuitem button:active:not(.disabled):not([aria-disabled=true]){background-color:var(--_nys-dropdownmenuitem-background-color--active)}.nys-dropdownmenuitem a:focus-visible:not(.disabled):not([aria-disabled=true]):not([focus-ring-false]),.nys-dropdownmenuitem button:focus-visible:not(.disabled):not([aria-disabled=true]):not([focus-ring-false]){position:relative;outline:var(--_nys-dropdownmenuitem-outline-width) solid var(--_nys-dropdownmenuitem-outline-color)}.nys-dropdownmenuitem a.disabled,.nys-dropdownmenuitem a[aria-disabled=true],.nys-dropdownmenuitem button.disabled,.nys-dropdownmenuitem button[aria-disabled=true]{color:var(--_nys-dropdownmenuitem-color--disabled);pointer-events:none;cursor:default}';
14
- var v = Object.defineProperty, c = (h, e, t, n) => {
15
- for (var o = void 0, i = h.length - 1, s; i >= 0; i--)
16
- (s = h[i]) && (o = s(e, t, o) || o);
17
- return o && v(e, t, o), o;
18
- };
14
+ /*!
15
+ * New York State Design System v1.20.1
16
+ * Description: A design system for New York State's digital products.
17
+ * Repository: https://github.com/its-hcd/nysds
18
+ * License: MIT
19
+ */
19
20
  let x = 0;
20
- const m = class m extends f {
21
+ function k(a) {
22
+ return `${a}-${Date.now()}-${x++}`;
23
+ }
24
+ const E = (a) => {
25
+ class e extends a {
26
+ get idPrefix() {
27
+ return this.localName || "nys-element";
28
+ }
29
+ ensureId() {
30
+ this.id || (this.id = k(this.idPrefix));
31
+ }
32
+ connectedCallback() {
33
+ super.connectedCallback(), this.ensureId();
34
+ }
35
+ }
36
+ return e;
37
+ }, _ = /* @__PURE__ */ E(y), g = ':host{--_nys-dropdownmenu-width: 180px;--_nys-dropdownmenu-height: 100%;--_nys-dropdownmenu-radius: var(--nys-radius-md, 4px);--_nys-dropdownmenu-border-width: var(--nys-border-width-sm, 1px);--_nys-dropdownmenu-border-color: var(--nys-color-neutral-100, #d0d0ce);--_nys-dropdownmenu-background-color: var(--nys-color-ink-reverse, #ffffff);--_nys-dropdownmenu-boxshadow-color-100: var( --nys-color-black-transparent-100, rgba(27, 27, 27, .1) );--_nys-dropdownmenu-boxshadow-color-50: var( --nys-color-black-transparent-50, rgba(27, 27, 27, .01) );--_nys-dropdownmenu-gap: var(--nys-space-2px, 2px);--_nys-dropdownmenu-padding: var(--nys-space-100, 8px);--_nys-dropdownmenu-font-size: var(--nys-font-size-ui-md, 16px);--_nys-dropdownmenu-font-weight: var(font-weight: 400);--_nys-dropdownmenu-line-height: var(--nys-font-lineheight-ui-md, 24px);--_nys-dropdownmenu-font-family: var( --nys-font-family-ui, var( --nys-font-family-sans, "Proxima Nova", "Helvetica Neue", "Helvetica", "Arial", sans-serif ) );--_nys-dropdownmenuitem-color: var(--nys-color-text, #1b1b1b);--_nys-dropdownmenuitem-gap: var(--nys-space-100, 8px);--_nys-dropdownmenuitem-padding: var(--nys-space-200, 16px) var(--nys-space-100, 8px);--_nys-dropdownmenuitem-border-radius: var(--nys-radius-md, 4px);--_nys-dropdownmenuitem-background-color: var(--nys-color-white, #ffffff);--_nys-dropdownmenuitem-background-color--hover: var( --nys-color-neutral-10, #f6f6f6 );--_nys-dropdownmenuitem-background-color--active: var( --nys-color-neutral-50, #ededed );--_nys-dropdownmenuitem-color--disabled: var( --nys-color-text-disabled, #bec0c1 );--_nys-dropdownmenuitem-outline-width: var(--nys-border-width-md, 2px);--_nys-dropdownmenuitem-outline-color: var(--nys-color-focus, #004dd1)}.nys-dropdownmenu{position:fixed;top:0;left:0;z-index:1776}.nys-dropdownmenu.active ul{display:flex}.nys-dropdownmenu ul{display:none;align-items:flex-start;flex-direction:column;gap:var(--_nys-dropdownmenu-gap);width:var(--_nys-dropdownmenu-width);height:var(--_nys-dropdownmenu-height);border-radius:var(--_nys-dropdownmenu-radius);border:var(--_nys-dropdownmenu-border-width) solid var(--_nys-dropdownmenu-border-color);background-color:var(--_nys-dropdownmenu-background-color);box-shadow:0 4px 6px -1px var(--_nys-dropdownmenu-boxshadow-color-100),0 4px 6px -1px var(--_nys-dropdownmenu-boxshadow-color-50);padding:var(--_nys-dropdownmenu-padding);font-family:var(--_nys-dropdownmenu-font-family);font-size:var(--_nys-dropdownmenu-font-size);font-weight:var(--_nys-dropdownmenu-font-weight);line-height:var(--_nys-dropdownmenu-line-height);overflow:hidden;margin:0}.nys-dropdownmenuitem{list-style:none;width:var(--_nys-dropdownmenu-width);padding:0;margin:0}.nys-dropdownmenuitem a,.nys-dropdownmenuitem button{display:flex;gap:var(--_nys-dropdownmenuitem-gap);padding:var(--_nys-dropdownmenuitem-padding);border-radius:var(--_nys-dropdownmenuitem-border-radius);background-color:var(--_nys-dropdownmenuitem-background-color);width:100%;box-sizing:border-box;text-decoration:none;text-wrap:wrap;color:var(--_nys-dropdownmenuitem-color);transition:.05s ease-in-out all;border:none;font-family:var(--_nys-dropdownmenu-font-family);font-size:var(--_nys-dropdownmenu-font-size);font-weight:var(--_nys-dropdownmenu-font-weight);line-height:var(--_nys-dropdownmenu-line-height);cursor:pointer}.nys-dropdownmenuitem a nys-icon,.nys-dropdownmenuitem button nys-icon{margin-top:2.5px}.nys-dropdownmenuitem a:hover:not(.disabled):not([aria-disabled=true]),.nys-dropdownmenuitem button:hover:not(.disabled):not([aria-disabled=true]){background-color:var(--_nys-dropdownmenuitem-background-color--hover)}.nys-dropdownmenuitem a:active:not(.disabled):not([aria-disabled=true]),.nys-dropdownmenuitem button:active:not(.disabled):not([aria-disabled=true]){background-color:var(--_nys-dropdownmenuitem-background-color--active)}.nys-dropdownmenuitem a:focus-visible:not(.disabled):not([aria-disabled=true]):not([focus-ring-false]),.nys-dropdownmenuitem button:focus-visible:not(.disabled):not([aria-disabled=true]):not([focus-ring-false]){position:relative;outline:var(--_nys-dropdownmenuitem-outline-width) solid var(--_nys-dropdownmenuitem-outline-color)}.nys-dropdownmenuitem a.disabled,.nys-dropdownmenuitem a[aria-disabled=true],.nys-dropdownmenuitem button.disabled,.nys-dropdownmenuitem button[aria-disabled=true]{color:var(--_nys-dropdownmenuitem-color--disabled);pointer-events:none;cursor:default}';
38
+ var $ = Object.defineProperty, h = (a, e, t, n) => {
39
+ for (var o = void 0, i = a.length - 1, s; i >= 0; i--)
40
+ (s = a[i]) && (o = s(e, t, o) || o);
41
+ return o && $(e, t, o), o;
42
+ };
43
+ const m = class m extends _ {
21
44
  constructor() {
22
45
  super(...arguments), this.label = "", this.href = "", this.disabled = !1, this.target = "_self", this.prefixIcon = "", this.divider = "";
23
46
  }
24
- // Generate a unique ID if one is not provided
47
+ // super.connectedCallback() (NysElement) auto-assigns this.id when
48
+ // one is not provided (prefix = localName, i.e. "nys-dropdownmenuitem-<ts>-<n>").
49
+ // role="menuitem" intentionally stays on the inner <a>/<button>, so this
50
+ // component keeps defaultRole = null and does not move a role onto the host.
25
51
  connectedCallback() {
26
- super.connectedCallback(), this.id || (this.id = `nys-dropdownmenuitem-${Date.now()}-${x++}`);
52
+ super.connectedCallback();
27
53
  }
28
54
  _handleClick(e) {
29
55
  if (this.disabled) {
@@ -75,37 +101,36 @@ const m = class m extends f {
75
101
  </li>`;
76
102
  }
77
103
  };
78
- m.styles = _(g), m.shadowRootOptions = {
79
- ...f.shadowRootOptions,
104
+ m.styles = b(g), m.shadowRootOptions = {
105
+ ...y.shadowRootOptions,
80
106
  delegatesFocus: !0
81
107
  };
82
- let a = m;
83
- c([
108
+ let l = m;
109
+ h([
84
110
  d({ type: String })
85
- ], a.prototype, "label");
86
- c([
111
+ ], l.prototype, "label");
112
+ h([
87
113
  d({ type: String })
88
- ], a.prototype, "href");
89
- c([
114
+ ], l.prototype, "href");
115
+ h([
90
116
  d({ type: Boolean, reflect: !0 })
91
- ], a.prototype, "disabled");
92
- c([
117
+ ], l.prototype, "disabled");
118
+ h([
93
119
  d({ type: String })
94
- ], a.prototype, "target");
95
- c([
120
+ ], l.prototype, "target");
121
+ h([
96
122
  d({ type: String })
97
- ], a.prototype, "prefixIcon");
98
- c([
123
+ ], l.prototype, "prefixIcon");
124
+ h([
99
125
  d({ type: String })
100
- ], a.prototype, "divider");
101
- customElements.get("nys-dropdownmenuitem") || customElements.define("nys-dropdownmenuitem", a);
102
- var k = Object.defineProperty, w = (h, e, t, n) => {
103
- for (var o = void 0, i = h.length - 1, s; i >= 0; i--)
104
- (s = h[i]) && (o = s(e, t, o) || o);
105
- return o && k(e, t, o), o;
126
+ ], l.prototype, "divider");
127
+ customElements.get("nys-dropdownmenuitem") || customElements.define("nys-dropdownmenuitem", l);
128
+ var C = Object.defineProperty, f = (a, e, t, n) => {
129
+ for (var o = void 0, i = a.length - 1, s; i >= 0; i--)
130
+ (s = a[i]) && (o = s(e, t, o) || o);
131
+ return o && C(e, t, o), o;
106
132
  };
107
- let E = 0;
108
- const y = class y extends f {
133
+ const w = class w extends _ {
109
134
  /**
110
135
  * Lifecycle Methods
111
136
  * --------------------------------------------------------------------------
@@ -125,7 +150,7 @@ const y = class y extends f {
125
150
  const t = e?.composedPath(), n = t.includes(this), o = this._trigger && t.includes(this._trigger);
126
151
  !n && !o && this._closeDropdown();
127
152
  }, this._handleTriggerKeydown = (e) => {
128
- (e.key === "Enter" || e.key === " ") && (e.preventDefault(), this._toggleDropdown()), e.key === "Escape" && this.showDropdown && (e.preventDefault(), this._closeDropdown());
153
+ e.defaultPrevented || e.key === "Escape" && this.showDropdown && (e.preventDefault(), this._closeDropdown());
129
154
  }, this._handleMenuKeydown = (e) => {
130
155
  const t = this._getMenuItems(), n = t.indexOf(document.activeElement);
131
156
  switch (e.key) {
@@ -152,9 +177,12 @@ const y = class y extends f {
152
177
  this.showDropdown && this._positionMenu();
153
178
  };
154
179
  }
155
- // Generate a unique ID if one is not provided
180
+ // super.connectedCallback() (NysElement) auto-assigns this.id when
181
+ // one is not provided (prefix = localName, i.e. "nys-dropdownmenu-<ts>-<n>").
182
+ // The menu/menuitem roles intentionally stay on the inner <ul>/items, so this
183
+ // component keeps defaultRole = null and does not move a role onto the host.
156
184
  connectedCallback() {
157
- super.connectedCallback(), this.id || (this.id = `nys-dropdownmenu-${Date.now()}-${E++}`);
185
+ super.connectedCallback();
158
186
  }
159
187
  disconnectedCallback() {
160
188
  super.disconnectedCallback();
@@ -259,8 +287,8 @@ const y = class y extends f {
259
287
  };
260
288
  }
261
289
  _checkPositionFits(e, t, n) {
262
- const o = n.width, i = n.height, [s, r] = e.split("-"), p = s === "bottom" ? t.bottom >= i + this.GAP : t.top >= i + this.GAP, b = r === "start" ? t.end >= o : t.start >= o;
263
- return p && b;
290
+ const o = n.width, i = n.height, [s, r] = e.split("-"), p = s === "bottom" ? t.bottom >= i + this.GAP : t.top >= i + this.GAP, v = r === "start" ? t.end >= o : t.start >= o;
291
+ return p && v;
264
292
  }
265
293
  /**
266
294
  * This position is called for when user's set position didn't fit OR auto positioning when default position doesn't fit
@@ -325,23 +353,23 @@ const y = class y extends f {
325
353
  </div>`;
326
354
  }
327
355
  };
328
- y.styles = _(g);
329
- let l = y;
330
- w([
356
+ w.styles = b(g);
357
+ let c = w;
358
+ f([
331
359
  d({ type: String, reflect: !0 })
332
- ], l.prototype, "for");
333
- w([
360
+ ], c.prototype, "for");
361
+ f([
334
362
  d({ type: Boolean })
335
- ], l.prototype, "showDropdown");
336
- w([
363
+ ], c.prototype, "showDropdown");
364
+ f([
337
365
  d({ type: String })
338
- ], l.prototype, "label");
339
- w([
366
+ ], c.prototype, "label");
367
+ f([
340
368
  d({ type: String, reflect: !0 })
341
- ], l.prototype, "position");
342
- customElements.get("nys-dropdownmenu") || customElements.define("nys-dropdownmenu", l);
369
+ ], c.prototype, "position");
370
+ customElements.get("nys-dropdownmenu") || customElements.define("nys-dropdownmenu", c);
343
371
  export {
344
- l as NysDropdownMenu,
345
- a as NysDropdownMenuItem
372
+ c as NysDropdownMenu,
373
+ l as NysDropdownMenuItem
346
374
  };
347
375
  //# sourceMappingURL=nys-dropdownmenu.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"nys-dropdownmenu.js","sources":["../src/nys-dropdownmenuitem.ts","../src/nys-dropdownmenu.ts"],"sourcesContent":["import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property } from \"lit/decorators.js\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-dropdownmenu.scss?inline\";\n\nlet dropdownMenuItemIdCounter = 0;\n\n/**\n * **Slotted component.** Displays an individual dropdown item within `nys-dropdown` with label.\n *\n * The `nys-dropdownitem` is used as customizable item within the dropdown so users don't have to raw code <ul>, <li>, <a href>\n * and have the benefit of default customization.\n *\n * @summary Dropdown item to display label and provide href link.\n * @element nys-dropdownmenuitem\n */\n\nexport class NysDropdownMenuItem extends LitElement {\n static styles = unsafeCSS(styles);\n static shadowRootOptions = {\n ...LitElement.shadowRootOptions,\n delegatesFocus: true,\n };\n\n @property({ type: String }) label = \"\";\n @property({ type: String }) href = \"\";\n @property({ type: Boolean, reflect: true }) disabled = false;\n @property({ type: String }) target = \"_self\";\n @property({ type: String }) prefixIcon = \"\";\n @property({ type: String }) divider = \"\";\n\n // Generate a unique ID if one is not provided\n connectedCallback() {\n super.connectedCallback();\n if (!this.id) {\n this.id = `nys-dropdownmenuitem-${Date.now()}-${dropdownMenuItemIdCounter++}`;\n }\n }\n\n private _handleClick(e: Event) {\n if (this.disabled) {\n e.preventDefault();\n return;\n }\n\n this.dispatchEvent(\n new CustomEvent(\"nys-click\", {\n bubbles: true,\n composed: true,\n detail: {\n id: this.id,\n label: this.label,\n ...(this.href && { href: this.href }),\n },\n }),\n );\n }\n\n render() {\n const isLink = !!this.href;\n\n return html`<li class=\"nys-dropdownmenuitem\" role=\"presentation\">\n ${isLink\n ? html` <a\n class=${this.disabled ? \"disabled\" : \"\"}\n href=${this.disabled ? \"\" : this.href}\n role=\"menuitem\"\n aria-disabled=\"${this.disabled ? \"true\" : \"false\"}\"\n aria-label=${this.label}\n tabindex=${this.disabled ? \"-1\" : \"0\"}\n @click=\"${this._handleClick}\"\n target=\"${this.target}\"\n >\n ${this.prefixIcon\n ? html`<nys-icon size=\"16\" name=${this.prefixIcon}></nys-icon>`\n : \"\"}\n ${this.label}</a\n >`\n : html`\n <button\n class=${this.disabled ? \"disabled\" : \"\"}\n type=\"button\"\n role=\"menuitem\"\n aria-disabled=\"${this.disabled ? \"true\" : \"false\"}\"\n aria-label=${this.label}\n tabindex=${this.disabled ? \"-1\" : \"0\"}\n ?disabled=${this.disabled}\n @click=\"${this._handleClick}\"\n >\n ${this.prefixIcon\n ? html`<nys-icon size=\"16\" name=${this.prefixIcon}></nys-icon>`\n : \"\"}\n ${this.label}\n </button>\n `}\n </li>`;\n }\n}\n\nif (!customElements.get(\"nys-dropdownmenuitem\")) {\n customElements.define(\"nys-dropdownmenuitem\", NysDropdownMenuItem);\n}\n","import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property } from \"lit/decorators.js\";\nimport \"./nys-dropdownmenuitem\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-dropdownmenu.scss?inline\";\n\nlet dropdownMenuIdCounter = 0;\n\ntype Position = \"bottom-start\" | \"bottom-end\" | \"top-start\" | \"top-end\";\n\ninterface PositionCoordinates {\n top: number;\n left: number;\n}\n\ninterface SpaceAvailable {\n top: number;\n bottom: number;\n start: number;\n end: number;\n}\n\n/**\n * Dropdown menus enable users to select an action from a list of options.\n * They’re commonly used to save space by grouping related actions, or to provide actions in a confined space.\n *\n * @summary Action menu with auto-positioning, keyboard support, and screen reader integration.\n * @element nys-dropdownmenu\n *\n * @example Basic\n * ```html\n * <nys-button id=\"my-trigger-id\" label=\"Open Menu\"></nys-button>\n * <nys-dropdownmenu id=\"my-dropdownmenu\" for=\"my-trigger-id\">\n * <nys-dropdownmenuitem label=\"Profile\" href=\"/profile\"></nys-dropdownmenuitem>\n * <nys-dropdownmenuitem label=\"Repositories & Github Pages\" href=\"/repos\"></nys-dropdownmenuitem>\n * <nys-dropdownmenuitem label=\"Organizations\" href=\"/organizations\"></nys-dropdownmenuitem>\n * <nys-dropdownmenuitem label=\"Sign out\" href=\"/logout\"></nys-dropdownmenuitem>\n * </nys-dropdownmenu>\n * </div>\n * ```\n *\n * @render Basic\n * ```html\n * <div style=\"margin: 200px; display: flex; justify-content: center; align-items: center;\">\n * <nys-button id=\"my-trigger-id\" label=\"Open Menu\"></nys-button>\n * <nys-dropdownmenu id=\"my-dropdownmenu\" for=\"my-trigger-id\">\n * <nys-dropdownmenuitem label=\"Profile\" href=\"/profile\"></nys-dropdownmenuitem>\n * <nys-dropdownmenuitem label=\"Repositories & Github Pages\" href=\"/repos\"></nys-dropdownmenuitem>\n * <nys-dropdownmenuitem label=\"Organizations\" href=\"/organizations\"></nys-dropdownmenuitem>\n * <nys-dropdownmenuitem label=\"Sign out\" href=\"/logout\"></nys-dropdownmenuitem>\n * </nys-dropdownmenu>\n * </div>\n * ```\n */\n\nexport class NysDropdownMenu extends LitElement {\n static styles = unsafeCSS(styles);\n\n @property({ type: String, reflect: true }) for = \"\";\n @property({ type: Boolean }) showDropdown = false;\n\n /**\n * Accessible label for the menu. Used as `aria-label` on the `<ul role=\"menu\">` element.\n * @default \"\"\n */\n @property({ type: String }) label = \"\";\n\n /**\n * Preferred position relative to trigger.\n * @default \"bottom-end\"\n */\n @property({ type: String, reflect: true }) position: Position | null = null;\n\n private _trigger: HTMLElement | null = null;\n private _menuElement: HTMLElement | null = null;\n private _ariaTarget: HTMLElement | null = null;\n private _lastFocusedIndex: number = 0;\n private readonly GAP = 4;\n private _resizeObserver: ResizeObserver | null = null;\n\n /**\n * Lifecycle Methods\n * --------------------------------------------------------------------------\n */\n\n constructor() {\n super();\n }\n\n // Generate a unique ID if one is not provided\n connectedCallback() {\n super.connectedCallback();\n\n if (!this.id) {\n this.id = `nys-dropdownmenu-${Date.now()}-${dropdownMenuIdCounter++}`;\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n }\n\n async firstUpdated() {\n await this.updateComplete;\n this.applyInverseTransform();\n this._connectTrigger();\n this._handleMenuClick();\n }\n /**\n * Functions\n * --------------------------------------------------------------------------\n */\n\n private _findTrigger() {\n const targetId = this.for;\n if (!targetId) return null;\n\n // lightDOM search\n let htmlElement = document.getElementById(targetId);\n if (htmlElement) return htmlElement;\n\n // Search recursively through shadow DOMs (e.g. for nys-label within other component's shadowDOM)\n const findInShadows = (root: ParentNode): HTMLElement | null => {\n for (const el of Array.from(root.querySelectorAll(\"*\"))) {\n const shadowElement = el.shadowRoot;\n if (shadowElement) {\n const found = shadowElement.getElementById(targetId);\n if (found) return found;\n\n const deeper = findInShadows(shadowElement);\n if (deeper) return deeper;\n }\n }\n return null;\n };\n\n return findInShadows(document);\n }\n\n private _connectTrigger() {\n const trigger = this._findTrigger();\n if (!trigger) return;\n\n this._trigger = trigger;\n\n const ariaTarget =\n trigger.tagName.toLowerCase() === \"nys-button\"\n ? (trigger.shadowRoot?.querySelector(\"button\") ?? trigger)\n : trigger;\n\n ariaTarget.setAttribute(\"aria-haspopup\", \"menu\");\n ariaTarget.setAttribute(\"aria-expanded\", \"false\");\n\n this._ariaTarget = ariaTarget;\n\n this._trigger.addEventListener(\"click\", this._toggleDropdown);\n this._trigger.addEventListener(\"keydown\", this._handleTriggerKeydown);\n }\n\n private _toggleDropdown = async () => {\n this.showDropdown = !this.showDropdown;\n\n this._ariaTarget?.setAttribute(\"aria-expanded\", String(this.showDropdown));\n\n if (this.showDropdown) {\n window.addEventListener(\"scroll\", this._handleWindowScroll, true);\n this._resizeObserver = new ResizeObserver(() => {\n if (this.showDropdown) {\n this._positionMenu();\n }\n });\n this._resizeObserver.observe(document.documentElement);\n\n document.addEventListener(\"click\", this._handleDocumentClick);\n\n this._menuElement = this.shadowRoot?.querySelector(\n \".nys-dropdownmenu\",\n ) as HTMLElement | null;\n this._menuElement!.addEventListener(\"keydown\", this._handleMenuKeydown);\n\n await this.updateComplete;\n this._positionMenu();\n this._focusOnItem(this._lastFocusedIndex);\n } else {\n window.removeEventListener(\"scroll\", this._handleWindowScroll, true);\n document.removeEventListener(\"click\", this._handleDocumentClick);\n this._menuElement!.removeEventListener(\n \"keydown\",\n this._handleMenuKeydown,\n );\n\n this._resizeObserver?.disconnect();\n this._resizeObserver = null;\n }\n };\n\n private _closeDropdown() {\n this.showDropdown = false;\n this._ariaTarget?.setAttribute(\"aria-expanded\", \"false\");\n this._trigger?.focus();\n }\n\n private _getMenuItems(): HTMLElement[] {\n const slot = this.shadowRoot?.querySelector(\"slot\");\n const assigned = slot?.assignedElements({ flatten: true }) || [];\n\n return assigned.filter(\n (el) => el && !el.hasAttribute(\"disabled\"),\n ) as HTMLElement[];\n }\n\n private _handleDocumentClick = (event: MouseEvent) => {\n if (!this.showDropdown) return;\n\n const path = event?.composedPath();\n\n const clickedInsideMenu = path.includes(this);\n const clickedTrigger = this._trigger && path.includes(this._trigger);\n\n if (!clickedInsideMenu && !clickedTrigger) {\n this._closeDropdown();\n }\n };\n\n private async _focusOnItem(index: number = 0) {\n await new Promise((resolve) => requestAnimationFrame(resolve));\n const items = this._getMenuItems();\n const target = items[Math.min(index, items.length - 1)];\n if (!target) return;\n\n target.focus();\n }\n\n // In some iframes (like Storybook's) or embedded containers , parent elements may have CSS transforms applied, creating a new coordinate context.\n // This function removes such transforms to prevent them from affecting tooltip positioning calculations.\n private applyInverseTransform() {\n document.querySelectorAll('div[scale=\"1\"]').forEach((el) => {\n (el as HTMLElement).style.transform = \"none\";\n });\n }\n\n /**\n * Position Logic\n * --------------------------------------------------------------------------\n */\n\n /**\n * The controller function for positioning the dropdown menu.\n * The logic diverts to if user sets position or we auto position the dropdown menu\n */\n private _positionMenu() {\n if (!this._trigger) return;\n\n this._menuElement = this.shadowRoot?.querySelector(\n \".nys-dropdownmenu\",\n ) as HTMLElement | null;\n if (!this._menuElement) return;\n\n // Decide position based on user preference OR auto position if no position chosen\n const finalPosition = this.position\n ? this._setUserPosition(this.position)\n : this._autoPosition();\n\n // Apply the calculated position\n const coords = this._calculateCoordinates(finalPosition);\n this._applyPosition(coords);\n }\n\n private _setUserPosition(userPosition: Position): Position {\n const space = this._checkSpaceAvailable();\n const menuRect = this._menuElement!.getBoundingClientRect();\n\n const userPositionFits = this._checkPositionFits(\n userPosition,\n space,\n menuRect,\n );\n\n if (userPositionFits) {\n return userPosition;\n }\n\n // User position doesn't fit, find best alternative\n return this._findBestAlternative(userPosition, space, menuRect);\n }\n\n /**\n * Auto Positioning of the dropdown menu relies on the best surrounding space available\n * to select the desirable position.\n */\n private _autoPosition(): Position {\n const space = this._checkSpaceAvailable();\n const menuRect = this._menuElement!.getBoundingClientRect();\n\n const defaultPosition: Position = \"bottom-end\";\n\n if (this._checkPositionFits(defaultPosition, space, menuRect)) {\n return defaultPosition;\n }\n\n return this._findBestAlternative(defaultPosition, space, menuRect);\n }\n\n /**\n * Checks if the dropdown menu fits inside the viewport on the given side of the trigger.\n * Overrides user set position for auto-positioning if user's desire space is not available\n */\n private _checkSpaceAvailable(): SpaceAvailable {\n if (!this._trigger) {\n return { top: 0, bottom: 0, start: 0, end: 0 };\n }\n\n const triggerRect = this._trigger.getBoundingClientRect();\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n\n return {\n top: triggerRect.top,\n bottom: viewportHeight - triggerRect.bottom,\n start: triggerRect.left,\n end: viewportWidth - triggerRect.right,\n };\n }\n\n private _checkPositionFits(\n position: Position,\n space: SpaceAvailable,\n menuRect: DOMRect,\n ): boolean {\n const menuWidth = menuRect.width;\n const menuHeight = menuRect.height;\n\n const [vertical, horizontal] = position.split(\"-\") as [\n \"top\" | \"bottom\",\n \"start\" | \"end\",\n ];\n\n const verticalFits =\n vertical === \"bottom\"\n ? space.bottom >= menuHeight + this.GAP\n : space.top >= menuHeight + this.GAP;\n\n const horizontalFits =\n horizontal === \"start\"\n ? space.end >= menuWidth\n : space.start >= menuWidth;\n return verticalFits && horizontalFits;\n }\n\n /**\n * This position is called for when user's set position didn't fit OR auto positioning when default position doesn't fit\n * We look for the best alternative positions in order of preference base on the set position (e.g. bottom-start => bottom-end).\n * @param userPosition\n * @param space\n * @param menuRect\n */\n private _findBestAlternative(\n userPosition: Position,\n space: SpaceAvailable,\n menuRect: DOMRect,\n ): Position {\n const [vertical, horizontal] = userPosition.split(\"-\") as [\n \"top\" | \"bottom\",\n \"start\" | \"end\",\n ];\n\n const alternatives: Position[] = [\n `${vertical === \"bottom\" ? \"top\" : \"bottom\"}-${horizontal}`, // Flip vertical\n `${vertical}-${horizontal === \"start\" ? \"end\" : \"start\"}`, // Flip horizontal\n `${vertical === \"bottom\" ? \"top\" : \"bottom\"}-${horizontal === \"start\" ? \"end\" : \"start\"}`, // Flip both\n ];\n\n for (const altPosition of alternatives) {\n if (this._checkPositionFits(altPosition, space, menuRect)) {\n return altPosition;\n }\n }\n\n // Fallback: nothing fits, return position with most space\n return this._findMostAvailableSpace(space) as Position;\n }\n\n private _findMostAvailableSpace(space: SpaceAvailable): Position {\n const vertical = space.bottom >= space.top ? \"bottom\" : \"top\";\n const horizontal = space.start >= space.end ? \"start\" : \"end\";\n\n return `${vertical}-${horizontal}`;\n }\n\n /**\n * A valid ideal position has been chosen.\n * This function calculates the coordinate of the trigger to properly position the dropdown menu.\n * @param position\n * @returns\n */\n private _calculateCoordinates(position: Position): PositionCoordinates {\n if (!this._trigger || !this._menuElement) {\n return { top: 0, left: 0 };\n }\n\n const triggerRect = this._trigger.getBoundingClientRect();\n const menuRect = this._menuElement.getBoundingClientRect();\n\n const [vertical, horizontal] = position.split(\"-\") as [\n \"top\" | \"bottom\",\n \"start\" | \"end\",\n ];\n\n let top = 0;\n let left = 0;\n\n // Vertical position\n if (vertical === \"bottom\") {\n top = triggerRect.bottom + this.GAP;\n } else {\n top = triggerRect.top - menuRect.height - this.GAP;\n }\n\n // Horizontal position\n if (horizontal === \"start\") {\n left = triggerRect.left;\n } else {\n left = triggerRect.right - menuRect.width;\n }\n\n return { top, left };\n }\n\n private _applyPosition(coords: PositionCoordinates) {\n if (!this._menuElement) return;\n\n this._menuElement.style.top = `${coords.top}px`;\n this._menuElement.style.left = `${coords.left}px`;\n }\n\n /**\n * Event Handlers\n * --------------------------------------------------------------------------\n */\n\n private _handleMenuClick() {\n this.addEventListener(\"nys-click\", (e: Event) => {\n const items = this._getMenuItems();\n const targetCrumb = (e as CustomEvent).detail?.id;\n const index = items.findIndex((item) => item.id === targetCrumb);\n if (index !== -1) this._lastFocusedIndex = index;\n this._closeDropdown();\n });\n }\n\n private _handleTriggerKeydown = (event: KeyboardEvent) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n this._toggleDropdown();\n }\n\n if (event.key === \"Escape\" && this.showDropdown) {\n event.preventDefault();\n this._closeDropdown();\n }\n };\n\n private _handleMenuKeydown = (event: KeyboardEvent) => {\n const items = this._getMenuItems();\n const currentIndex = items.indexOf(document.activeElement as HTMLElement);\n\n switch (event.key) {\n case \"Escape\":\n event.preventDefault();\n this._closeDropdown();\n break;\n case \"ArrowDown\":\n case \"ArrowRight\":\n event.preventDefault();\n const nextIndex =\n currentIndex < items.length - 1 ? currentIndex + 1 : 0;\n this._lastFocusedIndex = nextIndex;\n items[nextIndex].focus();\n break;\n case \"ArrowUp\":\n case \"ArrowLeft\":\n event.preventDefault();\n const prevIndex =\n currentIndex > 0 ? currentIndex - 1 : items.length - 1;\n this._lastFocusedIndex = prevIndex;\n items[prevIndex].focus();\n break;\n case \"Tab\":\n if (currentIndex >= items.length - 1 && !event.shiftKey) {\n this._closeDropdown();\n }\n break;\n default:\n break;\n }\n };\n\n private _handleWindowScroll = () => {\n if (this.showDropdown) {\n this._positionMenu();\n }\n };\n\n render() {\n return html`<div\n class=\"nys-dropdownmenu ${this.showDropdown ? \"active\" : \"\"}\"\n for=${this.for}\n ?hidden=${!this.showDropdown}\n >\n <ul role=\"menu\" aria-label=${this.label || \"Menu\"}>\n <slot></slot>\n </ul>\n </div>`;\n }\n}\n\nif (!customElements.get(\"nys-dropdownmenu\")) {\n customElements.define(\"nys-dropdownmenu\", NysDropdownMenu);\n}\n"],"names":["dropdownMenuItemIdCounter","_NysDropdownMenuItem","LitElement","isLink","html","unsafeCSS","styles","NysDropdownMenuItem","__decorateClass","property","dropdownMenuIdCounter","_NysDropdownMenu","event","path","clickedInsideMenu","clickedTrigger","items","currentIndex","nextIndex","prevIndex","targetId","htmlElement","findInShadows","root","el","shadowElement","found","deeper","trigger","ariaTarget","index","resolve","target","finalPosition","coords","userPosition","space","menuRect","defaultPosition","triggerRect","viewportWidth","viewportHeight","position","menuWidth","menuHeight","vertical","horizontal","verticalFits","horizontalFits","alternatives","altPosition","top","left","targetCrumb","item","NysDropdownMenu"],"mappings":";;;;;;;;;;;;;;;;;;AAKA,IAAIA,IAA4B;AAYzB,MAAMC,IAAN,MAAMA,UAA4BC,EAAW;AAAA,EAA7C,cAAA;AAAA,UAAA,GAAA,SAAA,GAOuB,KAAA,QAAQ,IACR,KAAA,OAAO,IACS,KAAA,WAAW,IAC3B,KAAA,SAAS,SACT,KAAA,aAAa,IACb,KAAA,UAAU;AAAA,EAAA;AAAA;AAAA,EAGtC,oBAAoB;AAClB,UAAM,kBAAA,GACD,KAAK,OACR,KAAK,KAAK,wBAAwB,KAAK,KAAK,IAAIF,GAA2B;AAAA,EAE/E;AAAA,EAEQ,aAAa,GAAU;AAC7B,QAAI,KAAK,UAAU;AACjB,QAAE,eAAA;AACF;AAAA,IACF;AAEA,SAAK;AAAA,MACH,IAAI,YAAY,aAAa;AAAA,QAC3B,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ;AAAA,UACN,IAAI,KAAK;AAAA,UACT,OAAO,KAAK;AAAA,UACZ,GAAI,KAAK,QAAQ,EAAE,MAAM,KAAK,KAAA;AAAA,QAAK;AAAA,MACrC,CACD;AAAA,IAAA;AAAA,EAEL;AAAA,EAEA,SAAS;AACP,UAAMG,IAAS,CAAC,CAAC,KAAK;AAEtB,WAAOC;AAAA,QACHD,IACEC;AAAA,oBACU,KAAK,WAAW,aAAa,EAAE;AAAA,mBAChC,KAAK,WAAW,KAAK,KAAK,IAAI;AAAA;AAAA,6BAEpB,KAAK,WAAW,SAAS,OAAO;AAAA,yBACpC,KAAK,KAAK;AAAA,uBACZ,KAAK,WAAW,OAAO,GAAG;AAAA,sBAC3B,KAAK,YAAY;AAAA,sBACjB,KAAK,MAAM;AAAA;AAAA,cAEnB,KAAK,aACHA,6BAAgC,KAAK,UAAU,iBAC/C,EAAE;AAAA,cACJ,KAAK,KAAK;AAAA,eAEdA;AAAA;AAAA,sBAEY,KAAK,WAAW,aAAa,EAAE;AAAA;AAAA;AAAA,+BAGtB,KAAK,WAAW,SAAS,OAAO;AAAA,2BACpC,KAAK,KAAK;AAAA,yBACZ,KAAK,WAAW,OAAO,GAAG;AAAA,0BACzB,KAAK,QAAQ;AAAA,wBACf,KAAK,YAAY;AAAA;AAAA,gBAEzB,KAAK,aACHA,6BAAgC,KAAK,UAAU,iBAC/C,EAAE;AAAA,gBACJ,KAAK,KAAK;AAAA;AAAA,WAEf;AAAA;AAAA,EAET;AACF;AA/EEH,EAAO,SAASI,EAAUC,CAAM,GAChCL,EAAO,oBAAoB;AAAA,EACzB,GAAGC,EAAW;AAAA,EACd,gBAAgB;AAAA;AAJb,IAAMK,IAANN;AAOuBO,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAPfF,EAOiB,WAAA,OAAA;AACAC,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GARfF,EAQiB,WAAA,MAAA;AACgBC,EAAA;AAAA,EAA3CC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GAT/BF,EASiC,WAAA,UAAA;AAChBC,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAVfF,EAUiB,WAAA,QAAA;AACAC,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAXfF,EAWiB,WAAA,YAAA;AACAC,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAZfF,EAYiB,WAAA,SAAA;AAsEzB,eAAe,IAAI,sBAAsB,KAC5C,eAAe,OAAO,wBAAwBA,CAAmB;;;;;;AC9FnE,IAAIG,IAAwB;AAiDrB,MAAMC,IAAN,MAAMA,UAAwBT,EAAW;AAAA;AAAA;AAAA;AAAA;AAAA,EA8B9C,cAAc;AACZ,UAAA,GA5ByC,KAAA,MAAM,IACpB,KAAA,eAAe,IAMhB,KAAA,QAAQ,IAMO,KAAA,WAA4B,MAEvE,KAAQ,WAA+B,MACvC,KAAQ,eAAmC,MAC3C,KAAQ,cAAkC,MAC1C,KAAQ,oBAA4B,GACpC,KAAiB,MAAM,GACvB,KAAQ,kBAAyC,MAiFjD,KAAQ,kBAAkB,YAAY;AACpC,WAAK,eAAe,CAAC,KAAK,cAE1B,KAAK,aAAa,aAAa,iBAAiB,OAAO,KAAK,YAAY,CAAC,GAErE,KAAK,gBACP,OAAO,iBAAiB,UAAU,KAAK,qBAAqB,EAAI,GAChE,KAAK,kBAAkB,IAAI,eAAe,MAAM;AAC9C,QAAI,KAAK,gBACP,KAAK,cAAA;AAAA,MAET,CAAC,GACD,KAAK,gBAAgB,QAAQ,SAAS,eAAe,GAErD,SAAS,iBAAiB,SAAS,KAAK,oBAAoB,GAE5D,KAAK,eAAe,KAAK,YAAY;AAAA,QACnC;AAAA,MAAA,GAEF,KAAK,aAAc,iBAAiB,WAAW,KAAK,kBAAkB,GAEtE,MAAM,KAAK,gBACX,KAAK,cAAA,GACL,KAAK,aAAa,KAAK,iBAAiB,MAExC,OAAO,oBAAoB,UAAU,KAAK,qBAAqB,EAAI,GACnE,SAAS,oBAAoB,SAAS,KAAK,oBAAoB,GAC/D,KAAK,aAAc;AAAA,QACjB;AAAA,QACA,KAAK;AAAA,MAAA,GAGP,KAAK,iBAAiB,WAAA,GACtB,KAAK,kBAAkB;AAAA,IAE3B,GAiBA,KAAQ,uBAAuB,CAACU,MAAsB;AACpD,UAAI,CAAC,KAAK,aAAc;AAExB,YAAMC,IAAOD,GAAO,aAAA,GAEdE,IAAoBD,EAAK,SAAS,IAAI,GACtCE,IAAiB,KAAK,YAAYF,EAAK,SAAS,KAAK,QAAQ;AAEnE,MAAI,CAACC,KAAqB,CAACC,KACzB,KAAK,eAAA;AAAA,IAET,GAoOA,KAAQ,wBAAwB,CAACH,MAAyB;AACxD,OAAIA,EAAM,QAAQ,WAAWA,EAAM,QAAQ,SACzCA,EAAM,eAAA,GACN,KAAK,gBAAA,IAGHA,EAAM,QAAQ,YAAY,KAAK,iBACjCA,EAAM,eAAA,GACN,KAAK,eAAA;AAAA,IAET,GAEA,KAAQ,qBAAqB,CAACA,MAAyB;AACrD,YAAMI,IAAQ,KAAK,cAAA,GACbC,IAAeD,EAAM,QAAQ,SAAS,aAA4B;AAExE,cAAQJ,EAAM,KAAA;AAAA,QACZ,KAAK;AACH,UAAAA,EAAM,eAAA,GACN,KAAK,eAAA;AACL;AAAA,QACF,KAAK;AAAA,QACL,KAAK;AACH,UAAAA,EAAM,eAAA;AACN,gBAAMM,IACJD,IAAeD,EAAM,SAAS,IAAIC,IAAe,IAAI;AACvD,eAAK,oBAAoBC,GACzBF,EAAME,CAAS,EAAE,MAAA;AACjB;AAAA,QACF,KAAK;AAAA,QACL,KAAK;AACH,UAAAN,EAAM,eAAA;AACN,gBAAMO,IACJF,IAAe,IAAIA,IAAe,IAAID,EAAM,SAAS;AACvD,eAAK,oBAAoBG,GACzBH,EAAMG,CAAS,EAAE,MAAA;AACjB;AAAA,QACF,KAAK;AACH,UAAIF,KAAgBD,EAAM,SAAS,KAAK,CAACJ,EAAM,YAC7C,KAAK,eAAA;AAEP;AAAA,MAEA;AAAA,IAEN,GAEA,KAAQ,sBAAsB,MAAM;AAClC,MAAI,KAAK,gBACP,KAAK,cAAA;AAAA,IAET;AAAA,EA9ZA;AAAA;AAAA,EAGA,oBAAoB;AAClB,UAAM,kBAAA,GAED,KAAK,OACR,KAAK,KAAK,oBAAoB,KAAK,KAAK,IAAIF,GAAuB;AAAA,EAEvE;AAAA,EAEA,uBAAuB;AACrB,UAAM,qBAAA;AAAA,EACR;AAAA,EAEA,MAAM,eAAe;AACnB,UAAM,KAAK,gBACX,KAAK,sBAAA,GACL,KAAK,gBAAA,GACL,KAAK,iBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAe;AACrB,UAAMU,IAAW,KAAK;AACtB,QAAI,CAACA,EAAU,QAAO;AAGtB,QAAIC,IAAc,SAAS,eAAeD,CAAQ;AAClD,QAAIC,EAAa,QAAOA;AAGxB,UAAMC,IAAgB,CAACC,MAAyC;AAC9D,iBAAWC,KAAM,MAAM,KAAKD,EAAK,iBAAiB,GAAG,CAAC,GAAG;AACvD,cAAME,IAAgBD,EAAG;AACzB,YAAIC,GAAe;AACjB,gBAAMC,IAAQD,EAAc,eAAeL,CAAQ;AACnD,cAAIM,EAAO,QAAOA;AAElB,gBAAMC,IAASL,EAAcG,CAAa;AAC1C,cAAIE,EAAQ,QAAOA;AAAA,QACrB;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAEA,WAAOL,EAAc,QAAQ;AAAA,EAC/B;AAAA,EAEQ,kBAAkB;AACxB,UAAMM,IAAU,KAAK,aAAA;AACrB,QAAI,CAACA,EAAS;AAEd,SAAK,WAAWA;AAEhB,UAAMC,IACJD,EAAQ,QAAQ,YAAA,MAAkB,eAC7BA,EAAQ,YAAY,cAAc,QAAQ,KAAKA,IAChDA;AAEN,IAAAC,EAAW,aAAa,iBAAiB,MAAM,GAC/CA,EAAW,aAAa,iBAAiB,OAAO,GAEhD,KAAK,cAAcA,GAEnB,KAAK,SAAS,iBAAiB,SAAS,KAAK,eAAe,GAC5D,KAAK,SAAS,iBAAiB,WAAW,KAAK,qBAAqB;AAAA,EACtE;AAAA,EAuCQ,iBAAiB;AACvB,SAAK,eAAe,IACpB,KAAK,aAAa,aAAa,iBAAiB,OAAO,GACvD,KAAK,UAAU,MAAA;AAAA,EACjB;AAAA,EAEQ,gBAA+B;AAIrC,YAHa,KAAK,YAAY,cAAc,MAAM,GAC3B,iBAAiB,EAAE,SAAS,GAAA,CAAM,KAAK,CAAA,GAE9C;AAAA,MACd,CAACL,MAAOA,KAAM,CAACA,EAAG,aAAa,UAAU;AAAA,IAAA;AAAA,EAE7C;AAAA,EAeA,MAAc,aAAaM,IAAgB,GAAG;AAC5C,UAAM,IAAI,QAAQ,CAACC,MAAY,sBAAsBA,CAAO,CAAC;AAC7D,UAAMf,IAAQ,KAAK,cAAA,GACbgB,IAAShB,EAAM,KAAK,IAAIc,GAAOd,EAAM,SAAS,CAAC,CAAC;AACtD,IAAKgB,KAELA,EAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA,EAIQ,wBAAwB;AAC9B,aAAS,iBAAiB,gBAAgB,EAAE,QAAQ,CAACR,MAAO;AACzD,MAAAA,EAAmB,MAAM,YAAY;AAAA,IACxC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,gBAAgB;AAMtB,QALI,CAAC,KAAK,aAEV,KAAK,eAAe,KAAK,YAAY;AAAA,MACnC;AAAA,IAAA,GAEE,CAAC,KAAK,cAAc;AAGxB,UAAMS,IAAgB,KAAK,WACvB,KAAK,iBAAiB,KAAK,QAAQ,IACnC,KAAK,cAAA,GAGHC,IAAS,KAAK,sBAAsBD,CAAa;AACvD,SAAK,eAAeC,CAAM;AAAA,EAC5B;AAAA,EAEQ,iBAAiBC,GAAkC;AACzD,UAAMC,IAAQ,KAAK,qBAAA,GACbC,IAAW,KAAK,aAAc,sBAAA;AAQpC,WANyB,KAAK;AAAA,MAC5BF;AAAA,MACAC;AAAA,MACAC;AAAA,IAAA,IAIOF,IAIF,KAAK,qBAAqBA,GAAcC,GAAOC,CAAQ;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,gBAA0B;AAChC,UAAMD,IAAQ,KAAK,qBAAA,GACbC,IAAW,KAAK,aAAc,sBAAA,GAE9BC,IAA4B;AAElC,WAAI,KAAK,mBAAmBA,GAAiBF,GAAOC,CAAQ,IACnDC,IAGF,KAAK,qBAAqBA,GAAiBF,GAAOC,CAAQ;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,uBAAuC;AAC7C,QAAI,CAAC,KAAK;AACR,aAAO,EAAE,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,KAAK,EAAA;AAG7C,UAAME,IAAc,KAAK,SAAS,sBAAA,GAC5BC,IAAgB,OAAO,YACvBC,IAAiB,OAAO;AAE9B,WAAO;AAAA,MACL,KAAKF,EAAY;AAAA,MACjB,QAAQE,IAAiBF,EAAY;AAAA,MACrC,OAAOA,EAAY;AAAA,MACnB,KAAKC,IAAgBD,EAAY;AAAA,IAAA;AAAA,EAErC;AAAA,EAEQ,mBACNG,GACAN,GACAC,GACS;AACT,UAAMM,IAAYN,EAAS,OACrBO,IAAaP,EAAS,QAEtB,CAACQ,GAAUC,CAAU,IAAIJ,EAAS,MAAM,GAAG,GAK3CK,IACJF,MAAa,WACTT,EAAM,UAAUQ,IAAa,KAAK,MAClCR,EAAM,OAAOQ,IAAa,KAAK,KAE/BI,IACJF,MAAe,UACXV,EAAM,OAAOO,IACbP,EAAM,SAASO;AACrB,WAAOI,KAAgBC;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,qBACNb,GACAC,GACAC,GACU;AACV,UAAM,CAACQ,GAAUC,CAAU,IAAIX,EAAa,MAAM,GAAG,GAK/Cc,IAA2B;AAAA,MAC/B,GAAGJ,MAAa,WAAW,QAAQ,QAAQ,IAAIC,CAAU;AAAA;AAAA,MACzD,GAAGD,CAAQ,IAAIC,MAAe,UAAU,QAAQ,OAAO;AAAA;AAAA,MACvD,GAAGD,MAAa,WAAW,QAAQ,QAAQ,IAAIC,MAAe,UAAU,QAAQ,OAAO;AAAA;AAAA,IAAA;AAGzF,eAAWI,KAAeD;AACxB,UAAI,KAAK,mBAAmBC,GAAad,GAAOC,CAAQ;AACtD,eAAOa;AAKX,WAAO,KAAK,wBAAwBd,CAAK;AAAA,EAC3C;AAAA,EAEQ,wBAAwBA,GAAiC;AAC/D,UAAMS,IAAWT,EAAM,UAAUA,EAAM,MAAM,WAAW,OAClDU,IAAaV,EAAM,SAASA,EAAM,MAAM,UAAU;AAExD,WAAO,GAAGS,CAAQ,IAAIC,CAAU;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,sBAAsBJ,GAAyC;AACrE,QAAI,CAAC,KAAK,YAAY,CAAC,KAAK;AAC1B,aAAO,EAAE,KAAK,GAAG,MAAM,EAAA;AAGzB,UAAMH,IAAc,KAAK,SAAS,sBAAA,GAC5BF,IAAW,KAAK,aAAa,sBAAA,GAE7B,CAACQ,GAAUC,CAAU,IAAIJ,EAAS,MAAM,GAAG;AAKjD,QAAIS,IAAM,GACNC,IAAO;AAGX,WAAIP,MAAa,WACfM,IAAMZ,EAAY,SAAS,KAAK,MAEhCY,IAAMZ,EAAY,MAAMF,EAAS,SAAS,KAAK,KAI7CS,MAAe,UACjBM,IAAOb,EAAY,OAEnBa,IAAOb,EAAY,QAAQF,EAAS,OAG/B,EAAE,KAAAc,GAAK,MAAAC,EAAA;AAAA,EAChB;AAAA,EAEQ,eAAelB,GAA6B;AAClD,IAAK,KAAK,iBAEV,KAAK,aAAa,MAAM,MAAM,GAAGA,EAAO,GAAG,MAC3C,KAAK,aAAa,MAAM,OAAO,GAAGA,EAAO,IAAI;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,mBAAmB;AACzB,SAAK,iBAAiB,aAAa,CAAC,MAAa;AAC/C,YAAMlB,IAAQ,KAAK,cAAA,GACbqC,IAAe,EAAkB,QAAQ,IACzCvB,IAAQd,EAAM,UAAU,CAACsC,MAASA,EAAK,OAAOD,CAAW;AAC/D,MAAIvB,MAAU,OAAI,KAAK,oBAAoBA,IAC3C,KAAK,eAAA;AAAA,IACP,CAAC;AAAA,EACH;AAAA,EAuDA,SAAS;AACP,WAAO1B;AAAA,gCACqB,KAAK,eAAe,WAAW,EAAE;AAAA,YACrD,KAAK,GAAG;AAAA,gBACJ,CAAC,KAAK,YAAY;AAAA;AAAA,mCAEC,KAAK,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA,EAIrD;AACF;AA1cEO,EAAO,SAASN,EAAUC,CAAM;AAD3B,IAAMiD,IAAN5C;AAGsCH,EAAA;AAAA,EAA1CC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAH9B8C,EAGgC,WAAA,KAAA;AACd/C,EAAA;AAAA,EAA5BC,EAAS,EAAE,MAAM,QAAA,CAAS;AAAA,GAJhB8C,EAIkB,WAAA,cAAA;AAMD/C,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAVf8C,EAUiB,WAAA,OAAA;AAMe/C,EAAA;AAAA,EAA1CC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAhB9B8C,EAgBgC,WAAA,UAAA;AA6bxC,eAAe,IAAI,kBAAkB,KACxC,eAAe,OAAO,oBAAoBA,CAAe;"}
1
+ {"version":3,"file":"nys-dropdownmenu.js","sources":["../../internals/dist/index.js","../src/nys-dropdownmenuitem.ts","../src/nys-dropdownmenu.ts"],"sourcesContent":["import { LitElement as u } from \"lit\";\n/*!\n * New York State Design System v1.20.1\n * Description: A design system for New York State's digital products.\n * Repository: https://github.com/its-hcd/nysds\n * License: MIT\n */\nlet y = 0;\nfunction f(e) {\n return `${e}-${Date.now()}-${y++}`;\n}\nconst p = {\n labelledby: \"ariaLabelledByElements\",\n describedby: \"ariaDescribedByElements\"\n}, A = {\n labelledby: \"ariaLabel\",\n describedby: \"ariaDescription\"\n};\nfunction R(e) {\n return \"ariaDescribedByElements\" in e;\n}\nfunction _(e) {\n return e === \"errormessage\" ? \"aria-errormessage\" : `aria-${e}`;\n}\nfunction d(e) {\n return e.filter((t) => !!t);\n}\nfunction E(e) {\n return e.map((t) => (t.id || (t.id = f(\"nys-ref\")), t.id));\n}\nfunction V(e, t, n) {\n const i = d(n), r = _(t);\n i.length ? e.setAttribute(r, E(i).join(\" \")) : e.removeAttribute(r);\n}\nfunction x(e, t, n, i, r) {\n const s = d(i), a = p[n], l = t;\n if (a && R(t)) {\n l[a] = s.length ? s : null;\n return;\n }\n const o = A[n];\n if (!o) return;\n const c = r ?? (s.length ? s.map((m) => m.textContent?.trim() ?? \"\").filter(Boolean).join(\" \") : \"\");\n o in l ? l[o] = c || null : c ? e.setAttribute(\n n === \"labelledby\" ? \"aria-label\" : \"aria-description\",\n c\n ) : e.removeAttribute(\n n === \"labelledby\" ? \"aria-label\" : \"aria-description\"\n );\n}\nconst g = {\n labelledby: \"ariaLabelledByElements\",\n describedby: \"ariaDescribedByElements\"\n}, C = {\n labelledby: \"aria-label\",\n describedby: \"aria-description\"\n};\nfunction L(e, t, n) {\n const i = d(n), r = g[t], s = C[t], a = e;\n if (r && r in e && (a[r] = i.length ? i : null), !s) return;\n const l = i.map((o) => o.textContent?.trim() ?? \"\").filter(Boolean).join(\" \");\n l ? e.setAttribute(s, l) : e.removeAttribute(s);\n}\nconst b = (e) => {\n class t extends e {\n get idPrefix() {\n return this.localName || \"nys-element\";\n }\n ensureId() {\n this.id || (this.id = f(this.idPrefix));\n }\n connectedCallback() {\n super.connectedCallback(), this.ensureId();\n }\n }\n return t;\n}, P = /* @__PURE__ */ b(u), h = (e) => {\n class t extends b(e) {\n constructor() {\n super(...arguments), this.__internals = null;\n }\n get internals() {\n if (this.__internals) return this.__internals;\n if (typeof this.attachInternals == \"function\")\n try {\n this.__internals = this.attachInternals();\n } catch {\n this.__internals = null;\n }\n return this.__internals;\n }\n get defaultRole() {\n return null;\n }\n setHostAria(i, r) {\n const s = this.internals;\n if (s && i in s) {\n s[i] = r;\n return;\n }\n const a = v(i);\n r === null ? this.removeAttribute(a) : this.setAttribute(a, r);\n }\n reflectDefaultSemantics() {\n const i = this.defaultRole;\n i && this.setHostAria(\"role\", i);\n }\n connectedCallback() {\n super.connectedCallback(), this.reflectDefaultSemantics();\n }\n }\n return t;\n};\nfunction v(e) {\n if (e === \"role\") return \"role\";\n const t = e.replace(/^aria/, \"\");\n return \"aria-\" + t.charAt(0).toLowerCase() + t.slice(1);\n}\nconst T = /* @__PURE__ */ h(u), I = (e) => {\n const n = class n extends h(e) {\n setFormValue(r) {\n this.internals?.setFormValue(r ?? null);\n }\n setValidityFromState(r, s, a) {\n const l = this.internals;\n if (!l) return;\n const o = Object.values(r).some(Boolean);\n o ? l.setValidity(r, s ?? \"Invalid value\", a) : l.setValidity({}), this.setHostAria(\"ariaInvalid\", o ? \"true\" : \"false\");\n }\n clearValidity() {\n this.internals?.setValidity({}), this.setHostAria(\"ariaInvalid\", \"false\");\n }\n checkValidity() {\n return this.internals?.checkValidity() ?? !0;\n }\n reportValidity() {\n return this.internals?.reportValidity() ?? !0;\n }\n formResetCallback() {\n this.clearValidity();\n }\n };\n n.formAssociated = !0;\n let t = n;\n return t;\n}, w = /* @__PURE__ */ I(u);\nfunction O(e) {\n const t = e.tagName.toLowerCase(), n = /* @__PURE__ */ new Set(), i = (r) => {\n r.querySelectorAll(\"*\").forEach((s) => {\n const a = s.tagName.toLowerCase();\n a.startsWith(\"nys-\") && a !== t && !customElements.get(a) && n.add(a), s.shadowRoot && i(s.shadowRoot);\n });\n };\n return e.shadowRoot && i(e.shadowRoot), i(e), [...n].sort();\n}\nexport {\n I as FormControlMixin,\n b as IdentifiedMixin,\n P as NysElement,\n w as NysFormControlElement,\n T as NysReflectsAriaElement,\n h as ReflectsAriaMixin,\n V as associateControl,\n L as associateControlRefs,\n x as associateHost,\n O as findUnregisteredChildren,\n f as generateId,\n R as supportsElementRefs\n};\n//# sourceMappingURL=index.js.map\n","import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property } from \"lit/decorators.js\";\nimport { NysElement } from \"@nysds/internals\";\n// This element is rendered inside this component's shadow DOM (the prefix\n// icon), so it must be registered whenever nys-dropdownmenuitem is used.\n// Importing it here (intentional side effect) guarantees it always renders.\nimport \"@nysds/nys-icon\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-dropdownmenu.scss?inline\";\n\n/**\n * **Slotted component.** Displays an individual dropdown item within `nys-dropdown` with label.\n *\n * The `nys-dropdownitem` is used as customizable item within the dropdown so users don't have to raw code <ul>, <li>, <a href>\n * and have the benefit of default customization.\n *\n * @summary Dropdown item to display label and provide href link.\n * @element nys-dropdownmenuitem\n */\nexport class NysDropdownMenuItem extends NysElement {\n static styles = unsafeCSS(styles);\n static shadowRootOptions = {\n ...LitElement.shadowRootOptions,\n delegatesFocus: true,\n };\n\n @property({ type: String }) label = \"\";\n @property({ type: String }) href = \"\";\n @property({ type: Boolean, reflect: true }) disabled = false;\n @property({ type: String }) target = \"_self\";\n @property({ type: String }) prefixIcon = \"\";\n @property({ type: String }) divider = \"\";\n\n // super.connectedCallback() (NysElement) auto-assigns this.id when\n // one is not provided (prefix = localName, i.e. \"nys-dropdownmenuitem-<ts>-<n>\").\n // role=\"menuitem\" intentionally stays on the inner <a>/<button>, so this\n // component keeps defaultRole = null and does not move a role onto the host.\n connectedCallback() {\n super.connectedCallback();\n }\n\n private _handleClick(e: Event) {\n if (this.disabled) {\n e.preventDefault();\n return;\n }\n\n this.dispatchEvent(\n new CustomEvent(\"nys-click\", {\n bubbles: true,\n composed: true,\n detail: {\n id: this.id,\n label: this.label,\n ...(this.href && { href: this.href }),\n },\n }),\n );\n }\n\n render() {\n const isLink = !!this.href;\n\n return html`<li class=\"nys-dropdownmenuitem\" role=\"presentation\">\n ${isLink\n ? html` <a\n class=${this.disabled ? \"disabled\" : \"\"}\n href=${this.disabled ? \"\" : this.href}\n role=\"menuitem\"\n aria-disabled=\"${this.disabled ? \"true\" : \"false\"}\"\n aria-label=${this.label}\n tabindex=${this.disabled ? \"-1\" : \"0\"}\n @click=\"${this._handleClick}\"\n target=\"${this.target}\"\n >\n ${this.prefixIcon\n ? html`<nys-icon size=\"16\" name=${this.prefixIcon}></nys-icon>`\n : \"\"}\n ${this.label}</a\n >`\n : html`\n <button\n class=${this.disabled ? \"disabled\" : \"\"}\n type=\"button\"\n role=\"menuitem\"\n aria-disabled=\"${this.disabled ? \"true\" : \"false\"}\"\n aria-label=${this.label}\n tabindex=${this.disabled ? \"-1\" : \"0\"}\n ?disabled=${this.disabled}\n @click=\"${this._handleClick}\"\n >\n ${this.prefixIcon\n ? html`<nys-icon size=\"16\" name=${this.prefixIcon}></nys-icon>`\n : \"\"}\n ${this.label}\n </button>\n `}\n </li>`;\n }\n}\n\nif (!customElements.get(\"nys-dropdownmenuitem\")) {\n customElements.define(\"nys-dropdownmenuitem\", NysDropdownMenuItem);\n}\n","import { html, unsafeCSS } from \"lit\";\nimport { property } from \"lit/decorators.js\";\nimport { NysElement } from \"@nysds/internals\";\nimport \"./nys-dropdownmenuitem\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-dropdownmenu.scss?inline\";\n\ntype Position = \"bottom-start\" | \"bottom-end\" | \"top-start\" | \"top-end\";\n\ninterface PositionCoordinates {\n top: number;\n left: number;\n}\n\ninterface SpaceAvailable {\n top: number;\n bottom: number;\n start: number;\n end: number;\n}\n\n/**\n * Dropdown menus enable users to select an action from a list of options.\n * They’re commonly used to save space by grouping related actions, or to provide actions in a confined space.\n *\n * @summary Action menu with auto-positioning, keyboard support, and screen reader integration.\n * @element nys-dropdownmenu\n *\n * @example Basic\n * ```html\n * <nys-button id=\"my-trigger-id\" label=\"Open Menu\"></nys-button>\n * <nys-dropdownmenu id=\"my-dropdownmenu\" for=\"my-trigger-id\">\n * <nys-dropdownmenuitem label=\"Profile\" href=\"/profile\"></nys-dropdownmenuitem>\n * <nys-dropdownmenuitem label=\"Repositories & Github Pages\" href=\"/repos\"></nys-dropdownmenuitem>\n * <nys-dropdownmenuitem label=\"Organizations\" href=\"/organizations\"></nys-dropdownmenuitem>\n * <nys-dropdownmenuitem label=\"Sign out\" href=\"/logout\"></nys-dropdownmenuitem>\n * </nys-dropdownmenu>\n * </div>\n * ```\n *\n * @render Basic\n * ```html\n * <div style=\"margin: 200px; display: flex; justify-content: center; align-items: center;\">\n * <nys-button id=\"my-trigger-id\" label=\"Open Menu\"></nys-button>\n * <nys-dropdownmenu id=\"my-dropdownmenu\" for=\"my-trigger-id\">\n * <nys-dropdownmenuitem label=\"Profile\" href=\"/profile\"></nys-dropdownmenuitem>\n * <nys-dropdownmenuitem label=\"Repositories & Github Pages\" href=\"/repos\"></nys-dropdownmenuitem>\n * <nys-dropdownmenuitem label=\"Organizations\" href=\"/organizations\"></nys-dropdownmenuitem>\n * <nys-dropdownmenuitem label=\"Sign out\" href=\"/logout\"></nys-dropdownmenuitem>\n * </nys-dropdownmenu>\n * </div>\n * ```\n */\n\nexport class NysDropdownMenu extends NysElement {\n static styles = unsafeCSS(styles);\n\n @property({ type: String, reflect: true }) for = \"\";\n @property({ type: Boolean }) showDropdown = false;\n\n /**\n * Accessible label for the menu (`role=\"menu\"`) container. Used as `aria-label`\n * on the `<ul role=\"menu\">` element. When empty, falls back to \"Menu\" so the\n * menu always has an accessible name for screen readers.\n * @default \"\"\n */\n @property({ type: String }) label = \"\";\n\n /**\n * Preferred position relative to trigger.\n * @default \"bottom-end\"\n */\n @property({ type: String, reflect: true }) position: Position | null = null;\n\n private _trigger: HTMLElement | null = null;\n private _menuElement: HTMLElement | null = null;\n private _ariaTarget: HTMLElement | null = null;\n private _lastFocusedIndex: number = 0;\n private readonly GAP = 4;\n private _resizeObserver: ResizeObserver | null = null;\n\n /**\n * Lifecycle Methods\n * --------------------------------------------------------------------------\n */\n\n constructor() {\n super();\n }\n\n // super.connectedCallback() (NysElement) auto-assigns this.id when\n // one is not provided (prefix = localName, i.e. \"nys-dropdownmenu-<ts>-<n>\").\n // The menu/menuitem roles intentionally stay on the inner <ul>/items, so this\n // component keeps defaultRole = null and does not move a role onto the host.\n connectedCallback() {\n super.connectedCallback();\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n }\n\n async firstUpdated() {\n await this.updateComplete;\n this.applyInverseTransform();\n this._connectTrigger();\n this._handleMenuClick();\n }\n /**\n * Functions\n * --------------------------------------------------------------------------\n */\n\n private _findTrigger() {\n const targetId = this.for;\n if (!targetId) return null;\n\n // lightDOM search\n let htmlElement = document.getElementById(targetId);\n if (htmlElement) return htmlElement;\n\n // Search recursively through shadow DOMs (e.g. for nys-label within other component's shadowDOM)\n const findInShadows = (root: ParentNode): HTMLElement | null => {\n for (const el of Array.from(root.querySelectorAll(\"*\"))) {\n const shadowElement = el.shadowRoot;\n if (shadowElement) {\n const found = shadowElement.getElementById(targetId);\n if (found) return found;\n\n const deeper = findInShadows(shadowElement);\n if (deeper) return deeper;\n }\n }\n return null;\n };\n\n return findInShadows(document);\n }\n\n private _connectTrigger() {\n const trigger = this._findTrigger();\n if (!trigger) return;\n\n this._trigger = trigger;\n\n const ariaTarget =\n trigger.tagName.toLowerCase() === \"nys-button\"\n ? (trigger.shadowRoot?.querySelector(\"button\") ?? trigger)\n : trigger;\n\n ariaTarget.setAttribute(\"aria-haspopup\", \"menu\");\n ariaTarget.setAttribute(\"aria-expanded\", \"false\");\n\n this._ariaTarget = ariaTarget;\n\n this._trigger.addEventListener(\"click\", this._toggleDropdown);\n this._trigger.addEventListener(\"keydown\", this._handleTriggerKeydown);\n }\n\n private _toggleDropdown = async () => {\n this.showDropdown = !this.showDropdown;\n\n this._ariaTarget?.setAttribute(\"aria-expanded\", String(this.showDropdown));\n\n if (this.showDropdown) {\n window.addEventListener(\"scroll\", this._handleWindowScroll, true);\n this._resizeObserver = new ResizeObserver(() => {\n if (this.showDropdown) {\n this._positionMenu();\n }\n });\n this._resizeObserver.observe(document.documentElement);\n\n document.addEventListener(\"click\", this._handleDocumentClick);\n\n this._menuElement = this.shadowRoot?.querySelector(\n \".nys-dropdownmenu\",\n ) as HTMLElement | null;\n this._menuElement!.addEventListener(\"keydown\", this._handleMenuKeydown);\n\n await this.updateComplete;\n this._positionMenu();\n this._focusOnItem(this._lastFocusedIndex);\n } else {\n window.removeEventListener(\"scroll\", this._handleWindowScroll, true);\n document.removeEventListener(\"click\", this._handleDocumentClick);\n this._menuElement!.removeEventListener(\n \"keydown\",\n this._handleMenuKeydown,\n );\n\n this._resizeObserver?.disconnect();\n this._resizeObserver = null;\n }\n };\n\n private _closeDropdown() {\n this.showDropdown = false;\n this._ariaTarget?.setAttribute(\"aria-expanded\", \"false\");\n this._trigger?.focus();\n }\n\n private _getMenuItems(): HTMLElement[] {\n const slot = this.shadowRoot?.querySelector(\"slot\");\n const assigned = slot?.assignedElements({ flatten: true }) || [];\n\n return assigned.filter(\n (el) => el && !el.hasAttribute(\"disabled\"),\n ) as HTMLElement[];\n }\n\n private _handleDocumentClick = (event: MouseEvent) => {\n if (!this.showDropdown) return;\n\n const path = event?.composedPath();\n\n const clickedInsideMenu = path.includes(this);\n const clickedTrigger = this._trigger && path.includes(this._trigger);\n\n if (!clickedInsideMenu && !clickedTrigger) {\n this._closeDropdown();\n }\n };\n\n private async _focusOnItem(index: number = 0) {\n await new Promise((resolve) => requestAnimationFrame(resolve));\n const items = this._getMenuItems();\n const target = items[Math.min(index, items.length - 1)];\n if (!target) return;\n\n target.focus();\n }\n\n // In some iframes (like Storybook's) or embedded containers , parent elements may have CSS transforms applied, creating a new coordinate context.\n // This function removes such transforms to prevent them from affecting tooltip positioning calculations.\n private applyInverseTransform() {\n document.querySelectorAll('div[scale=\"1\"]').forEach((el) => {\n (el as HTMLElement).style.transform = \"none\";\n });\n }\n\n /**\n * Position Logic\n * --------------------------------------------------------------------------\n */\n\n /**\n * The controller function for positioning the dropdown menu.\n * The logic diverts to if user sets position or we auto position the dropdown menu\n */\n private _positionMenu() {\n if (!this._trigger) return;\n\n this._menuElement = this.shadowRoot?.querySelector(\n \".nys-dropdownmenu\",\n ) as HTMLElement | null;\n if (!this._menuElement) return;\n\n // Decide position based on user preference OR auto position if no position chosen\n const finalPosition = this.position\n ? this._setUserPosition(this.position)\n : this._autoPosition();\n\n // Apply the calculated position\n const coords = this._calculateCoordinates(finalPosition);\n this._applyPosition(coords);\n }\n\n private _setUserPosition(userPosition: Position): Position {\n const space = this._checkSpaceAvailable();\n const menuRect = this._menuElement!.getBoundingClientRect();\n\n const userPositionFits = this._checkPositionFits(\n userPosition,\n space,\n menuRect,\n );\n\n if (userPositionFits) {\n return userPosition;\n }\n\n // User position doesn't fit, find best alternative\n return this._findBestAlternative(userPosition, space, menuRect);\n }\n\n /**\n * Auto Positioning of the dropdown menu relies on the best surrounding space available\n * to select the desirable position.\n */\n private _autoPosition(): Position {\n const space = this._checkSpaceAvailable();\n const menuRect = this._menuElement!.getBoundingClientRect();\n\n const defaultPosition: Position = \"bottom-end\";\n\n if (this._checkPositionFits(defaultPosition, space, menuRect)) {\n return defaultPosition;\n }\n\n return this._findBestAlternative(defaultPosition, space, menuRect);\n }\n\n /**\n * Checks if the dropdown menu fits inside the viewport on the given side of the trigger.\n * Overrides user set position for auto-positioning if user's desire space is not available\n */\n private _checkSpaceAvailable(): SpaceAvailable {\n if (!this._trigger) {\n return { top: 0, bottom: 0, start: 0, end: 0 };\n }\n\n const triggerRect = this._trigger.getBoundingClientRect();\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n\n return {\n top: triggerRect.top,\n bottom: viewportHeight - triggerRect.bottom,\n start: triggerRect.left,\n end: viewportWidth - triggerRect.right,\n };\n }\n\n private _checkPositionFits(\n position: Position,\n space: SpaceAvailable,\n menuRect: DOMRect,\n ): boolean {\n const menuWidth = menuRect.width;\n const menuHeight = menuRect.height;\n\n const [vertical, horizontal] = position.split(\"-\") as [\n \"top\" | \"bottom\",\n \"start\" | \"end\",\n ];\n\n const verticalFits =\n vertical === \"bottom\"\n ? space.bottom >= menuHeight + this.GAP\n : space.top >= menuHeight + this.GAP;\n\n const horizontalFits =\n horizontal === \"start\"\n ? space.end >= menuWidth\n : space.start >= menuWidth;\n return verticalFits && horizontalFits;\n }\n\n /**\n * This position is called for when user's set position didn't fit OR auto positioning when default position doesn't fit\n * We look for the best alternative positions in order of preference base on the set position (e.g. bottom-start => bottom-end).\n * @param userPosition\n * @param space\n * @param menuRect\n */\n private _findBestAlternative(\n userPosition: Position,\n space: SpaceAvailable,\n menuRect: DOMRect,\n ): Position {\n const [vertical, horizontal] = userPosition.split(\"-\") as [\n \"top\" | \"bottom\",\n \"start\" | \"end\",\n ];\n\n const alternatives: Position[] = [\n `${vertical === \"bottom\" ? \"top\" : \"bottom\"}-${horizontal}`, // Flip vertical\n `${vertical}-${horizontal === \"start\" ? \"end\" : \"start\"}`, // Flip horizontal\n `${vertical === \"bottom\" ? \"top\" : \"bottom\"}-${horizontal === \"start\" ? \"end\" : \"start\"}`, // Flip both\n ];\n\n for (const altPosition of alternatives) {\n if (this._checkPositionFits(altPosition, space, menuRect)) {\n return altPosition;\n }\n }\n\n // Fallback: nothing fits, return position with most space\n return this._findMostAvailableSpace(space) as Position;\n }\n\n private _findMostAvailableSpace(space: SpaceAvailable): Position {\n const vertical = space.bottom >= space.top ? \"bottom\" : \"top\";\n const horizontal = space.start >= space.end ? \"start\" : \"end\";\n\n return `${vertical}-${horizontal}`;\n }\n\n /**\n * A valid ideal position has been chosen.\n * This function calculates the coordinate of the trigger to properly position the dropdown menu.\n * @param position\n * @returns\n */\n private _calculateCoordinates(position: Position): PositionCoordinates {\n if (!this._trigger || !this._menuElement) {\n return { top: 0, left: 0 };\n }\n\n const triggerRect = this._trigger.getBoundingClientRect();\n const menuRect = this._menuElement.getBoundingClientRect();\n\n const [vertical, horizontal] = position.split(\"-\") as [\n \"top\" | \"bottom\",\n \"start\" | \"end\",\n ];\n\n let top = 0;\n let left = 0;\n\n // Vertical position\n if (vertical === \"bottom\") {\n top = triggerRect.bottom + this.GAP;\n } else {\n top = triggerRect.top - menuRect.height - this.GAP;\n }\n\n // Horizontal position\n if (horizontal === \"start\") {\n left = triggerRect.left;\n } else {\n left = triggerRect.right - menuRect.width;\n }\n\n return { top, left };\n }\n\n private _applyPosition(coords: PositionCoordinates) {\n if (!this._menuElement) return;\n\n this._menuElement.style.top = `${coords.top}px`;\n this._menuElement.style.left = `${coords.left}px`;\n }\n\n /**\n * Event Handlers\n * --------------------------------------------------------------------------\n */\n\n private _handleMenuClick() {\n this.addEventListener(\"nys-click\", (e: Event) => {\n const items = this._getMenuItems();\n const targetCrumb = (e as CustomEvent).detail?.id;\n const index = items.findIndex((item) => item.id === targetCrumb);\n if (index !== -1) this._lastFocusedIndex = index;\n this._closeDropdown();\n });\n }\n\n private _handleTriggerKeydown = (event: KeyboardEvent) => {\n if (event.defaultPrevented) return;\n\n if (event.key === \"Escape\" && this.showDropdown) {\n event.preventDefault();\n this._closeDropdown();\n }\n };\n\n private _handleMenuKeydown = (event: KeyboardEvent) => {\n const items = this._getMenuItems();\n const currentIndex = items.indexOf(document.activeElement as HTMLElement);\n\n switch (event.key) {\n case \"Escape\":\n event.preventDefault();\n this._closeDropdown();\n break;\n case \"ArrowDown\":\n case \"ArrowRight\":\n event.preventDefault();\n const nextIndex =\n currentIndex < items.length - 1 ? currentIndex + 1 : 0;\n this._lastFocusedIndex = nextIndex;\n items[nextIndex].focus();\n break;\n case \"ArrowUp\":\n case \"ArrowLeft\":\n event.preventDefault();\n const prevIndex =\n currentIndex > 0 ? currentIndex - 1 : items.length - 1;\n this._lastFocusedIndex = prevIndex;\n items[prevIndex].focus();\n break;\n case \"Tab\":\n if (currentIndex >= items.length - 1 && !event.shiftKey) {\n this._closeDropdown();\n }\n break;\n default:\n break;\n }\n };\n\n private _handleWindowScroll = () => {\n if (this.showDropdown) {\n this._positionMenu();\n }\n };\n\n render() {\n return html`<div\n class=\"nys-dropdownmenu ${this.showDropdown ? \"active\" : \"\"}\"\n for=${this.for}\n ?hidden=${!this.showDropdown}\n >\n <ul role=\"menu\" aria-label=${this.label || \"Menu\"}>\n <slot></slot>\n </ul>\n </div>`;\n }\n}\n\nif (!customElements.get(\"nys-dropdownmenu\")) {\n customElements.define(\"nys-dropdownmenu\", NysDropdownMenu);\n}\n"],"names":["LitElement","unsafeCSS","html","property","y","f","e","b","t","P","u","_NysDropdownMenuItem","NysElement","isLink","styles","NysDropdownMenuItem","__decorateClass","_NysDropdownMenu","event","path","clickedInsideMenu","clickedTrigger","items","currentIndex","nextIndex","prevIndex","targetId","htmlElement","findInShadows","root","el","shadowElement","found","deeper","trigger","ariaTarget","index","resolve","target","finalPosition","coords","userPosition","space","menuRect","defaultPosition","triggerRect","viewportWidth","viewportHeight","position","menuWidth","menuHeight","vertical","horizontal","verticalFits","horizontalFits","alternatives","altPosition","top","left","targetCrumb","item","NysDropdownMenu"],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { NysElement } from "@nysds/internals";
2
+ import "@nysds/nys-icon";
3
+ /**
4
+ * **Slotted component.** Displays an individual dropdown item within `nys-dropdown` with label.
5
+ *
6
+ * The `nys-dropdownitem` is used as customizable item within the dropdown so users don't have to raw code <ul>, <li>, <a href>
7
+ * and have the benefit of default customization.
8
+ *
9
+ * @summary Dropdown item to display label and provide href link.
10
+ * @element nys-dropdownmenuitem
11
+ */
12
+ export declare class NysDropdownMenuItem extends NysElement {
13
+ static styles: import("lit").CSSResult;
14
+ static shadowRootOptions: {
15
+ delegatesFocus: boolean;
16
+ clonable?: boolean;
17
+ customElementRegistry?: CustomElementRegistry;
18
+ mode: ShadowRootMode;
19
+ serializable?: boolean;
20
+ slotAssignment?: SlotAssignmentMode;
21
+ };
22
+ label: string;
23
+ href: string;
24
+ disabled: boolean;
25
+ target: string;
26
+ prefixIcon: string;
27
+ divider: string;
28
+ connectedCallback(): void;
29
+ private _handleClick;
30
+ render(): import("lit-html").TemplateResult<1>;
31
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nysds/nys-dropdownmenu",
3
- "version": "1.19.4",
3
+ "version": "1.20.1",
4
4
  "description": "The Dropdownmenu component from the NYS Design System.",
5
5
  "module": "dist/nys-dropdownmenu.js",
6
6
  "types": "dist/index.d.ts",
@@ -23,9 +23,10 @@
23
23
  "lit-analyze": "lit-analyzer 'src/**/*.ts'"
24
24
  },
25
25
  "dependencies": {
26
- "@nysds/nys-icon": "^1.19.4"
26
+ "@nysds/nys-icon": "^1.20.1"
27
27
  },
28
28
  "devDependencies": {
29
+ "@nysds/internals": "^1.20.1",
29
30
  "lit": "^3.3.1",
30
31
  "typescript": "^5.9.3",
31
32
  "vite": "^7.3.1"