@nysds/nys-combobox 1.15.0
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/dist/nys-combobox.js +472 -0
- package/dist/nys-combobox.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
import { LitElement as v, unsafeCSS as x, html as h } from "lit";
|
|
2
|
+
import { property as l, state as d, query as y } from "lit/decorators.js";
|
|
3
|
+
import { ifDefined as m } from "lit/directives/if-defined.js";
|
|
4
|
+
/*!
|
|
5
|
+
* █▄ █ █ █ █▀▀▀█ █▀▀▄ █▀▀▀█
|
|
6
|
+
* █ █ █ █▄▄▄█ ▀▀▀▄▄ █ █ ▀▀▀▄▄
|
|
7
|
+
* █ ▀█ █ █▄▄▄█ █▄▄▀ █▄▄▄█
|
|
8
|
+
*
|
|
9
|
+
* Combobox Component
|
|
10
|
+
* Part of the New York State Design System
|
|
11
|
+
* Repository: https://github.com/its-hcd/nysds
|
|
12
|
+
* License: MIT
|
|
13
|
+
*/
|
|
14
|
+
const g = ':host{--_nys-combobox-width: 100%;--_nys-combobox-height: var(--nys-size-500, 40px);--_nys-combobox-border-radius: var(--nys-radius-md, 4px);--_nys-combobox-border-width: var(--nys-border-width-sm, 1px);--_nys-combobox-border-color: var(--nys-color-neutral-400, #909395);--_nys-combobox-color: var(--nys-color-text, var(--nys-color-neutral-900, #1b1b1b));--_nys-combobox-padding: var(--nys-space-100, 8px) var(--nys-space-150, 12px);--_nys-combobox-gap: var(--nys-space-50, 4px);--_nys-combobox-background-color: var(--nys-color-ink-reverse, var(--nys-color-white, #ffffff));--_nys-combobox-outline-color--hover: var(--nys-color-neutral-900, #1b1b1b);--_nys-combobox-outline-width: var(--nys-border-width-sm, 1px);--_nys-combobox-outline-color--focus: var(--nys-color-focus, #004dd1);--_nys-combobox-background-color--disabled: var(--nys-color-neutral-10, #f6f6f6);--_nys-combobox-border-color--disabled: var(--nys-color-neutral-200, #bec0c1);--_nys-combobox-color--disabled: var(--nys-color-text-disabled, var(--nys-color-neutral-200, #bec0c1));--_nys-combobox-background-color--dropdown: var(--nys-color-ink-reverse, var(--nys-color-white, #ffffff));--_nys-combobox-border-color--dropdown: var(--nys-color-neutral-400, #909395);--_nys-combobox-shadow--dropdown: var(--nys-shadow-lg, 0 4px 8px rgba(0, 0, 0, .1));--_nys-combobox-max-height--dropdown: var(--nys-size-3000, 300px);--_nys-combobox-padding--option: var(--nys-space-100, 8px) var(--nys-space-150, 12px);--_nys-combobox-background-color--option--hover: var(--nys-color-neutral-10, #f6f6f6);--_nys-combobox-background-color--option--active: var(--nys-color-neutral-50, #ededed);--_nys-combobox-background-color--option--disabled: var(--nys-color-white, #ffffff);--_nys-combobox-color--option--disabled: var(--nys-color-text-disabled, #bec0c1);--_nys-combobox-background-color--option--selected: var(--nys-theme-weaker, #eff6fb);--_nys-combobox-border-color--option--selected: var(--nys-color-theme-mid, #457aa5);--_nys-combobox-font-family: var(--nys-font-family-ui, var(--nys-font-family-sans, "Proxima Nova", "Helvetica Neue", "Helvetica", "Arial", sans-serif));--_nys-combobox-font-size: var(--nys-font-size-ui-md, 16px);--_nys-combobox-font-weight: var(--nys-font-weight-regular, 400);--_nys-combobox-line-height: var(--nys-font-lineheight-ui-md, 24px);--_nys-combobox-letter-spacing: var(--nys-font-letterspacing-ui-md, var(--nys-font-letterspacing-400, .044px))}:host([width=sm]){--_nys-combobox-width: var(--nys-form-width-sm, 88px)}:host([width=md]){--_nys-combobox-width: var(--nys-form-width-md, 200px)}:host([width=lg]){--_nys-combobox-width: var(--nys-form-width-lg, 384px)}:host([width=full]){--_nys-combobox-width: 100%;flex:1}:host([showError]){--_nys-combobox-border-color: var(--nys-color-danger, #b52c2c)}.nys-combobox{font-weight:var(--_nys-combobox-font-weight);font-family:var(--_nys-combobox-font-family);font-size:var(--_nys-combobox-font-size);line-height:var(--_nys-combobox-line-height);letter-spacing:var(--_nys-combobox-letter-spacing);color:var(--_nys-combobox-color);gap:var(--_nys-combobox-gap);display:flex;flex-direction:column;position:relative}.nys-combobox__container{width:var(--_nys-combobox-width);max-width:100%;position:relative}.nys-combobox__input-wrapper{position:relative;display:flex;align-items:center;background-color:var(--_nys-combobox-background-color);border-radius:var(--_nys-combobox-border-radius)}.nys-combobox__input{color:var(--_nys-combobox-color);border-radius:var(--_nys-combobox-border-radius);border:solid var(--_nys-combobox-border-color) var(--_nys-combobox-border-width);outline-color:transparent;outline-width:var(--_nys-combobox-outline-width);outline-style:solid;padding:var(--_nys-combobox-padding);padding-right:calc(var(--nys-size-400, 32px) + var(--nys-space-100, 8px));width:100%;height:var(--_nys-combobox-height);box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;background-color:transparent;font:inherit;cursor:text}.nys-combobox__input:not(:placeholder-shown){padding-right:calc(var(--nys-size-400, 32px) * 2 + var(--nys-space-100, 8px))}.nys-combobox__input:hover:not(:disabled):not(:focus):not([readonly]){outline-color:var(--_nys-combobox-outline-color--hover);border-color:var(--_nys-combobox-outline-color--hover)}.nys-combobox__input:focus:not([readonly]){outline-color:var(--_nys-combobox-outline-color--focus);border-color:var(--_nys-combobox-outline-color--focus);caret-color:var(--_nys-combobox-outline-color--focus)}.nys-combobox__input:disabled{background-color:var(--_nys-combobox-background-color--disabled);border-color:var(--_nys-combobox-border-color--disabled);color:var(--_nys-combobox-color--disabled);cursor:not-allowed}.nys-combobox__buttons{display:flex;position:absolute;right:var(--nys-space-150, 12px);gap:var(--nys-space-150, 12px)}.nys-combobox__buttons nys-button{--_nys-button-padding--y: var(--nys-space-50, 4px);--_nys-button-padding--x: var(--nys-space-50, 4px);--_nys-button-height: var(--nys-size-300, 32px);--_nys-button-width: var(--nys-size-400, 32px)}.nys-combobox__buttons .nys-combobox__chevron{border-inline-start:solid var(--nys-color-neutral-200, #bec0c1) var(--nys-border-width-sm, 1px);padding-inline-start:var(--nys-space-150, 12px)}.nys-combobox__listbox{position:absolute;left:0;right:0;top:calc(100% + var(--nys-space-50, 4px));background-color:var(--_nys-combobox-background-color--dropdown);border:solid var(--_nys-combobox-border-color--dropdown) var(--_nys-combobox-border-width);border-radius:var(--_nys-combobox-border-radius);box-shadow:var(--_nys-combobox-shadow--dropdown);max-height:var(--_nys-combobox-max-height--dropdown);overflow-y:auto;z-index:1000;box-sizing:border-box}.nys-combobox__listbox--above{top:auto;bottom:calc(100% + var(--nys-space-50, 4px))}.nys-combobox__option{padding:var(--_nys-combobox-padding--option);cursor:pointer;-webkit-user-select:none;user-select:none;transition:background-color .15s ease;border-bottom:var(--nys-border-width-sm, 1px) solid var(--nys-color-neutral-50, #ededed);background-color:var(--_nys-combobox-background-color)}.nys-combobox__option:hover:not([disabled]):not(.nys-combobox__option--selected){background-color:var(--_nys-combobox-background-color--option--hover)}.nys-combobox__option:active:not([disabled]):not(.nys-combobox__option--selected){background-color:var(--_nys-combobox-background-color--option--active)}.nys-combobox__option--selected:not([disabled]){background-color:var(--_nys-combobox-background-color--option--selected);border:var(--_nys-combobox-border-color--option--selected) solid 1px}.nys-combobox__option--focused:not([disabled]):not(:hover){outline:var(--_nys-combobox-outline-color--focus) solid 2px;outline-offset:-2px}.nys-combobox__option[disabled]{background-color:var(--_nys-combobox-background-color--option--disabled);color:var(--_nys-combobox-color--option--disabled);cursor:not-allowed}.nys-combobox__optgroup{padding:var(--nys-space-100, 8px) var(--nys-space-150, 12px);border-bottom:var(--nys-border-width-sm, 1px) solid var(--nys-color-neutral-50, #ededed);-webkit-user-select:none;user-select:none;color:var(--nys-color-text);font-family:var(--nys-font-family-ui, "Proxima Nova");font-size:var(--nys-font-size-ui-md, 16px);font-style:normal;font-weight:700;line-height:var(--nys-font-lineheight-ui-md, 24px);letter-spacing:var(--nys-font-letterspacing-ui-md, .044px)}.nys-combobox__optgroup~.nys-combobox__option{padding-left:var(--nys-space-300, 24px)}.nys-combobox__no-results{background-color:var(--_nys-combobox-background-color);padding:var(--_nys-combobox-padding--option);color:var(--_nys-combobox-color);cursor:not-allowed}.nys-combobox__listbox::-webkit-scrollbar{width:var(--nys-space-100, 8px)}.nys-combobox__listbox::-webkit-scrollbar-track{background:var(--nys-color-neutral-50, #eeeeee);border-radius:var(--_nys-combobox-border-radius)}.nys-combobox__listbox::-webkit-scrollbar-thumb{background:var(--nys-color-neutral-300, #a7a9ab);border-radius:var(--_nys-combobox-border-radius)}.nys-combobox__listbox::-webkit-scrollbar-thumb:hover{background:var(--nys-color-neutral-400, #909395)}';
|
|
15
|
+
var w = Object.defineProperty, r = (u, o, s, e) => {
|
|
16
|
+
for (var t = void 0, n = u.length - 1, a; n >= 0; n--)
|
|
17
|
+
(a = u[n]) && (t = a(o, s, t) || t);
|
|
18
|
+
return t && w(o, s, t), t;
|
|
19
|
+
};
|
|
20
|
+
let k = 0;
|
|
21
|
+
const _ = class _ extends v {
|
|
22
|
+
constructor() {
|
|
23
|
+
super(), this.id = "", this.name = "", this.label = "", this.description = "", this.value = "", this.disabled = !1, this.required = !1, this.optional = !1, this.tooltip = "", this.form = null, this.width = "full", this.inverted = !1, this.showError = !1, this.errorMessage = "", this._isOpen = !1, this._filterText = "", this._highlightedIndex = -1, this._options = [], this._filteredOptions = [], this._dropdownAbove = !1, this._announcement = "", this._originalErrorMessage = "", this._hasUserInteracted = !1, this._selectedLabel = "", this._defaultValue = "", this._handleDocumentClick = (o) => {
|
|
24
|
+
o.target === this || this.shadowRoot?.contains(o.target) || this._closeDropdown();
|
|
25
|
+
}, this._internals = this.attachInternals();
|
|
26
|
+
}
|
|
27
|
+
connectedCallback() {
|
|
28
|
+
super.connectedCallback(), this.id || (this.id = `nys-combobox-${Date.now()}-${k++}`), this._originalErrorMessage = this.errorMessage ?? "", this.addEventListener("invalid", this._handleInvalid), document.addEventListener("click", this._handleDocumentClick);
|
|
29
|
+
}
|
|
30
|
+
disconnectedCallback() {
|
|
31
|
+
super.disconnectedCallback(), this.removeEventListener("invalid", this._handleInvalid), document.removeEventListener("click", this._handleDocumentClick);
|
|
32
|
+
}
|
|
33
|
+
firstUpdated() {
|
|
34
|
+
this._handleSlotChange();
|
|
35
|
+
const o = this.shadowRoot?.querySelector(
|
|
36
|
+
'slot:not([name="description"])'
|
|
37
|
+
);
|
|
38
|
+
if (!this.value && o) {
|
|
39
|
+
const s = o.assignedElements({ flatten: !0 });
|
|
40
|
+
for (const e of s)
|
|
41
|
+
if (e.tagName === "OPTION" && e.selected) {
|
|
42
|
+
this.value = e.value;
|
|
43
|
+
break;
|
|
44
|
+
} else if (e.tagName === "OPTGROUP") {
|
|
45
|
+
for (const t of e.children)
|
|
46
|
+
if (t.tagName === "OPTION" && t.selected) {
|
|
47
|
+
this.value = t.value;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
if (this.value) break;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
this._setValue(), this._defaultValue = this.value;
|
|
54
|
+
}
|
|
55
|
+
updated(o) {
|
|
56
|
+
if (o.has("value")) {
|
|
57
|
+
const s = this._options.find((e) => e.value === this.value);
|
|
58
|
+
this._selectedLabel = s ? s.label : "", this._filterText = this._selectedLabel;
|
|
59
|
+
}
|
|
60
|
+
o.has("_isOpen") && this._isOpen && (this._positionDropdown(), this.updateComplete.then(() => {
|
|
61
|
+
this._scrollToHighlighted();
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Slot handling
|
|
66
|
+
* --------------------------------------------------------------------------
|
|
67
|
+
*/
|
|
68
|
+
_handleSlotChange() {
|
|
69
|
+
const o = this.shadowRoot?.querySelector(
|
|
70
|
+
'slot:not([name="description"])'
|
|
71
|
+
);
|
|
72
|
+
if (!o) return;
|
|
73
|
+
const s = o.assignedElements({ flatten: !0 }), e = [];
|
|
74
|
+
if (s.forEach((t) => {
|
|
75
|
+
if (t.tagName === "OPTION") {
|
|
76
|
+
const n = t;
|
|
77
|
+
e.push({
|
|
78
|
+
value: n.value,
|
|
79
|
+
label: n.textContent?.trim() || n.value,
|
|
80
|
+
disabled: n.disabled
|
|
81
|
+
});
|
|
82
|
+
} else if (t.tagName === "OPTGROUP") {
|
|
83
|
+
const n = t, a = n.label;
|
|
84
|
+
Array.from(n.children).forEach((p) => {
|
|
85
|
+
if (p.tagName === "OPTION") {
|
|
86
|
+
const c = p;
|
|
87
|
+
e.push({
|
|
88
|
+
value: c.value,
|
|
89
|
+
label: c.textContent?.trim() || c.value,
|
|
90
|
+
disabled: c.disabled || n.disabled,
|
|
91
|
+
group: a
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}), this._options = e, this._filteredOptions = e, this.value) {
|
|
97
|
+
const t = this._options.find((n) => n.value === this.value);
|
|
98
|
+
t && (this._selectedLabel = t.label, this._filterText = t.label);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Form Integration
|
|
103
|
+
* --------------------------------------------------------------------------
|
|
104
|
+
*/
|
|
105
|
+
_setValue() {
|
|
106
|
+
this._internals.setFormValue(this.value), this._manageRequire();
|
|
107
|
+
}
|
|
108
|
+
_manageRequire() {
|
|
109
|
+
const o = this.errorMessage || "This field is required";
|
|
110
|
+
this.required && (!this.value || this.value?.trim() === "") ? (this._internals.ariaRequired = "true", this._internals.setValidity({ valueMissing: !0 }, o, this._input)) : (this._internals.ariaRequired = "false", this._internals.setValidity({}), this._hasUserInteracted = !1);
|
|
111
|
+
}
|
|
112
|
+
_setValidityMessage(o = "") {
|
|
113
|
+
this.showError = !!o, this._originalErrorMessage?.trim() && o !== "" ? this.errorMessage = this._originalErrorMessage : this.errorMessage = o;
|
|
114
|
+
const s = o ? { customError: !0 } : {};
|
|
115
|
+
this._internals.setValidity(s, this.errorMessage, this._input);
|
|
116
|
+
}
|
|
117
|
+
_validate() {
|
|
118
|
+
if (!this._input) return;
|
|
119
|
+
const o = this._input.validity;
|
|
120
|
+
let s = "";
|
|
121
|
+
o.valueMissing ? s = "This field is required" : s = this._input.validationMessage, this._setValidityMessage(s);
|
|
122
|
+
}
|
|
123
|
+
formResetCallback() {
|
|
124
|
+
this.value = this._defaultValue, this._filterText = this._defaultValue ? this._options.find((o) => o.value === this._defaultValue)?.label ?? "" : "", this._selectedLabel = this._filterText, this._input && (this._input.value = this._filterText), this._internals.setFormValue(this.value), this.showError = !1, this.errorMessage = "", this._internals.setValidity({}), this.requestUpdate();
|
|
125
|
+
}
|
|
126
|
+
checkValidity() {
|
|
127
|
+
return this._input ? this._input.checkValidity() : !0;
|
|
128
|
+
}
|
|
129
|
+
_handleInvalid(o) {
|
|
130
|
+
if (o.preventDefault(), this._hasUserInteracted = !0, this._validate(), this._input) {
|
|
131
|
+
const s = this._internals.form;
|
|
132
|
+
s ? Array.from(s.elements).find(
|
|
133
|
+
(n) => typeof n.checkValidity == "function" && !n.checkValidity()
|
|
134
|
+
) === this && this._input.focus() : this._input.focus();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Dropdown positioning
|
|
139
|
+
* --------------------------------------------------------------------------
|
|
140
|
+
*/
|
|
141
|
+
_positionDropdown() {
|
|
142
|
+
if (!this._listbox || !this._input) return;
|
|
143
|
+
const o = this._input.getBoundingClientRect(), s = this._listbox.offsetHeight, t = window.innerHeight - o.bottom, n = o.top;
|
|
144
|
+
this._dropdownAbove = t < s && n > t;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Filtering
|
|
148
|
+
* --------------------------------------------------------------------------
|
|
149
|
+
*/
|
|
150
|
+
_filterOptions(o) {
|
|
151
|
+
if (!o) {
|
|
152
|
+
this._filteredOptions = this._options;
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const s = o.toLowerCase();
|
|
156
|
+
this._filteredOptions = this._options.filter(
|
|
157
|
+
(e) => e.label.toLowerCase().includes(s)
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Keyboard navigation
|
|
162
|
+
* --------------------------------------------------------------------------
|
|
163
|
+
*/
|
|
164
|
+
_scrollToHighlighted() {
|
|
165
|
+
if (!this._listbox || this._highlightedIndex < 0) return;
|
|
166
|
+
const o = this._listbox.querySelector(
|
|
167
|
+
`[data-index="${this._highlightedIndex}"]`
|
|
168
|
+
);
|
|
169
|
+
o && o.scrollIntoView({ block: "nearest" });
|
|
170
|
+
}
|
|
171
|
+
_handleKeyDown(o) {
|
|
172
|
+
switch (o.key) {
|
|
173
|
+
case "ArrowDown":
|
|
174
|
+
o.preventDefault(), this._isOpen ? this._moveHighlight(1) : this._openDropdown();
|
|
175
|
+
break;
|
|
176
|
+
case "ArrowUp":
|
|
177
|
+
o.preventDefault(), this._isOpen ? this._moveHighlight(-1) : this._openDropdown();
|
|
178
|
+
break;
|
|
179
|
+
case "Enter":
|
|
180
|
+
o.preventDefault(), this._isOpen && this._highlightedIndex >= 0 && this._selectOption(this._filteredOptions[this._highlightedIndex]);
|
|
181
|
+
break;
|
|
182
|
+
case "Escape":
|
|
183
|
+
o.preventDefault(), this._closeDropdown(), this._filterText = this._selectedLabel;
|
|
184
|
+
break;
|
|
185
|
+
case "Tab":
|
|
186
|
+
this._isOpen && (this._closeDropdown(), this._filterText = this._selectedLabel);
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
_moveHighlight(o) {
|
|
191
|
+
if (this._filteredOptions.filter((b) => !b.disabled).length === 0) return;
|
|
192
|
+
let e = this._highlightedIndex + o;
|
|
193
|
+
for (e < 0 ? e = this._filteredOptions.length - 1 : e >= this._filteredOptions.length && (e = 0); this._filteredOptions[e]?.disabled; )
|
|
194
|
+
e += o, e < 0 && (e = this._filteredOptions.length - 1), e >= this._filteredOptions.length && (e = 0);
|
|
195
|
+
this._highlightedIndex = e, this._scrollToHighlighted();
|
|
196
|
+
const t = this._filteredOptions[e], n = this._filteredOptions[e - o], a = this._filteredOptions.filter(
|
|
197
|
+
(b) => !b.disabled
|
|
198
|
+
), p = a.findIndex((b) => b.value === t.value) + 1, c = t.value === this.value ? "selected" : "unselected", f = t.group && t.group !== n?.group ? `${t.group}, ` : "";
|
|
199
|
+
this._announcement = `${f} ${t.label} ${p} of ${a.length}, ${c}`;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Event Handlers
|
|
203
|
+
* --------------------------------------------------------------------------
|
|
204
|
+
*/
|
|
205
|
+
_handleInput(o) {
|
|
206
|
+
const s = o.target;
|
|
207
|
+
this._filterText = s.value, this._filterOptions(this._filterText), this._isOpen || this._openDropdown(), this._highlightedIndex = 0;
|
|
208
|
+
const e = this._filteredOptions.filter((t) => !t.disabled).length;
|
|
209
|
+
this._announcement = e > 0 ? `${e} options available` : "No results found", this._hasUserInteracted && this._validate(), this.dispatchEvent(
|
|
210
|
+
new CustomEvent("nys-input", {
|
|
211
|
+
detail: { id: this.id, value: this._filterText },
|
|
212
|
+
bubbles: !0,
|
|
213
|
+
composed: !0
|
|
214
|
+
})
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
_handleFocus() {
|
|
218
|
+
this.dispatchEvent(new Event("nys-focus"));
|
|
219
|
+
}
|
|
220
|
+
_handleBlur(o) {
|
|
221
|
+
const s = o.relatedTarget;
|
|
222
|
+
s && this._listbox?.contains(s) || ((!this.value || this._filterText !== this._selectedLabel) && (this._filterText = this._selectedLabel, this._filterOptions("")), this._closeDropdown(), this._hasUserInteracted || (this._hasUserInteracted = !0), this._validate(), this.dispatchEvent(new Event("nys-blur")));
|
|
223
|
+
}
|
|
224
|
+
_handleIconClick() {
|
|
225
|
+
this.disabled || (this._isOpen ? this._closeDropdown() : (this._input.focus(), this._openDropdown()));
|
|
226
|
+
}
|
|
227
|
+
_handleClearClick(o) {
|
|
228
|
+
o.stopPropagation(), this.value = "", this._filterText = "", this._selectedLabel = "", this._filterOptions(""), this._internals.setFormValue(""), this._closeDropdown(), this._input.focus(), this._handleChange();
|
|
229
|
+
}
|
|
230
|
+
_handleOptionClick(o) {
|
|
231
|
+
o.disabled || this._selectOption(o);
|
|
232
|
+
}
|
|
233
|
+
_handleOptionMouseEnter(o) {
|
|
234
|
+
this._highlightedIndex = o;
|
|
235
|
+
}
|
|
236
|
+
_selectOption(o) {
|
|
237
|
+
this.value = o.value, this._selectedLabel = o.label, this._filterText = o.label, this._internals.setFormValue(this.value), this._input.focus(), this._closeDropdown(), this._filterOptions(""), this._setValidityMessage(""), this._hasUserInteracted && this._validate(), this._handleChange();
|
|
238
|
+
}
|
|
239
|
+
_handleChange() {
|
|
240
|
+
this.dispatchEvent(
|
|
241
|
+
new CustomEvent("nys-change", {
|
|
242
|
+
detail: { id: this.id, value: this.value },
|
|
243
|
+
bubbles: !0,
|
|
244
|
+
composed: !0
|
|
245
|
+
})
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
_openDropdown() {
|
|
249
|
+
this._isOpen = !0, this._highlightedIndex = this._filteredOptions.findIndex(
|
|
250
|
+
(o) => o.value === this.value
|
|
251
|
+
), this._highlightedIndex < 0 && (this._highlightedIndex = 0);
|
|
252
|
+
}
|
|
253
|
+
_closeDropdown() {
|
|
254
|
+
this._isOpen = !1, this._highlightedIndex = -1;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Render helpers
|
|
258
|
+
* --------------------------------------------------------------------------
|
|
259
|
+
*/
|
|
260
|
+
_renderOptions() {
|
|
261
|
+
let o = "";
|
|
262
|
+
const s = [];
|
|
263
|
+
return this._filteredOptions.forEach((e, t) => {
|
|
264
|
+
e.group && e.group !== o && (o = e.group, s.push(h`
|
|
265
|
+
<div class="nys-combobox__optgroup" role="presentation">
|
|
266
|
+
${e.group}
|
|
267
|
+
</div>
|
|
268
|
+
`));
|
|
269
|
+
const n = t === this._highlightedIndex, a = e.value === this.value;
|
|
270
|
+
s.push(h`
|
|
271
|
+
<div
|
|
272
|
+
class="nys-combobox__option ${n ? "nys-combobox__option--focused" : ""} ${a ? "nys-combobox__option--selected" : ""}"
|
|
273
|
+
role="option"
|
|
274
|
+
id="${this.id}--option-${t}"
|
|
275
|
+
data-index="${t}"
|
|
276
|
+
aria-selected="${a}"
|
|
277
|
+
aria-disabled="${e.disabled || !1}"
|
|
278
|
+
?disabled=${e.disabled}
|
|
279
|
+
@click=${() => this._handleOptionClick(e)}
|
|
280
|
+
@mouseenter=${() => this._handleOptionMouseEnter(t)}
|
|
281
|
+
>
|
|
282
|
+
${e.label}
|
|
283
|
+
</div>
|
|
284
|
+
`);
|
|
285
|
+
}), s.length === 0 ? h`
|
|
286
|
+
<div class="nys-combobox__no-results" role="option">
|
|
287
|
+
No results found
|
|
288
|
+
</div>
|
|
289
|
+
` : s;
|
|
290
|
+
}
|
|
291
|
+
render() {
|
|
292
|
+
return h`
|
|
293
|
+
<div class="nys-combobox">
|
|
294
|
+
<nys-label
|
|
295
|
+
for=${this.id + "--native"}
|
|
296
|
+
label=${this.label}
|
|
297
|
+
description=${this.description}
|
|
298
|
+
flag=${this.required ? "required" : this.optional ? "optional" : ""}
|
|
299
|
+
tooltip=${this.tooltip}
|
|
300
|
+
?inverted=${this.inverted}
|
|
301
|
+
>
|
|
302
|
+
<slot name="description" slot="description">${this.description}</slot>
|
|
303
|
+
</nys-label>
|
|
304
|
+
<div
|
|
305
|
+
class="nys-combobox__container ${this._isOpen ? "nys-combobox__container--open" : ""}"
|
|
306
|
+
>
|
|
307
|
+
<div class="nys-combobox__input-wrapper">
|
|
308
|
+
<input
|
|
309
|
+
class="nys-combobox__input"
|
|
310
|
+
type="text"
|
|
311
|
+
role="combobox"
|
|
312
|
+
aria-autocomplete="list"
|
|
313
|
+
aria-expanded="${this._isOpen}"
|
|
314
|
+
aria-controls="${this.id}--listbox"
|
|
315
|
+
aria-activedescendant="${this._highlightedIndex >= 0 ? `${this.id}--option-${this._highlightedIndex}` : ""}"
|
|
316
|
+
name=${this.name}
|
|
317
|
+
id=${this.id + "--native"}
|
|
318
|
+
?disabled=${this.disabled}
|
|
319
|
+
?required=${this.required}
|
|
320
|
+
aria-required=${this.required}
|
|
321
|
+
aria-disabled="${this.disabled}"
|
|
322
|
+
aria-label="${[this.label, this.description].filter(Boolean).join(" ")}"
|
|
323
|
+
.value=${this._filterText}
|
|
324
|
+
form=${m(this.form || void 0)}
|
|
325
|
+
@input=${this._handleInput}
|
|
326
|
+
@focus="${this._handleFocus}"
|
|
327
|
+
@blur="${this._handleBlur}"
|
|
328
|
+
@keydown="${this._handleKeyDown}"
|
|
329
|
+
/>
|
|
330
|
+
<div class="nys-combobox__buttons">
|
|
331
|
+
${this.value ? h`
|
|
332
|
+
<nys-button
|
|
333
|
+
class="nys-combobox__clear"
|
|
334
|
+
suffixIcon="slotted"
|
|
335
|
+
ariaLabel="clear selection"
|
|
336
|
+
variant="ghost"
|
|
337
|
+
size="sm"
|
|
338
|
+
circle
|
|
339
|
+
@nys-click=${this._handleClearClick}
|
|
340
|
+
?disabled=${this.disabled}
|
|
341
|
+
>
|
|
342
|
+
<nys-icon
|
|
343
|
+
slot="suffix-icon"
|
|
344
|
+
size="20"
|
|
345
|
+
name="close"
|
|
346
|
+
></nys-icon>
|
|
347
|
+
</nys-button>
|
|
348
|
+
` : ""}
|
|
349
|
+
<nys-button
|
|
350
|
+
class="nys-combobox__chevron"
|
|
351
|
+
suffixIcon="slotted"
|
|
352
|
+
ariaLabel="toggle dropdown"
|
|
353
|
+
variant="ghost"
|
|
354
|
+
size="sm"
|
|
355
|
+
circle
|
|
356
|
+
@nys-click=${this._handleIconClick}
|
|
357
|
+
?disabled=${this.disabled}
|
|
358
|
+
>
|
|
359
|
+
<nys-icon
|
|
360
|
+
slot="suffix-icon"
|
|
361
|
+
size="20"
|
|
362
|
+
name="chevron_down"
|
|
363
|
+
></nys-icon>
|
|
364
|
+
</nys-button>
|
|
365
|
+
</div>
|
|
366
|
+
</div>
|
|
367
|
+
${this._isOpen ? h`
|
|
368
|
+
<div
|
|
369
|
+
class="nys-combobox__listbox ${this._dropdownAbove ? "nys-combobox__listbox--above" : ""}"
|
|
370
|
+
id="${this.id}--listbox"
|
|
371
|
+
role="listbox"
|
|
372
|
+
tabindex="-1"
|
|
373
|
+
>
|
|
374
|
+
${this._renderOptions()}
|
|
375
|
+
</div>
|
|
376
|
+
` : ""}
|
|
377
|
+
</div>
|
|
378
|
+
<slot
|
|
379
|
+
style="display: none;"
|
|
380
|
+
@slotchange=${this._handleSlotChange}
|
|
381
|
+
></slot>
|
|
382
|
+
<nys-errormessage
|
|
383
|
+
?showError=${this.showError}
|
|
384
|
+
errorMessage=${this.errorMessage}
|
|
385
|
+
></nys-errormessage>
|
|
386
|
+
<div
|
|
387
|
+
aria-live="polite"
|
|
388
|
+
aria-atomic="true"
|
|
389
|
+
style="position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;"
|
|
390
|
+
>
|
|
391
|
+
${this._announcement}
|
|
392
|
+
</div>
|
|
393
|
+
</div>
|
|
394
|
+
`;
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
_.styles = x(g), _.formAssociated = !0;
|
|
398
|
+
let i = _;
|
|
399
|
+
r([
|
|
400
|
+
l({ type: String, reflect: !0 })
|
|
401
|
+
], i.prototype, "id");
|
|
402
|
+
r([
|
|
403
|
+
l({ type: String, reflect: !0 })
|
|
404
|
+
], i.prototype, "name");
|
|
405
|
+
r([
|
|
406
|
+
l({ type: String })
|
|
407
|
+
], i.prototype, "label");
|
|
408
|
+
r([
|
|
409
|
+
l({ type: String })
|
|
410
|
+
], i.prototype, "description");
|
|
411
|
+
r([
|
|
412
|
+
l({ type: String })
|
|
413
|
+
], i.prototype, "value");
|
|
414
|
+
r([
|
|
415
|
+
l({ type: Boolean, reflect: !0 })
|
|
416
|
+
], i.prototype, "disabled");
|
|
417
|
+
r([
|
|
418
|
+
l({ type: Boolean, reflect: !0 })
|
|
419
|
+
], i.prototype, "required");
|
|
420
|
+
r([
|
|
421
|
+
l({ type: Boolean, reflect: !0 })
|
|
422
|
+
], i.prototype, "optional");
|
|
423
|
+
r([
|
|
424
|
+
l({ type: String })
|
|
425
|
+
], i.prototype, "tooltip");
|
|
426
|
+
r([
|
|
427
|
+
l({ type: String, reflect: !0 })
|
|
428
|
+
], i.prototype, "form");
|
|
429
|
+
r([
|
|
430
|
+
l({ type: String, reflect: !0 })
|
|
431
|
+
], i.prototype, "width");
|
|
432
|
+
r([
|
|
433
|
+
l({ type: Boolean, reflect: !0 })
|
|
434
|
+
], i.prototype, "inverted");
|
|
435
|
+
r([
|
|
436
|
+
l({ type: Boolean, reflect: !0 })
|
|
437
|
+
], i.prototype, "showError");
|
|
438
|
+
r([
|
|
439
|
+
l({ type: String })
|
|
440
|
+
], i.prototype, "errorMessage");
|
|
441
|
+
r([
|
|
442
|
+
d()
|
|
443
|
+
], i.prototype, "_isOpen");
|
|
444
|
+
r([
|
|
445
|
+
d()
|
|
446
|
+
], i.prototype, "_filterText");
|
|
447
|
+
r([
|
|
448
|
+
d()
|
|
449
|
+
], i.prototype, "_highlightedIndex");
|
|
450
|
+
r([
|
|
451
|
+
d()
|
|
452
|
+
], i.prototype, "_options");
|
|
453
|
+
r([
|
|
454
|
+
d()
|
|
455
|
+
], i.prototype, "_filteredOptions");
|
|
456
|
+
r([
|
|
457
|
+
d()
|
|
458
|
+
], i.prototype, "_dropdownAbove");
|
|
459
|
+
r([
|
|
460
|
+
d()
|
|
461
|
+
], i.prototype, "_announcement");
|
|
462
|
+
r([
|
|
463
|
+
y("input")
|
|
464
|
+
], i.prototype, "_input");
|
|
465
|
+
r([
|
|
466
|
+
y(".nys-combobox__listbox")
|
|
467
|
+
], i.prototype, "_listbox");
|
|
468
|
+
customElements.get("nys-combobox") || customElements.define("nys-combobox", i);
|
|
469
|
+
export {
|
|
470
|
+
i as NysCombobox
|
|
471
|
+
};
|
|
472
|
+
//# sourceMappingURL=nys-combobox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nys-combobox.js","sources":["../src/nys-combobox.ts"],"sourcesContent":["import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property, state, query } from \"lit/decorators.js\";\nimport { ifDefined } from \"lit/directives/if-defined.js\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-combobox.scss?inline\";\n\nlet comboboxIdCounter = 0;\n\ninterface ComboboxOption {\n value: string;\n label: string;\n disabled?: boolean;\n group?: string;\n}\n\n/**\n * `<nys-combobox>` is a form-enabled combo box combining text input with a filterable dropdown.\n *\n * Features:\n * - Type to filter options\n * - Keyboard navigation (Arrow keys, Enter, Escape)\n * - Mouse and keyboard interaction\n * - Clears non-selected text on blur\n * - Clear button when value is selected\n * - Integrates with forms via ElementInternals\n * - Supports native <option> and <optgroup> elements\n * - Accessible per W3C ARIA Authoring Practices\n *\n * @slot description - Optional custom description content below the label.\n * @slot default - Options (<option>, <optgroup>) to populate the dropdown\n *\n * @fires nys-change - Fired when selection changes. Detail: `{ id, value }`.\n * @fires nys-input - Fired on input change. Detail: `{ id, value }`.\n * @fires nys-focus - Fired when combobox receives focus.\n * @fires nys-blur - Fired when combobox loses focus.\n */\n\nexport class NysCombobox extends LitElement {\n static styles = unsafeCSS(styles);\n\n @property({ type: String, reflect: true }) id = \"\";\n @property({ type: String, reflect: true }) name = \"\";\n @property({ type: String }) label = \"\";\n @property({ type: String }) description = \"\";\n @property({ type: String }) value = \"\";\n @property({ type: Boolean, reflect: true }) disabled = false;\n @property({ type: Boolean, reflect: true }) required = false;\n @property({ type: Boolean, reflect: true }) optional = false;\n @property({ type: String }) tooltip = \"\";\n @property({ type: String, reflect: true }) form: string | null = null;\n @property({ type: String, reflect: true }) width: \"md\" | \"lg\" | \"full\" =\n \"full\";\n @property({ type: Boolean, reflect: true }) inverted = false;\n @property({ type: Boolean, reflect: true }) showError = false;\n @property({ type: String }) errorMessage = \"\";\n\n @state() private _isOpen = false;\n @state() private _filterText = \"\";\n @state() private _highlightedIndex = -1;\n @state() private _options: ComboboxOption[] = [];\n @state() private _filteredOptions: ComboboxOption[] = [];\n @state() private _dropdownAbove = false;\n @state() private _announcement = \"\";\n\n @query(\"input\") private _input!: HTMLInputElement;\n @query(\".nys-combobox__listbox\") private _listbox?: HTMLElement;\n\n private _originalErrorMessage = \"\";\n private _hasUserInteracted = false;\n private _internals: ElementInternals;\n private _selectedLabel = \"\";\n private _defaultValue = \"\";\n\n /**\n * Lifecycle methods\n * --------------------------------------------------------------------------\n */\n static formAssociated = true;\n\n constructor() {\n super();\n this._internals = this.attachInternals();\n }\n\n connectedCallback() {\n super.connectedCallback();\n if (!this.id) {\n this.id = `nys-combobox-${Date.now()}-${comboboxIdCounter++}`;\n }\n\n this._originalErrorMessage = this.errorMessage ?? \"\";\n this.addEventListener(\"invalid\", this._handleInvalid);\n document.addEventListener(\"click\", this._handleDocumentClick);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener(\"invalid\", this._handleInvalid);\n document.removeEventListener(\"click\", this._handleDocumentClick);\n }\n\n firstUpdated() {\n this._handleSlotChange();\n\n // If a selected option was found and no explicit value was set, use it\n const slot = this.shadowRoot?.querySelector(\n 'slot:not([name=\"description\"])',\n ) as HTMLSlotElement | null;\n\n if (!this.value && slot) {\n const assignedElements = slot.assignedElements({ flatten: true });\n for (const node of assignedElements) {\n if (node.tagName === \"OPTION\" && (node as HTMLOptionElement).selected) {\n this.value = (node as HTMLOptionElement).value;\n break;\n } else if (node.tagName === \"OPTGROUP\") {\n for (const child of (node as HTMLOptGroupElement).children) {\n if (\n child.tagName === \"OPTION\" &&\n (child as HTMLOptionElement).selected\n ) {\n this.value = (child as HTMLOptionElement).value;\n break;\n }\n }\n if (this.value) break;\n }\n }\n }\n\n this._setValue();\n this._defaultValue = this.value; // ← capture after resolving selected option\n }\n\n updated(changedProperties: Map<string | number | symbol, unknown>) {\n if (changedProperties.has(\"value\")) {\n const option = this._options.find((opt) => opt.value === this.value);\n this._selectedLabel = option ? option.label : \"\";\n this._filterText = this._selectedLabel;\n }\n\n if (changedProperties.has(\"_isOpen\") && this._isOpen) {\n this._positionDropdown();\n this.updateComplete.then(() => {\n this._scrollToHighlighted();\n });\n }\n }\n\n /**\n * Slot handling\n * --------------------------------------------------------------------------\n */\n private _handleSlotChange() {\n const slot = this.shadowRoot?.querySelector(\n 'slot:not([name=\"description\"])',\n ) as HTMLSlotElement | null;\n\n if (!slot) return;\n\n const assignedElements = slot.assignedElements({ flatten: true });\n const options: ComboboxOption[] = [];\n\n assignedElements.forEach((node) => {\n if (node.tagName === \"OPTION\") {\n const option = node as HTMLOptionElement;\n options.push({\n value: option.value,\n label: option.textContent?.trim() || option.value,\n disabled: option.disabled,\n });\n } else if (node.tagName === \"OPTGROUP\") {\n const group = node as HTMLOptGroupElement;\n const groupLabel = group.label;\n\n Array.from(group.children).forEach((child) => {\n if (child.tagName === \"OPTION\") {\n const option = child as HTMLOptionElement;\n options.push({\n value: option.value,\n label: option.textContent?.trim() || option.value,\n disabled: option.disabled || group.disabled,\n group: groupLabel,\n });\n }\n });\n }\n });\n\n this._options = options;\n this._filteredOptions = options;\n\n // Set initial display text if value exists\n if (this.value) {\n const option = this._options.find((opt) => opt.value === this.value);\n if (option) {\n this._selectedLabel = option.label;\n this._filterText = option.label;\n }\n }\n }\n\n /**\n * Form Integration\n * --------------------------------------------------------------------------\n */\n private _setValue() {\n this._internals.setFormValue(this.value);\n this._manageRequire();\n }\n\n private _manageRequire() {\n const message = this.errorMessage || \"This field is required\";\n const isInvalid =\n this.required && (!this.value || this.value?.trim() === \"\");\n\n if (isInvalid) {\n this._internals.ariaRequired = \"true\";\n this._internals.setValidity({ valueMissing: true }, message, this._input);\n } else {\n this._internals.ariaRequired = \"false\";\n this._internals.setValidity({});\n this._hasUserInteracted = false;\n }\n }\n\n private _setValidityMessage(message: string = \"\") {\n this.showError = !!message;\n\n if (this._originalErrorMessage?.trim() && message !== \"\") {\n this.errorMessage = this._originalErrorMessage;\n } else {\n this.errorMessage = message;\n }\n\n const validityState = message ? { customError: true } : {};\n this._internals.setValidity(validityState, this.errorMessage, this._input);\n }\n\n private _validate() {\n if (!this._input) return;\n\n const validity = this._input.validity;\n let message = \"\";\n\n if (validity.valueMissing) {\n message = \"This field is required\";\n } else {\n message = this._input.validationMessage;\n }\n\n this._setValidityMessage(message);\n }\n\n formResetCallback() {\n this.value = this._defaultValue;\n this._filterText = this._defaultValue\n ? (this._options.find((opt) => opt.value === this._defaultValue)?.label ??\n \"\")\n : \"\";\n this._selectedLabel = this._filterText;\n\n if (this._input) {\n this._input.value = this._filterText;\n }\n\n this._internals.setFormValue(this.value);\n\n // Reset validation UI\n this.showError = false;\n this.errorMessage = \"\";\n this._internals.setValidity({});\n\n this.requestUpdate();\n }\n checkValidity(): boolean {\n return this._input ? this._input.checkValidity() : true;\n }\n\n private _handleInvalid(event: Event) {\n event.preventDefault();\n this._hasUserInteracted = true;\n this._validate();\n\n if (this._input) {\n const form = this._internals.form;\n if (form) {\n const elements = Array.from(form.elements) as Array<\n HTMLElement & { checkValidity?: () => boolean }\n >;\n const firstInvalidElement = elements.find(\n (element) =>\n typeof element.checkValidity === \"function\" &&\n !element.checkValidity(),\n );\n if (firstInvalidElement === this) {\n this._input.focus();\n }\n } else {\n this._input.focus();\n }\n }\n }\n\n /**\n * Dropdown positioning\n * --------------------------------------------------------------------------\n */\n private _positionDropdown() {\n if (!this._listbox || !this._input) return;\n\n const inputRect = this._input.getBoundingClientRect();\n const listboxHeight = this._listbox.offsetHeight;\n const viewportHeight = window.innerHeight;\n const spaceBelow = viewportHeight - inputRect.bottom;\n const spaceAbove = inputRect.top;\n\n // Show above if not enough space below and more space above\n this._dropdownAbove = spaceBelow < listboxHeight && spaceAbove > spaceBelow;\n }\n\n /**\n * Filtering\n * --------------------------------------------------------------------------\n */\n private _filterOptions(searchText: string) {\n if (!searchText) {\n this._filteredOptions = this._options;\n return;\n }\n\n const search = searchText.toLowerCase();\n this._filteredOptions = this._options.filter((option) =>\n option.label.toLowerCase().includes(search),\n );\n }\n\n /**\n * Keyboard navigation\n * --------------------------------------------------------------------------\n */\n private _scrollToHighlighted() {\n if (!this._listbox || this._highlightedIndex < 0) return;\n\n const highlighted = this._listbox.querySelector(\n `[data-index=\"${this._highlightedIndex}\"]`,\n ) as HTMLElement;\n\n if (highlighted) {\n highlighted.scrollIntoView({ block: \"nearest\" });\n }\n }\n\n private _handleKeyDown(event: KeyboardEvent) {\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault();\n if (!this._isOpen) {\n this._openDropdown();\n } else {\n this._moveHighlight(1);\n }\n break;\n\n case \"ArrowUp\":\n event.preventDefault();\n if (!this._isOpen) {\n this._openDropdown();\n } else {\n this._moveHighlight(-1);\n }\n break;\n\n case \"Enter\":\n event.preventDefault();\n if (this._isOpen && this._highlightedIndex >= 0) {\n this._selectOption(this._filteredOptions[this._highlightedIndex]);\n }\n break;\n\n case \"Escape\":\n event.preventDefault();\n this._closeDropdown();\n this._filterText = this._selectedLabel;\n break;\n\n case \"Tab\":\n if (this._isOpen) {\n this._closeDropdown();\n this._filterText = this._selectedLabel;\n }\n break;\n }\n }\n\n private _moveHighlight(direction: number) {\n const enabledOptions = this._filteredOptions.filter((opt) => !opt.disabled);\n if (enabledOptions.length === 0) return;\n\n let newIndex = this._highlightedIndex + direction;\n\n // Wrap around\n if (newIndex < 0) {\n newIndex = this._filteredOptions.length - 1;\n } else if (newIndex >= this._filteredOptions.length) {\n newIndex = 0;\n }\n\n // Skip disabled options\n while (this._filteredOptions[newIndex]?.disabled) {\n newIndex += direction;\n if (newIndex < 0) newIndex = this._filteredOptions.length - 1;\n if (newIndex >= this._filteredOptions.length) newIndex = 0;\n }\n\n this._highlightedIndex = newIndex;\n this._scrollToHighlighted();\n\n const option = this._filteredOptions[newIndex];\n const prevOption = this._filteredOptions[newIndex - direction];\n const enabledFiltered = this._filteredOptions.filter(\n (opt) => !opt.disabled,\n );\n const position =\n enabledFiltered.findIndex((opt) => opt.value === option.value) + 1;\n const isSelected = option.value === this.value ? \"selected\" : \"unselected\";\n const groupChanged = option.group && option.group !== prevOption?.group;\n const groupPrefix = groupChanged ? `${option.group}, ` : \"\";\n this._announcement = `${groupPrefix} ${option.label} ${position} of ${enabledFiltered.length}, ${isSelected}`;\n }\n\n /**\n * Event Handlers\n * --------------------------------------------------------------------------\n */\n private _handleInput(event: Event) {\n const input = event.target as HTMLInputElement;\n this._filterText = input.value;\n this._filterOptions(this._filterText);\n\n if (!this._isOpen) {\n this._openDropdown();\n }\n\n this._highlightedIndex = 0;\n\n const count = this._filteredOptions.filter((opt) => !opt.disabled).length;\n this._announcement =\n count > 0 ? `${count} options available` : \"No results found\";\n\n if (this._hasUserInteracted) {\n this._validate();\n }\n\n this.dispatchEvent(\n new CustomEvent(\"nys-input\", {\n detail: { id: this.id, value: this._filterText },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n private _handleFocus() {\n this.dispatchEvent(new Event(\"nys-focus\"));\n }\n\n private _handleBlur(event: FocusEvent) {\n // Check if focus moved to the listbox\n const relatedTarget = event.relatedTarget as HTMLElement;\n if (relatedTarget && this._listbox?.contains(relatedTarget)) {\n return;\n }\n\n // If no valid selection, clear the input\n if (!this.value || this._filterText !== this._selectedLabel) {\n this._filterText = this._selectedLabel;\n this._filterOptions(\"\");\n }\n\n this._closeDropdown();\n\n if (!this._hasUserInteracted) {\n this._hasUserInteracted = true;\n }\n this._validate();\n\n this.dispatchEvent(new Event(\"nys-blur\"));\n }\n\n private _handleDocumentClick = (event: MouseEvent) => {\n // Don't close if click is on the combobox host element or inside shadow DOM\n if (\n event.target === this ||\n this.shadowRoot?.contains(event.target as Node)\n ) {\n return;\n }\n this._closeDropdown();\n };\n\n private _handleIconClick() {\n if (this.disabled) return;\n\n if (this._isOpen) {\n this._closeDropdown();\n } else {\n this._input.focus();\n this._openDropdown();\n }\n }\n\n private _handleClearClick(event: Event) {\n event.stopPropagation();\n this.value = \"\";\n this._filterText = \"\";\n this._selectedLabel = \"\";\n this._filterOptions(\"\");\n this._internals.setFormValue(\"\");\n this._closeDropdown();\n this._input.focus();\n\n this._handleChange();\n }\n\n private _handleOptionClick(option: ComboboxOption) {\n if (option.disabled) return;\n this._selectOption(option);\n }\n\n private _handleOptionMouseEnter(index: number) {\n this._highlightedIndex = index;\n }\n\n private _selectOption(option: ComboboxOption) {\n this.value = option.value;\n this._selectedLabel = option.label;\n this._filterText = option.label;\n this._internals.setFormValue(this.value);\n this._input.focus();\n this._closeDropdown();\n this._filterOptions(\"\");\n\n this._setValidityMessage(\"\");\n\n if (this._hasUserInteracted) {\n this._validate();\n }\n\n this._handleChange();\n }\n\n private _handleChange() {\n this.dispatchEvent(\n new CustomEvent(\"nys-change\", {\n detail: { id: this.id, value: this.value },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n private _openDropdown() {\n this._isOpen = true;\n this._highlightedIndex = this._filteredOptions.findIndex(\n (opt) => opt.value === this.value,\n );\n if (this._highlightedIndex < 0) this._highlightedIndex = 0;\n }\n\n private _closeDropdown() {\n this._isOpen = false;\n this._highlightedIndex = -1;\n }\n\n /**\n * Render helpers\n * --------------------------------------------------------------------------\n */\n private _renderOptions() {\n let currentGroup = \"\";\n const elements: any[] = [];\n\n this._filteredOptions.forEach((option, index) => {\n if (option.group && option.group !== currentGroup) {\n currentGroup = option.group;\n elements.push(html`\n <div class=\"nys-combobox__optgroup\" role=\"presentation\">\n ${option.group}\n </div>\n `);\n }\n\n const isFocused = index === this._highlightedIndex;\n const isSelected = option.value === this.value;\n\n elements.push(html`\n <div\n class=\"nys-combobox__option ${isFocused\n ? \"nys-combobox__option--focused\"\n : \"\"} ${isSelected ? \"nys-combobox__option--selected\" : \"\"}\"\n role=\"option\"\n id=\"${this.id}--option-${index}\"\n data-index=\"${index}\"\n aria-selected=\"${isSelected}\"\n aria-disabled=\"${option.disabled || false}\"\n ?disabled=${option.disabled}\n @click=${() => this._handleOptionClick(option)}\n @mouseenter=${() => this._handleOptionMouseEnter(index)}\n >\n ${option.label}\n </div>\n `);\n });\n\n if (elements.length === 0) {\n return html`\n <div class=\"nys-combobox__no-results\" role=\"option\">\n No results found\n </div>\n `;\n }\n\n return elements;\n }\n\n render() {\n return html`\n <div class=\"nys-combobox\">\n <nys-label\n for=${this.id + \"--native\"}\n label=${this.label}\n description=${this.description}\n flag=${this.required ? \"required\" : this.optional ? \"optional\" : \"\"}\n tooltip=${this.tooltip}\n ?inverted=${this.inverted}\n >\n <slot name=\"description\" slot=\"description\">${this.description}</slot>\n </nys-label>\n <div\n class=\"nys-combobox__container ${this._isOpen\n ? \"nys-combobox__container--open\"\n : \"\"}\"\n >\n <div class=\"nys-combobox__input-wrapper\">\n <input\n class=\"nys-combobox__input\"\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded=\"${this._isOpen}\"\n aria-controls=\"${this.id}--listbox\"\n aria-activedescendant=\"${this._highlightedIndex >= 0\n ? `${this.id}--option-${this._highlightedIndex}`\n : \"\"}\"\n name=${this.name}\n id=${this.id + \"--native\"}\n ?disabled=${this.disabled}\n ?required=${this.required}\n aria-required=${this.required}\n aria-disabled=\"${this.disabled}\"\n aria-label=\"${[this.label, this.description]\n .filter(Boolean)\n .join(\" \")}\"\n .value=${this._filterText}\n form=${ifDefined(this.form || undefined)}\n @input=${this._handleInput}\n @focus=\"${this._handleFocus}\"\n @blur=\"${this._handleBlur}\"\n @keydown=\"${this._handleKeyDown}\"\n />\n <div class=\"nys-combobox__buttons\">\n ${this.value\n ? html`\n <nys-button\n class=\"nys-combobox__clear\"\n suffixIcon=\"slotted\"\n ariaLabel=\"clear selection\"\n variant=\"ghost\"\n size=\"sm\"\n circle\n @nys-click=${this._handleClearClick}\n ?disabled=${this.disabled}\n >\n <nys-icon\n slot=\"suffix-icon\"\n size=\"20\"\n name=\"close\"\n ></nys-icon>\n </nys-button>\n `\n : \"\"}\n <nys-button\n class=\"nys-combobox__chevron\"\n suffixIcon=\"slotted\"\n ariaLabel=\"toggle dropdown\"\n variant=\"ghost\"\n size=\"sm\"\n circle\n @nys-click=${this._handleIconClick}\n ?disabled=${this.disabled}\n >\n <nys-icon\n slot=\"suffix-icon\"\n size=\"20\"\n name=\"chevron_down\"\n ></nys-icon>\n </nys-button>\n </div>\n </div>\n ${this._isOpen\n ? html`\n <div\n class=\"nys-combobox__listbox ${this._dropdownAbove\n ? \"nys-combobox__listbox--above\"\n : \"\"}\"\n id=\"${this.id}--listbox\"\n role=\"listbox\"\n tabindex=\"-1\"\n >\n ${this._renderOptions()}\n </div>\n `\n : \"\"}\n </div>\n <slot\n style=\"display: none;\"\n @slotchange=${this._handleSlotChange}\n ></slot>\n <nys-errormessage\n ?showError=${this.showError}\n errorMessage=${this.errorMessage}\n ></nys-errormessage>\n <div\n aria-live=\"polite\"\n aria-atomic=\"true\"\n style=\"position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;\"\n >\n ${this._announcement}\n </div>\n </div>\n `;\n }\n}\n\nif (!customElements.get(\"nys-combobox\")) {\n customElements.define(\"nys-combobox\", NysCombobox);\n}\n"],"names":["comboboxIdCounter","_NysCombobox","LitElement","event","slot","assignedElements","node","child","changedProperties","option","opt","options","group","groupLabel","message","validityState","validity","form","element","inputRect","listboxHeight","spaceBelow","spaceAbove","searchText","search","highlighted","direction","newIndex","prevOption","enabledFiltered","position","isSelected","groupPrefix","input","count","relatedTarget","index","currentGroup","elements","html","isFocused","ifDefined","unsafeCSS","styles","NysCombobox","__decorateClass","property","state","query"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nysds/nys-combobox",
|
|
3
|
+
"version": "1.15.0",
|
|
4
|
+
"description": "The Combobox component from the NYS Design System.",
|
|
5
|
+
"module": "dist/nys-combobox.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/nys-combobox.js",
|
|
10
|
+
"types": "./dist/index.d.ts"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"files": [
|
|
15
|
+
"dist/"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"dev": "tsc --emitDeclarationOnly && vite",
|
|
19
|
+
"build": "tsc --emitDeclarationOnly && vite build",
|
|
20
|
+
"test": "vite build && wtr",
|
|
21
|
+
"build:watch": "tsc --emitDeclarationOnly && vite build --watch",
|
|
22
|
+
"test:watch": "vite build && wtr --watch",
|
|
23
|
+
"lit-analyze": "lit-analyzer '*.ts'"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"lit": "^3.3.1",
|
|
28
|
+
"typescript": "^5.9.3",
|
|
29
|
+
"vite": "^7.3.1"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"new-york-state",
|
|
33
|
+
"design-system",
|
|
34
|
+
"web-components",
|
|
35
|
+
"lit",
|
|
36
|
+
"nys",
|
|
37
|
+
"combobox",
|
|
38
|
+
"forms"
|
|
39
|
+
],
|
|
40
|
+
"author": "New York State Design System Team",
|
|
41
|
+
"license": "MIT"
|
|
42
|
+
}
|