@nova-design-system/nova-webcomponents 3.30.0 → 3.31.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/cjs/index.cjs.js +9 -0
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/native.cjs.js +1 -1
- package/dist/cjs/nv-fielddropdown.cjs.entry.js +100 -22
- package/dist/cjs/nv-fielddropdownitem.cjs.entry.js +1 -1
- package/dist/cjs/nv-fieldselect.cjs.entry.js +44 -6
- package/dist/cjs/nv-fieldslider.cjs.entry.js +3 -3
- package/dist/cjs/nv-fieldtext.cjs.entry.js +4 -4
- package/dist/cjs/nv-fieldtextarea.cjs.entry.js +3 -3
- package/dist/cjs/nv-fieldtime.cjs.entry.js +3 -3
- package/dist/cjs/nv-icon.cjs.entry.js +2 -2
- package/dist/cjs/nv-iconbutton_2.cjs.entry.js +2 -2
- package/dist/cjs/nv-menu.cjs.entry.js +1 -1
- package/dist/cjs/nv-menuitem.cjs.entry.js +1 -1
- package/dist/cjs/nv-notification.cjs.entry.js +1 -1
- package/dist/cjs/nv-notificationcontainer.cjs.entry.js +1 -1
- package/dist/cjs/nv-pagination-nav.cjs.entry.js +1 -1
- package/dist/cjs/nv-paginationtable.cjs.entry.js +1 -1
- package/dist/cjs/nv-popover.cjs.entry.js +1 -1
- package/dist/cjs/nv-row.cjs.entry.js +1 -1
- package/dist/cjs/nv-sidebar.cjs.entry.js +2 -2
- package/dist/cjs/nv-sidebarcontent.cjs.entry.js +1 -1
- package/dist/cjs/nv-sidebardivider.cjs.entry.js +1 -1
- package/dist/cjs/nv-sidebarfooter.cjs.entry.js +1 -1
- package/dist/cjs/nv-sidebargroup.cjs.entry.js +1 -1
- package/dist/cjs/nv-sidebarheader.cjs.entry.js +1 -1
- package/dist/cjs/nv-sidebarlogo.cjs.entry.js +1 -1
- package/dist/cjs/nv-sidebarnavitem.cjs.entry.js +2 -2
- package/dist/cjs/nv-sidebarnavsubitem.cjs.entry.js +1 -1
- package/dist/cjs/nv-split.cjs.entry.js +1 -1
- package/dist/cjs/nv-stack.cjs.entry.js +1 -1
- package/dist/cjs/nv-statusindicator.cjs.entry.js +1 -1
- package/dist/cjs/nv-table.cjs.entry.js +1 -1
- package/dist/cjs/nv-tableheader.cjs.entry.js +1 -1
- package/dist/cjs/nv-timetest.cjs.entry.js +1 -1
- package/dist/cjs/nv-toggle.cjs.entry.js +2 -2
- package/dist/cjs/nv-togglebutton.cjs.entry.js +1 -1
- package/dist/cjs/nv-togglebuttongroup.cjs.entry.js +1 -1
- package/dist/cjs/nv-tooltip.cjs.entry.js +1 -1
- package/dist/collection/components/nv-alert/nv-alert.js +1 -1
- package/dist/collection/components/nv-badge/nv-badge.js +2 -2
- package/dist/collection/components/nv-dialogfooter/nv-dialogfooter.js +2 -2
- package/dist/collection/components/nv-drawerfooter/nv-drawerfooter.js +2 -2
- package/dist/collection/components/nv-fielddropdown/nv-fielddropdown.docs.js +11 -0
- package/dist/collection/components/nv-fielddropdown/nv-fielddropdown.js +151 -22
- package/dist/collection/components/nv-fielddropdownitem/nv-fielddropdownitem.docs.js +7 -7
- package/dist/collection/components/nv-fielddropdownitem/nv-fielddropdownitem.js +1 -1
- package/dist/collection/components/nv-fieldselect/nv-fieldselect.docs.js +11 -0
- package/dist/collection/components/nv-fieldselect/nv-fieldselect.js +98 -5
- package/dist/collection/components/nv-fieldselect/styles/nv-fieldselect.css +3 -0
- package/dist/collection/components/nv-fieldslider/nv-fieldslider.js +3 -3
- package/dist/collection/components/nv-fieldtext/nv-fieldtext.js +4 -4
- package/dist/collection/components/nv-fieldtextarea/nv-fieldtextarea.js +3 -3
- package/dist/collection/components/nv-fieldtime/nv-fieldtime.js +3 -3
- package/dist/collection/components/nv-icon/nv-icon.js +2 -2
- package/dist/collection/components/nv-icon/nv-icons.js +9 -0
- package/dist/collection/components/nv-iconbutton/nv-iconbutton.js +2 -2
- package/dist/collection/components/nv-loader/nv-loader.js +1 -1
- package/dist/collection/components/nv-menu/nv-menu.js +1 -1
- package/dist/collection/components/nv-menuitem/nv-menuitem.js +2 -2
- package/dist/collection/components/nv-notification/nv-notification.js +2 -2
- package/dist/collection/components/nv-notificationcontainer/nv-notificationcontainer.js +1 -1
- package/dist/collection/components/nv-pagination-nav/nv-pagination-nav.js +1 -1
- package/dist/collection/components/nv-paginationtable/nv-paginationtable.js +1 -1
- package/dist/collection/components/nv-popover/nv-popover.js +1 -1
- package/dist/collection/components/nv-row/nv-row.js +1 -1
- package/dist/collection/components/nv-sidebar/nv-sidebar.js +2 -2
- package/dist/collection/components/nv-sidebarcontent/nv-sidebarcontent.js +1 -1
- package/dist/collection/components/nv-sidebardivider/nv-sidebardivider.js +1 -1
- package/dist/collection/components/nv-sidebarfooter/nv-sidebarfooter.js +1 -1
- package/dist/collection/components/nv-sidebargroup/nv-sidebargroup.js +1 -1
- package/dist/collection/components/nv-sidebarheader/nv-sidebarheader.js +1 -1
- package/dist/collection/components/nv-sidebarlogo/nv-sidebarlogo.js +1 -1
- package/dist/collection/components/nv-sidebarnavitem/nv-sidebarnavitem.js +3 -3
- package/dist/collection/components/nv-sidebarnavsubitem/nv-sidebarnavsubitem.js +1 -1
- package/dist/collection/components/nv-split/nv-split.js +1 -1
- package/dist/collection/components/nv-stack/nv-stack.js +1 -1
- package/dist/collection/components/nv-statusindicator/nv-statusindicator.js +1 -1
- package/dist/collection/components/nv-table/nv-table.js +1 -1
- package/dist/collection/components/nv-tableheader/nv-tableheader.js +1 -1
- package/dist/collection/components/nv-timetest/nv-timetest.js +1 -1
- package/dist/collection/components/nv-toggle/nv-toggle.js +2 -2
- package/dist/collection/components/nv-togglebutton/nv-togglebutton.js +1 -1
- package/dist/collection/components/nv-togglebuttongroup/nv-togglebuttongroup.js +1 -1
- package/dist/collection/components/nv-tooltip/nv-tooltip.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/nv-accordion-item.js +1 -1
- package/dist/components/nv-accordion.js +1 -1
- package/dist/components/nv-alert.js +1 -1
- package/dist/components/nv-avatar.js +1 -1
- package/dist/components/nv-badge.js +1 -1
- package/dist/components/nv-breadcrumb.js +1 -1
- package/dist/components/nv-button.js +1 -1
- package/dist/components/nv-datagrid.js +1 -1
- package/dist/components/nv-dialog.js +1 -1
- package/dist/components/nv-dialogfooter.js +1 -1
- package/dist/components/nv-drawer.js +1 -1
- package/dist/components/nv-drawerfooter.js +1 -1
- package/dist/components/nv-fielddate.js +1 -1
- package/dist/components/nv-fielddaterange.js +1 -1
- package/dist/components/nv-fielddropdown.js +1 -1
- package/dist/components/nv-fielddropdownitem.js +1 -1
- package/dist/components/nv-fieldmultiselect.js +1 -1
- package/dist/components/nv-fieldnumber.js +1 -1
- package/dist/components/nv-fieldpassword.js +1 -1
- package/dist/components/nv-fieldselect.js +1 -1
- package/dist/components/nv-fieldslider.js +1 -1
- package/dist/components/nv-fieldtext.js +1 -1
- package/dist/components/nv-fieldtextarea.js +1 -1
- package/dist/components/nv-fieldtime.js +1 -1
- package/dist/components/nv-icon.js +1 -1
- package/dist/components/nv-iconbutton.js +1 -1
- package/dist/components/nv-loader.js +1 -1
- package/dist/components/nv-menu.js +1 -1
- package/dist/components/nv-menuitem.js +1 -1
- package/dist/components/nv-notification.js +1 -1
- package/dist/components/nv-notificationcontainer.js +1 -1
- package/dist/components/nv-pagination-nav.js +1 -1
- package/dist/components/nv-paginationtable.js +1 -1
- package/dist/components/nv-popover.js +1 -1
- package/dist/components/nv-row.js +1 -1
- package/dist/components/nv-sidebar.js +1 -1
- package/dist/components/nv-sidebarcontent.js +1 -1
- package/dist/components/nv-sidebardivider.js +1 -1
- package/dist/components/nv-sidebarfooter.js +1 -1
- package/dist/components/nv-sidebargroup.js +1 -1
- package/dist/components/nv-sidebarheader.js +1 -1
- package/dist/components/nv-sidebarlogo.js +1 -1
- package/dist/components/nv-sidebarnavitem.js +1 -1
- package/dist/components/nv-sidebarnavsubitem.js +1 -1
- package/dist/components/nv-split.js +1 -1
- package/dist/components/nv-stack.js +1 -1
- package/dist/components/nv-statusindicator.js +1 -1
- package/dist/components/nv-table.js +1 -1
- package/dist/components/nv-tableheader.js +1 -1
- package/dist/components/nv-tag.js +1 -1
- package/dist/components/nv-timetest.js +1 -1
- package/dist/components/nv-toggle.js +1 -1
- package/dist/components/nv-togglebutton.js +1 -1
- package/dist/components/nv-togglebuttongroup.js +1 -1
- package/dist/components/nv-tooltip.js +1 -1
- package/dist/components/{p-D54x8OFu.js → p-1Zs1aHJ4.js} +1 -1
- package/dist/components/{p-Dg-Ac5i4.js → p-B4Uw_U8V.js} +1 -1
- package/dist/components/{p-yPMU6HZQ.js → p-BFM_8Jgq.js} +1 -1
- package/dist/components/{p-BYrgllP3.js → p-B_SethFg.js} +1 -1
- package/dist/components/{p-Cx5CLy9v.js → p-Bt5_pj49.js} +1 -1
- package/dist/components/{p-MLanePUO.js → p-C-Rs6wG9.js} +1 -1
- package/dist/components/p-C_eOV3Z7.js +1 -0
- package/dist/components/{p-Bu90dktV.js → p-Co54UCK_.js} +1 -1
- package/dist/components/{p-BhRpSdkR.js → p-CsPx96EZ.js} +1 -1
- package/dist/components/{p-DP_K3tkj.js → p-DCYvyQ_j.js} +1 -1
- package/dist/components/{p-L7U51TAH.js → p-DWvQs_c-.js} +1 -1
- package/dist/components/{p-B8yJMa0S.js → p-Ghb9L_N-.js} +1 -1
- package/dist/components/{p-CzRlra4z.js → p-Oger3lC0.js} +1 -1
- package/dist/components/{p-DQuJvZ4Z.js → p-VppCgviO.js} +1 -1
- package/dist/components/{p-Cj6urNtm.js → p-YhjPEgIT.js} +1 -1
- package/dist/esm/index.js +9 -0
- package/dist/esm/loader.js +1 -1
- package/dist/esm/native.js +1 -1
- package/dist/esm/nv-fielddropdown.entry.js +100 -22
- package/dist/esm/nv-fielddropdownitem.entry.js +1 -1
- package/dist/esm/nv-fieldselect.entry.js +44 -6
- package/dist/esm/nv-fieldslider.entry.js +3 -3
- package/dist/esm/nv-fieldtext.entry.js +4 -4
- package/dist/esm/nv-fieldtextarea.entry.js +3 -3
- package/dist/esm/nv-fieldtime.entry.js +3 -3
- package/dist/esm/nv-icon.entry.js +2 -2
- package/dist/esm/nv-iconbutton_2.entry.js +2 -2
- package/dist/esm/nv-menu.entry.js +1 -1
- package/dist/esm/nv-menuitem.entry.js +1 -1
- package/dist/esm/nv-notification.entry.js +1 -1
- package/dist/esm/nv-notificationcontainer.entry.js +1 -1
- package/dist/esm/nv-pagination-nav.entry.js +1 -1
- package/dist/esm/nv-paginationtable.entry.js +1 -1
- package/dist/esm/nv-popover.entry.js +1 -1
- package/dist/esm/nv-row.entry.js +1 -1
- package/dist/esm/nv-sidebar.entry.js +2 -2
- package/dist/esm/nv-sidebarcontent.entry.js +1 -1
- package/dist/esm/nv-sidebardivider.entry.js +1 -1
- package/dist/esm/nv-sidebarfooter.entry.js +1 -1
- package/dist/esm/nv-sidebargroup.entry.js +1 -1
- package/dist/esm/nv-sidebarheader.entry.js +1 -1
- package/dist/esm/nv-sidebarlogo.entry.js +1 -1
- package/dist/esm/nv-sidebarnavitem.entry.js +2 -2
- package/dist/esm/nv-sidebarnavsubitem.entry.js +1 -1
- package/dist/esm/nv-split.entry.js +1 -1
- package/dist/esm/nv-stack.entry.js +1 -1
- package/dist/esm/nv-statusindicator.entry.js +1 -1
- package/dist/esm/nv-table.entry.js +1 -1
- package/dist/esm/nv-tableheader.entry.js +1 -1
- package/dist/esm/nv-timetest.entry.js +1 -1
- package/dist/esm/nv-toggle.entry.js +2 -2
- package/dist/esm/nv-togglebutton.entry.js +1 -1
- package/dist/esm/nv-togglebuttongroup.entry.js +1 -1
- package/dist/esm/nv-tooltip.entry.js +1 -1
- package/dist/native/index.esm.js +1 -1
- package/dist/native/native.esm.js +1 -1
- package/dist/native/{p-189647e4.entry.js → p-007fef99.entry.js} +1 -1
- package/dist/native/{p-6ccc84c8.entry.js → p-00f4c8d3.entry.js} +1 -1
- package/dist/native/{p-04011d0f.entry.js → p-06eb42e0.entry.js} +1 -1
- package/dist/native/{p-93d2bfab.entry.js → p-13c507cd.entry.js} +1 -1
- package/dist/native/{p-b2ef61bc.entry.js → p-144ab827.entry.js} +1 -1
- package/dist/native/{p-ec919a10.entry.js → p-29b23e1d.entry.js} +1 -1
- package/dist/native/{p-c1faed1f.entry.js → p-2b20125e.entry.js} +1 -1
- package/dist/native/p-31e192d9.entry.js +1 -0
- package/dist/native/{p-dfd364de.entry.js → p-3855de15.entry.js} +1 -1
- package/dist/native/{p-37c42bed.entry.js → p-39d5af96.entry.js} +1 -1
- package/dist/native/p-3bed118d.entry.js +1 -0
- package/dist/native/{p-49745be2.entry.js → p-42dc404a.entry.js} +1 -1
- package/dist/native/{p-8faf3e05.entry.js → p-49ceb38e.entry.js} +1 -1
- package/dist/native/{p-c305f1c6.entry.js → p-4b8945c0.entry.js} +1 -1
- package/dist/native/{p-3f888601.entry.js → p-4cff908a.entry.js} +1 -1
- package/dist/native/{p-ffc9e2a0.entry.js → p-513fb9e7.entry.js} +1 -1
- package/dist/native/p-5adac760.entry.js +1 -0
- package/dist/native/p-6e49d3a1.entry.js +1 -0
- package/dist/native/{p-8decb323.entry.js → p-72c461ac.entry.js} +1 -1
- package/dist/native/{p-5375ddc6.entry.js → p-77bc9afe.entry.js} +1 -1
- package/dist/native/{p-33889f52.entry.js → p-789fdae9.entry.js} +1 -1
- package/dist/native/{p-287c67e1.entry.js → p-80ba6f84.entry.js} +1 -1
- package/dist/native/p-90397b9d.entry.js +1 -0
- package/dist/native/{p-40000df1.entry.js → p-91719d87.entry.js} +1 -1
- package/dist/native/p-a5d647f1.entry.js +1 -0
- package/dist/native/{p-0c65e726.entry.js → p-a6554d37.entry.js} +1 -1
- package/dist/native/{p-859b24ed.entry.js → p-b76682bb.entry.js} +1 -1
- package/dist/native/{p-d0dfa700.entry.js → p-bc0b637f.entry.js} +1 -1
- package/dist/native/p-bebf7bf7.entry.js +1 -0
- package/dist/native/{p-10dee67d.entry.js → p-c81532c9.entry.js} +1 -1
- package/dist/native/p-cec93106.entry.js +1 -0
- package/dist/native/{p-c5261442.entry.js → p-cfe99a3f.entry.js} +1 -1
- package/dist/native/{p-4514a6a4.entry.js → p-d0c5f580.entry.js} +1 -1
- package/dist/native/p-ef90ca99.entry.js +1 -0
- package/dist/native/{p-be2e4cf0.entry.js → p-f6341ac4.entry.js} +1 -1
- package/dist/native/{p-2afcd5e4.entry.js → p-f986b4e5.entry.js} +1 -1
- package/dist/types/components/nv-fielddropdown/nv-fielddropdown.d.ts +39 -0
- package/dist/types/components/nv-fieldselect/nv-fieldselect.d.ts +28 -0
- package/dist/types/components/nv-icon/nv-icons.d.ts +1 -1
- package/dist/types/components.d.ts +38 -0
- package/dist/vscode-data.json +332 -0
- package/hydrate/index.js +199 -79
- package/hydrate/index.mjs +199 -79
- package/package.json +1 -1
- package/dist/components/p-B4qcUV0M.js +0 -1
- package/dist/native/p-298d893d.entry.js +0 -1
- package/dist/native/p-5690757b.entry.js +0 -1
- package/dist/native/p-7c9e1f01.entry.js +0 -1
- package/dist/native/p-7cbc09f0.entry.js +0 -1
- package/dist/native/p-b99ad8a7.entry.js +0 -1
- package/dist/native/p-d4d04530.entry.js +0 -1
- package/dist/native/p-dfb46af1.entry.js +0 -1
- package/dist/native/p-e7a73a7c.entry.js +0 -1
- package/dist/native/p-eab25bfa.entry.js +0 -1
|
@@ -88,6 +88,13 @@ export class NvFielddropdown {
|
|
|
88
88
|
* Enables or disables the filtering feature for the dropdown items.
|
|
89
89
|
*/
|
|
90
90
|
this.filterable = false;
|
|
91
|
+
/**
|
|
92
|
+
* Shows the inline clear (×) button when a value is selected (or when
|
|
93
|
+
* filterable and the user has typed). The programmatic `clear()` method
|
|
94
|
+
* works regardless of this prop — leave it off when you want to manage
|
|
95
|
+
* clearing the selection from outside the component.
|
|
96
|
+
*/
|
|
97
|
+
this.clearable = false;
|
|
91
98
|
/**
|
|
92
99
|
* When an item is selected by the user, the dropdown will continue to stay
|
|
93
100
|
* open.
|
|
@@ -181,10 +188,35 @@ export class NvFielddropdown {
|
|
|
181
188
|
if (!this.el?.contains(event.target))
|
|
182
189
|
this.open = false;
|
|
183
190
|
};
|
|
191
|
+
/**
|
|
192
|
+
* Handles clicks on the inline clear button. When a value is already
|
|
193
|
+
* selected and the user has typed in a filter, clearing should dismiss
|
|
194
|
+
* the filter and revert the input to the selected label rather than
|
|
195
|
+
* wipe the selection. Always emits `cleared` so subscribers see one
|
|
196
|
+
* consistent signal regardless of which path ran.
|
|
197
|
+
* @param {MouseEvent} [event] - The click event from the clear button.
|
|
198
|
+
*/
|
|
199
|
+
this.handleClearButtonClick = (event) => {
|
|
200
|
+
// Keyboard-activated clicks have detail === 0; mouse clicks are >= 1.
|
|
201
|
+
// We only restore focus on keyboard activation so we don't steal focus
|
|
202
|
+
// from mouse users (and we don't reopen a closed popover via the focus
|
|
203
|
+
// listener on mouse clicks).
|
|
204
|
+
const isKeyboard = event?.detail === 0;
|
|
205
|
+
if (this.value && this.filterable && this.filterText?.length > 0) {
|
|
206
|
+
this.clearFilter();
|
|
207
|
+
this.cleared.emit();
|
|
208
|
+
if (isKeyboard)
|
|
209
|
+
this.focusField();
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
this.clear();
|
|
213
|
+
if (isKeyboard)
|
|
214
|
+
this.focusField();
|
|
215
|
+
};
|
|
184
216
|
this.handleFilterInput = () => {
|
|
185
217
|
this.open = true;
|
|
186
|
-
this.filterText = this.inputElement
|
|
187
|
-
this.filterTextChanged.emit(this.
|
|
218
|
+
this.filterText = this.inputElement?.value ?? '';
|
|
219
|
+
this.filterTextChanged.emit(this.filterText);
|
|
188
220
|
clearTimeout(this.debounceTimer);
|
|
189
221
|
// Use longer debounce for fuzzy mode (Fuse.js needs more time)
|
|
190
222
|
// For fuzzy mode, use FUZZY_DEBOUNCE_DELAY (300ms), otherwise use this.debounceDelay
|
|
@@ -200,12 +232,12 @@ export class NvFielddropdown {
|
|
|
200
232
|
return '';
|
|
201
233
|
if (this.filterText?.length)
|
|
202
234
|
return this.filterText;
|
|
203
|
-
if (this.options?.length > 1) {
|
|
204
|
-
const matchingItem = this.options
|
|
235
|
+
if ((this.options?.length ?? 0) > 1) {
|
|
236
|
+
const matchingItem = this.options?.find(option => option.value === this.value);
|
|
205
237
|
return matchingItem?.label ?? matchingItem?.value ?? this.value;
|
|
206
238
|
}
|
|
207
239
|
const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitem'));
|
|
208
|
-
const matchingItem =
|
|
240
|
+
const matchingItem = this.findItemMatchingValue(items);
|
|
209
241
|
const selectedLabel = matchingItem
|
|
210
242
|
? matchingItem.label ??
|
|
211
243
|
matchingItem.textContent?.trim() ??
|
|
@@ -262,8 +294,13 @@ export class NvFielddropdown {
|
|
|
262
294
|
event.relatedTarget.tagName.includes('NV-FIELDDROPDOWNITEM')) {
|
|
263
295
|
return;
|
|
264
296
|
}
|
|
265
|
-
|
|
266
|
-
|
|
297
|
+
// Toggle and clear are inline controls inside the trigger that should
|
|
298
|
+
// not open the popover when focused (keyboard or otherwise).
|
|
299
|
+
if (event.target === this.toggleElement)
|
|
300
|
+
return;
|
|
301
|
+
if (event.target === this.clearElement)
|
|
302
|
+
return;
|
|
303
|
+
this.open = true;
|
|
267
304
|
}
|
|
268
305
|
handleFocusOut(event) {
|
|
269
306
|
if (!(event.relatedTarget instanceof Node))
|
|
@@ -320,6 +357,32 @@ export class NvFielddropdown {
|
|
|
320
357
|
this.setFilterInputToSelectedValue();
|
|
321
358
|
}, 0);
|
|
322
359
|
}
|
|
360
|
+
/**
|
|
361
|
+
* Clears the current selection. Resets the value to an empty string,
|
|
362
|
+
* removes the selected state from items, clears the filter text (when
|
|
363
|
+
* filterable) and emits `valueChanged` (and `filterTextChanged` when the
|
|
364
|
+
* filter was reset). Emits `cleared` when anything was actually reset.
|
|
365
|
+
*/
|
|
366
|
+
async clear() {
|
|
367
|
+
const hadValue = Boolean(this.value);
|
|
368
|
+
const hadFilterText = this.filterable && this.filterText?.length > 0;
|
|
369
|
+
if (hadValue) {
|
|
370
|
+
this.value = '';
|
|
371
|
+
this.valueChanged.emit('');
|
|
372
|
+
}
|
|
373
|
+
if (hadFilterText) {
|
|
374
|
+
this.filterText = '';
|
|
375
|
+
this.filterTextChanged.emit('');
|
|
376
|
+
this.filterItems();
|
|
377
|
+
}
|
|
378
|
+
if (hadValue || hadFilterText) {
|
|
379
|
+
this.cleared.emit();
|
|
380
|
+
}
|
|
381
|
+
// Wait for wrapper lifecycle to finish before resetting input display.
|
|
382
|
+
setTimeout(() => {
|
|
383
|
+
this.setFilterInputToSelectedValue();
|
|
384
|
+
}, 0);
|
|
385
|
+
}
|
|
323
386
|
/**
|
|
324
387
|
* Toggles the dropdown popover open state
|
|
325
388
|
* @param {boolean} open - The open state to set, if null, toggles the state
|
|
@@ -348,6 +411,21 @@ export class NvFielddropdown {
|
|
|
348
411
|
return (this.inputElement.value = '');
|
|
349
412
|
this.inputElement.value = this.getSelectedLabel();
|
|
350
413
|
}
|
|
414
|
+
/**
|
|
415
|
+
* Finds the item that matches the current value. Falls back to matching by
|
|
416
|
+
* label when no item matches by value, so that consumers who pass a value
|
|
417
|
+
* matching only the label (e.g. `<nv-fielddropdownitem label="Item 2">`
|
|
418
|
+
* with `value="Item 2"`) still get the correct selected item.
|
|
419
|
+
* @param {HTMLNvFielddropdownitemElement[]} items - The dropdown items to search.
|
|
420
|
+
* @returns {HTMLNvFielddropdownitemElement | undefined} The matching item, or undefined if no match is found.
|
|
421
|
+
*/
|
|
422
|
+
findItemMatchingValue(items) {
|
|
423
|
+
if (!this.value)
|
|
424
|
+
return undefined;
|
|
425
|
+
const value = this.value;
|
|
426
|
+
return (items.find(item => item.value === value) ??
|
|
427
|
+
items.find(item => item.label === value));
|
|
428
|
+
}
|
|
351
429
|
// Will exclude detached items and data-empty
|
|
352
430
|
getFilterableItems() {
|
|
353
431
|
return Array.from(this.el.querySelectorAll('nv-fielddropdownitem:not([data-empty]):not([detached])'));
|
|
@@ -592,16 +670,10 @@ export class NvFielddropdown {
|
|
|
592
670
|
}
|
|
593
671
|
async updateSelectedItem() {
|
|
594
672
|
const items = this.getAllItems();
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
}
|
|
600
|
-
else {
|
|
601
|
-
item.selected = false;
|
|
602
|
-
}
|
|
603
|
-
});
|
|
604
|
-
}
|
|
673
|
+
const matchingItem = this.findItemMatchingValue(items);
|
|
674
|
+
items.forEach(item => {
|
|
675
|
+
item.selected = Boolean(this.value) && item === matchingItem;
|
|
676
|
+
});
|
|
605
677
|
}
|
|
606
678
|
//#endregion METHODS
|
|
607
679
|
/****************************************************************************/
|
|
@@ -619,7 +691,9 @@ export class NvFielddropdown {
|
|
|
619
691
|
componentDidRender() {
|
|
620
692
|
// Make sure to show the value when the field is disabled or readonly
|
|
621
693
|
// as we switch to an input instead of a p in that case
|
|
622
|
-
if (!this.filterable &&
|
|
694
|
+
if (!this.filterable &&
|
|
695
|
+
(this.disabled || this.readonly) &&
|
|
696
|
+
this.inputElement) {
|
|
623
697
|
this.inputElement.value = this.getSelectedLabel();
|
|
624
698
|
}
|
|
625
699
|
}
|
|
@@ -658,11 +732,14 @@ export class NvFielddropdown {
|
|
|
658
732
|
? ariaRequiredAttrValue === 'true' || ariaRequiredAttrValue === ''
|
|
659
733
|
: undefined;
|
|
660
734
|
const useNativeRequired = this.required && (!useAriaRequired || ariaRequiredValue === true);
|
|
661
|
-
return (h(Host, { key: '
|
|
735
|
+
return (h(Host, { key: '83aecee12e5f0fea2ddc293f1631dc4e55ab3764', role: "combobox", "aria-expanded": this.open.toString(), "aria-haspopup": "listbox", "aria-label": this.label }, (this.label || this.el.querySelector('[slot="label"]')) && (h("label", { key: 'adfef46ef0163fb3c902df5df70b5c591a6dd7e1', htmlFor: this.inputId, onClick: this.syncToggleDropdown.bind(this) }, h("slot", { key: 'ed6bd8cc6fcace8604f934ba197c31589bf5e296', name: "label" }, this.label))), h("nv-popover", { key: '9dfa5dd021c2d0803a35b79fd58dd70422dbe6f0', triggerMode: "controlled", placement: "bottom-start", open: this.open, onOpenChanged: e => this.openChanged.emit(e.detail) }, h("div", { key: '62024e3fae662f316a932cce628e58e6917fc624', class: "input-wrapper", slot: "trigger" }, h("slot", { key: '61fe57f847075dc6e1447cc377e7e8f828700b43', name: "before-input" }), h("div", { key: '8139ffe5b0b7d37781c2b435ed1b9c94f2eea9de', class: "input-container" }, h("slot", { key: 'ab2515724a53a1b9e4081bd1944130cd435a0a92', name: "leading-input" }), this.filterable || this.disabled || this.readonly ? (h("input", { "data-scope": "focusable", id: this.inputId, type: "search", ref: e => (this.inputElement = e), autofocus: this.autofocus, autocomplete: this.autocomplete, placeholder: this.placeholder, name: this.name, required: useNativeRequired ? this.required : undefined, ...(ariaRequiredValue !== undefined && {
|
|
662
736
|
'aria-required': String(ariaRequiredValue),
|
|
663
|
-
}), disabled: this.disabled, readOnly: this.readonly, onInput: this.handleFilterInput })) : (h("p", { "data-scope": "focusable", id: this.inputId, ref: el => (this.selectElement = el), class: "non-filterable-text", tabIndex: this.disabled ? -1 : 0 }, this.getSelectedLabel() || this.value || this.placeholder)), this.
|
|
664
|
-
this.
|
|
665
|
-
this.
|
|
737
|
+
}), disabled: this.disabled, readOnly: this.readonly, onInput: this.handleFilterInput })) : (h("p", { "data-scope": "focusable", id: this.inputId, ref: el => (this.selectElement = el), class: "non-filterable-text", tabIndex: this.disabled ? -1 : 0 }, this.getSelectedLabel() || this.value || this.placeholder)), this.clearable &&
|
|
738
|
+
!this.disabled &&
|
|
739
|
+
!this.readonly &&
|
|
740
|
+
(this.value || (this.filterable && this.filterText)) && (h("nv-iconbutton", { key: 'b467a3949af859fe4e9d19f810a19a8e1d1834c9', ref: el => (this.clearElement = el), "data-scope": "clear", name: "x", size: "md", emphasis: "lower", class: "clear-button", onMouseDown: (e) => e.preventDefault(), onClick: this.handleClearButtonClick, "aria-label": this.value ? 'Clear selection' : 'Clear input', title: this.value ? 'Clear selection' : 'Clear input' })), this.error && (h("nv-icon", { key: '2c05d617da93adddd4994c3063b0e6fe7be017c7', name: "alert-circle", class: "validation", size: "md" })), h("nv-iconbutton", { key: '372a295a58b391a61d240d5133b427c3ddf1edba', "data-scope": "toggle-dropdown", ref: el => (this.toggleElement = el), name: this.open ? 'chevron-top' : 'chevron-down', size: "md", emphasis: "lower", "aria-label": this.open ? 'Hide dropdown' : 'Show dropdown', onClick: this.syncToggleDropdown.bind(this), tabIndex: this.disabled ? -1 : 0 })), h("slot", { key: '95db16c591f0bf7dec95550260b9d6bcd7e084a9', name: "after-input" })), h("div", { key: '46372589dee8ff8509570bd1a3cc33763cf17869', slot: "content", style: this.maxHeight ? { maxHeight: this.maxHeight } : {} }, (this.options?.length ?? 0) > 0 && (h("ul", { key: 'dc2840ef3e798291e49ae179a978c5b3d277ffa2' }, this.options?.map(option => (h("nv-fielddropdownitem", { label: option.label, value: option.value, disabled: option.disabled, selected: option.value === this.value }))))), h("slot", { key: '750ef13e5911fe9bfc9a277b24150a1d3e631d4d', name: "content" }))), (this.description ||
|
|
741
|
+
this.el.querySelector('[slot="description"]')) && (h("div", { key: '34e1fbd85f790f0ea38502d10daadabf2c26c493', class: "description" }, h("slot", { key: '248779124cefa199c5ee3b664c1a26ddfab0d849', name: "description" }, this.description))), (this.errorDescription ||
|
|
742
|
+
this.el.querySelector('[slot="error-description"]')) && (h("div", { key: 'dff99dce8c08ca76a620cf199147a72a0624b3be', hidden: !this.error, class: "error-description" }, h("slot", { key: 'fcdbc2a466f9d13593a5fb6d7a2ba719b0df19dd', name: "error-description" }, this.errorDescription)))));
|
|
666
743
|
}
|
|
667
744
|
static get is() { return "nv-fielddropdown"; }
|
|
668
745
|
static get formAssociated() { return true; }
|
|
@@ -1014,6 +1091,26 @@ export class NvFielddropdown {
|
|
|
1014
1091
|
"attribute": "filterable",
|
|
1015
1092
|
"defaultValue": "false"
|
|
1016
1093
|
},
|
|
1094
|
+
"clearable": {
|
|
1095
|
+
"type": "boolean",
|
|
1096
|
+
"mutable": false,
|
|
1097
|
+
"complexType": {
|
|
1098
|
+
"original": "boolean",
|
|
1099
|
+
"resolved": "boolean",
|
|
1100
|
+
"references": {}
|
|
1101
|
+
},
|
|
1102
|
+
"required": false,
|
|
1103
|
+
"optional": false,
|
|
1104
|
+
"docs": {
|
|
1105
|
+
"tags": [],
|
|
1106
|
+
"text": "Shows the inline clear (\u00D7) button when a value is selected (or when\nfilterable and the user has typed). The programmatic `clear()` method\nworks regardless of this prop \u2014 leave it off when you want to manage\nclearing the selection from outside the component."
|
|
1107
|
+
},
|
|
1108
|
+
"getter": false,
|
|
1109
|
+
"setter": false,
|
|
1110
|
+
"reflect": true,
|
|
1111
|
+
"attribute": "clearable",
|
|
1112
|
+
"defaultValue": "false"
|
|
1113
|
+
},
|
|
1017
1114
|
"openOnSelect": {
|
|
1018
1115
|
"type": "boolean",
|
|
1019
1116
|
"mutable": false,
|
|
@@ -1352,6 +1449,21 @@ export class NvFielddropdown {
|
|
|
1352
1449
|
"resolved": "string",
|
|
1353
1450
|
"references": {}
|
|
1354
1451
|
}
|
|
1452
|
+
}, {
|
|
1453
|
+
"method": "cleared",
|
|
1454
|
+
"name": "cleared",
|
|
1455
|
+
"bubbles": false,
|
|
1456
|
+
"cancelable": true,
|
|
1457
|
+
"composed": true,
|
|
1458
|
+
"docs": {
|
|
1459
|
+
"tags": [],
|
|
1460
|
+
"text": "Emitted when the field is cleared via the inline clear button or the\nprogrammatic `clear()` method. Useful for reacting to user-initiated\nclears without subscribing to every `valueChanged` emission."
|
|
1461
|
+
},
|
|
1462
|
+
"complexType": {
|
|
1463
|
+
"original": "void",
|
|
1464
|
+
"resolved": "void",
|
|
1465
|
+
"references": {}
|
|
1466
|
+
}
|
|
1355
1467
|
}, {
|
|
1356
1468
|
"method": "openChanged",
|
|
1357
1469
|
"name": "openChanged",
|
|
@@ -1413,6 +1525,23 @@ export class NvFielddropdown {
|
|
|
1413
1525
|
"tags": []
|
|
1414
1526
|
}
|
|
1415
1527
|
},
|
|
1528
|
+
"clear": {
|
|
1529
|
+
"complexType": {
|
|
1530
|
+
"signature": "() => Promise<void>",
|
|
1531
|
+
"parameters": [],
|
|
1532
|
+
"references": {
|
|
1533
|
+
"Promise": {
|
|
1534
|
+
"location": "global",
|
|
1535
|
+
"id": "global::Promise"
|
|
1536
|
+
}
|
|
1537
|
+
},
|
|
1538
|
+
"return": "Promise<void>"
|
|
1539
|
+
},
|
|
1540
|
+
"docs": {
|
|
1541
|
+
"text": "Clears the current selection. Resets the value to an empty string,\nremoves the selected state from items, clears the filter text (when\nfilterable) and emits `valueChanged` (and `filterTextChanged` when the\nfilter was reset). Emits `cleared` when anything was actually reset.",
|
|
1542
|
+
"tags": []
|
|
1543
|
+
}
|
|
1544
|
+
},
|
|
1416
1545
|
"toggleDropdown": {
|
|
1417
1546
|
"complexType": {
|
|
1418
1547
|
"signature": "(open?: boolean) => Promise<void>",
|
|
@@ -9,13 +9,13 @@ const NvFielddropdownitemDocs = {
|
|
|
9
9
|
{
|
|
10
10
|
name: 'Default',
|
|
11
11
|
description: 'Basic dropdown item within a fielddropdown',
|
|
12
|
-
template: (h("nv-fielddropdown", { label: "Select an option" }, h("nv-fielddropdownitem", { "data-storybook-args": true, value: "item1" }, "Item 1"), h("nv-fielddropdownitem", { value: "item2" }, "Item 2"), h("nv-fielddropdownitem", { value: "item3" }, "Item 3"))),
|
|
12
|
+
template: (h("nv-fielddropdown", { label: "Select an option" }, h("ul", { slot: "content" }, h("nv-fielddropdownitem", { "data-storybook-args": true, value: "item1" }, "Item 1"), h("nv-fielddropdownitem", { value: "item2" }, "Item 2"), h("nv-fielddropdownitem", { value: "item3" }, "Item 3")))),
|
|
13
13
|
},
|
|
14
14
|
// value
|
|
15
15
|
{
|
|
16
16
|
name: nameof(x => x.value),
|
|
17
17
|
description: 'Dropdown item with a specific value',
|
|
18
|
-
template: (h("nv-fielddropdown", { label: "Select a city" }, h("nv-fielddropdownitem", { value: "paris" }, "Paris"), h("nv-fielddropdownitem", { "data-storybook-args": true, value: "london" }, "London"), h("nv-fielddropdownitem", { value: "tokyo" }, "Tokyo"))),
|
|
18
|
+
template: (h("nv-fielddropdown", { label: "Select a city" }, h("ul", { slot: "content" }, h("nv-fielddropdownitem", { value: "paris" }, "Paris"), h("nv-fielddropdownitem", { "data-storybook-args": true, value: "london" }, "London"), h("nv-fielddropdownitem", { value: "tokyo" }, "Tokyo")))),
|
|
19
19
|
},
|
|
20
20
|
// disabled
|
|
21
21
|
{
|
|
@@ -24,7 +24,7 @@ const NvFielddropdownitemDocs = {
|
|
|
24
24
|
args: {
|
|
25
25
|
disabled: true,
|
|
26
26
|
},
|
|
27
|
-
template: (h("nv-fielddropdown", { label: "Select an option" }, h("nv-fielddropdownitem", { value: "item1" }, "Item 1"), h("nv-fielddropdownitem", { "data-storybook-args": true, value: "item2", disabled: true }, "Item 2 (Disabled)"), h("nv-fielddropdownitem", { value: "item3" }, "Item 3"))),
|
|
27
|
+
template: (h("nv-fielddropdown", { label: "Select an option" }, h("ul", { slot: "content" }, h("nv-fielddropdownitem", { value: "item1" }, "Item 1"), h("nv-fielddropdownitem", { "data-storybook-args": true, value: "item2", disabled: true }, "Item 2 (Disabled)"), h("nv-fielddropdownitem", { value: "item3" }, "Item 3")))),
|
|
28
28
|
},
|
|
29
29
|
// detached
|
|
30
30
|
{
|
|
@@ -33,25 +33,25 @@ const NvFielddropdownitemDocs = {
|
|
|
33
33
|
args: {
|
|
34
34
|
detached: true,
|
|
35
35
|
},
|
|
36
|
-
template: (h("nv-fielddropdown", { label: "Search items", filterable: true }, h("nv-fielddropdownitem", { "data-storybook-args": true, value: "all", detached: true }, "All Items"), h("nv-fielddropdownitem", { value: "item1" }, "Item 1"), h("nv-fielddropdownitem", { value: "item2" }, "Item 2"), h("nv-fielddropdownitem", { value: "item3" }, "Item 3"))),
|
|
36
|
+
template: (h("nv-fielddropdown", { label: "Search items", filterable: true }, h("ul", { slot: "content" }, h("nv-fielddropdownitem", { "data-storybook-args": true, value: "all", detached: true }, "All Items"), h("nv-fielddropdownitem", { value: "item1" }, "Item 1"), h("nv-fielddropdownitem", { value: "item2" }, "Item 2"), h("nv-fielddropdownitem", { value: "item3" }, "Item 3")))),
|
|
37
37
|
},
|
|
38
38
|
// WithIcon
|
|
39
39
|
{
|
|
40
40
|
name: 'WithIcon',
|
|
41
41
|
description: 'Dropdown item with leading icon',
|
|
42
|
-
template: (h("nv-fielddropdown", { label: "Select with icons" }, h("nv-fielddropdownitem", { value: "home" }, h("nv-icon", { slot: "leading-icon", name: "home" }), "Home"), h("nv-fielddropdownitem", { value: "user" }, h("nv-icon", { slot: "leading-icon", name: "user" }), "Profile"), h("nv-fielddropdownitem", { value: "settings" }, h("nv-icon", { slot: "leading-icon", name: "settings" }), "Settings"))),
|
|
42
|
+
template: (h("nv-fielddropdown", { label: "Select with icons" }, h("ul", { slot: "content" }, h("nv-fielddropdownitem", { value: "home" }, h("nv-icon", { slot: "leading-icon", name: "home" }), "Home"), h("nv-fielddropdownitem", { value: "user" }, h("nv-icon", { slot: "leading-icon", name: "user" }), "Profile"), h("nv-fielddropdownitem", { value: "settings" }, h("nv-icon", { slot: "leading-icon", name: "settings" }), "Settings")))),
|
|
43
43
|
},
|
|
44
44
|
// WithAvatar
|
|
45
45
|
{
|
|
46
46
|
name: 'WithAvatar',
|
|
47
47
|
description: 'Dropdown item with avatar',
|
|
48
|
-
template: (h("nv-fielddropdown", { label: "Select user" }, h("nv-fielddropdownitem", { value: "user1" }, h("nv-avatar", { slot: "leading-icon", initials: "JD", size: "xs" }), "John Doe"), h("nv-fielddropdownitem", { value: "user2" }, h("nv-avatar", { slot: "leading-icon", initials: "JS", size: "xs" }), "Jane Smith"))),
|
|
48
|
+
template: (h("nv-fielddropdown", { label: "Select user" }, h("ul", { slot: "content" }, h("nv-fielddropdownitem", { value: "user1" }, h("nv-avatar", { slot: "leading-icon", initials: "JD", size: "xs" }), "John Doe"), h("nv-fielddropdownitem", { value: "user2" }, h("nv-avatar", { slot: "leading-icon", initials: "JS", size: "xs" }), "Jane Smith")))),
|
|
49
49
|
},
|
|
50
50
|
// WithBadge
|
|
51
51
|
{
|
|
52
52
|
name: 'WithBadge',
|
|
53
53
|
description: 'Dropdown item with trailing badge',
|
|
54
|
-
template: (h("nv-fielddropdown", { label: "Select status" }, h("nv-fielddropdownitem", { value: "active" }, "Active", h("nv-badge", { slot: "trailing-icon", color: "success", label: "New" })), h("nv-fielddropdownitem", { value: "pending" }, "Pending", h("nv-badge", { slot: "trailing-icon", color: "warning", label: "3" })), h("nv-fielddropdownitem", { value: "inactive" }, "Inactive"))),
|
|
54
|
+
template: (h("nv-fielddropdown", { label: "Select status" }, h("ul", { slot: "content" }, h("nv-fielddropdownitem", { value: "active" }, "Active", h("nv-badge", { slot: "trailing-icon", color: "success", label: "New" })), h("nv-fielddropdownitem", { value: "pending" }, "Pending", h("nv-badge", { slot: "trailing-icon", color: "warning", label: "3" })), h("nv-fielddropdownitem", { value: "inactive" }, "Inactive")))),
|
|
55
55
|
},
|
|
56
56
|
],
|
|
57
57
|
};
|
|
@@ -53,7 +53,7 @@ export class NvFielddropdownitem {
|
|
|
53
53
|
/****************************************************************************/
|
|
54
54
|
//#region RENDER
|
|
55
55
|
render() {
|
|
56
|
-
return (h(Host, { key: '9931decf5664d77d8c164859bc4046ca313e13a9', role: "menuitem", tabindex: '-1', onClick: this.handleSelected }, h("
|
|
56
|
+
return (h(Host, { key: '9931decf5664d77d8c164859bc4046ca313e13a9', role: "menuitem", tabindex: '-1', onClick: this.handleSelected }, this.selected && (h("nv-icon", { key: 'aba64f319fb37bc8f471ebd65d00d0f17158fe41', name: "check", "aria-hidden": "true", "data-scope": "selected" })), h("slot", { key: 'ffafa2e39d704caa576d59bba459503be10f4ffc' }, h("div", { key: '065293dca56bfaec8f89910f88b92a52907fcf28', class: "text-wrapper" }, h("span", { key: '2f85b57db26203bc19b32047707f9281a6d906a0', "data-scope": "text" }, this.label)))));
|
|
57
57
|
}
|
|
58
58
|
static get is() { return "nv-fielddropdownitem"; }
|
|
59
59
|
static get originalStyleUrls() {
|
|
@@ -197,6 +197,17 @@ const NvFieldselectDocs = {
|
|
|
197
197
|
},
|
|
198
198
|
template: (h("nv-fieldselect", { "data-storybook-args": true }, h("option", { value: "1" }, "Option 1"), h("option", { value: "2" }, "Option 2"))),
|
|
199
199
|
},
|
|
200
|
+
// clearable
|
|
201
|
+
{
|
|
202
|
+
name: nameof(x => x.clearable),
|
|
203
|
+
description: 'When set, an inline clear (×) button appears whenever a value is selected so users can wipe the selection in one click. The programmatic `clear()` method works regardless of this prop.',
|
|
204
|
+
args: {
|
|
205
|
+
label: 'Select with clear button',
|
|
206
|
+
value: '2',
|
|
207
|
+
clearable: true,
|
|
208
|
+
},
|
|
209
|
+
template: (h("nv-fieldselect", { "data-storybook-args": true }, h("option", { value: "1" }, "Option 1"), h("option", { value: "2" }, "Option 2"), h("option", { value: "3" }, "Option 3"))),
|
|
210
|
+
},
|
|
200
211
|
// Placeholder
|
|
201
212
|
{
|
|
202
213
|
name: 'Placeholder',
|
|
@@ -68,6 +68,12 @@ export class NvFieldselect {
|
|
|
68
68
|
* When enabled, allows the select to handle multiple selections.
|
|
69
69
|
*/
|
|
70
70
|
this.multiple = false;
|
|
71
|
+
/**
|
|
72
|
+
* Shows the inline clear (×) button when a value is selected. The
|
|
73
|
+
* programmatic `clear()` method works regardless of this prop — leave
|
|
74
|
+
* it off when you want to manage clearing from outside the component.
|
|
75
|
+
*/
|
|
76
|
+
this.clearable = false;
|
|
71
77
|
/**
|
|
72
78
|
* The value of the select field.
|
|
73
79
|
* - If `multiple` is `false`, it's a single string.
|
|
@@ -121,6 +127,21 @@ export class NvFieldselect {
|
|
|
121
127
|
this.selectElement.focus();
|
|
122
128
|
}
|
|
123
129
|
};
|
|
130
|
+
/**
|
|
131
|
+
* Handles a click on the inline clear button. Stops the click from
|
|
132
|
+
* bubbling up to the select container (which would refocus the select)
|
|
133
|
+
* and clears the value. On keyboard activation (Enter/Space) it also
|
|
134
|
+
* moves focus back to the native `<select>` so keyboard users don't
|
|
135
|
+
* lose their place when the button disappears.
|
|
136
|
+
* @param {MouseEvent} event - The click event from the clear button.
|
|
137
|
+
*/
|
|
138
|
+
this.handleClearButtonClick = (event) => {
|
|
139
|
+
event.stopPropagation();
|
|
140
|
+
this.clear();
|
|
141
|
+
// detail === 0 means keyboard-activated; >= 1 means a real mouse click.
|
|
142
|
+
if (event.detail === 0)
|
|
143
|
+
this.selectElement?.focus();
|
|
144
|
+
};
|
|
124
145
|
}
|
|
125
146
|
//#endregion EVENTS
|
|
126
147
|
/****************************************************************************/
|
|
@@ -252,6 +273,19 @@ export class NvFieldselect {
|
|
|
252
273
|
this.selectElement = this.el.querySelector('select');
|
|
253
274
|
}
|
|
254
275
|
}
|
|
276
|
+
/**
|
|
277
|
+
* Clears the current selection. Resets the value to an empty string and
|
|
278
|
+
* emits `valueChanged` and `cleared` when the value actually changed.
|
|
279
|
+
* The `@Watch('value')` watcher takes care of syncing the underlying
|
|
280
|
+
* native `<select>` options and the form value.
|
|
281
|
+
*/
|
|
282
|
+
async clear() {
|
|
283
|
+
if (!this.value)
|
|
284
|
+
return;
|
|
285
|
+
this.value = '';
|
|
286
|
+
this.valueChanged.emit('');
|
|
287
|
+
this.cleared.emit();
|
|
288
|
+
}
|
|
255
289
|
//#endregion METHODS
|
|
256
290
|
/****************************************************************************/
|
|
257
291
|
//#region LIFECYCLE
|
|
@@ -372,15 +406,18 @@ export class NvFieldselect {
|
|
|
372
406
|
? ariaRequiredAttrValue === 'true' || ariaRequiredAttrValue === ''
|
|
373
407
|
: undefined;
|
|
374
408
|
const useNativeRequired = this.required && (!useAriaRequired || ariaRequiredValue === true);
|
|
375
|
-
return (h(Host, { key: '
|
|
409
|
+
return (h(Host, { key: '94e1f6453200ac25c9a8bb1161da1332fe964a88' }, (this.label || this.el.querySelector('[slot="label"]')) && (h("label", { key: 'cddbd8dcb267c3931f2a97d2409732e203e60d42', htmlFor: this.inputId }, h("slot", { key: 'bfbae02481c4bdac23e2c7c69044c171c2e4c627', name: "label" }, this.label))), h("div", { key: '1070a34841596517c2803aa529b875c86e1cace7', class: "select-wrapper" }, h("slot", { key: '8a36b232f72dcf98aaa0fd1d3fe0ee4a77102254', name: "before-input" }), h("div", { key: '716bd6d6f489b1b23d4f97ddf8b404c9b06cbb6d', class: "select-container", onClick: this.handleSelectContainerClick }, h("slot", { key: '282b5103ab923c70d66fb5cbf68bb741f2f9c436', name: "leading-input" }), this.internalReadonly && (h("input", { key: 'a612673aec7e0fb2a63c0d52a68bc2f74332db44', id: this.inputId + '-readonly', type: "text", value: this.computedDisplayValue, readonly: true, class: "readonly-input", "aria-readonly": "true", "aria-label": this.label, "aria-describedby": this.error
|
|
376
410
|
? `${this.inputId}-error`
|
|
377
|
-
: `${this.inputId}-description` })), h("select", { key: '
|
|
411
|
+
: `${this.inputId}-description` })), h("select", { key: '4fe11669e745846bcc14e3c657160287912351f2', id: this.inputId, ref: el => (this.selectElement = el), name: this.name, autofocus: this.autofocus, disabled: this.disabled, required: useNativeRequired ? this.required : undefined, ...(ariaRequiredValue !== undefined && {
|
|
378
412
|
'aria-required': String(ariaRequiredValue),
|
|
379
413
|
}), multiple: this.multiple, onChange: this.handleSelectChange, class: this.internalReadonly ? 'hidden' : '', "aria-label": this.label, "aria-describedby": this.error
|
|
380
414
|
? `${this.inputId}-error`
|
|
381
|
-
: `${this.inputId}-description` }, this.options && this.options.length > 0 ? (this.options.map(option => (h("option", { value: option.value, selected: option.selected, disabled: option.disabled }, option.label)))) : (h("slot", null))), h("div", { key: '
|
|
382
|
-
this.
|
|
383
|
-
this.
|
|
415
|
+
: `${this.inputId}-description` }, this.options && this.options.length > 0 ? (this.options.map(option => (h("option", { value: option.value, selected: option.selected, disabled: option.disabled }, option.label)))) : (h("slot", null))), h("div", { key: 'e04e676525522d40410815ea8da80f9c18730e3f', class: "select-icons" }, this.clearable &&
|
|
416
|
+
!this.disabled &&
|
|
417
|
+
!this.internalReadonly &&
|
|
418
|
+
this.value && (h("nv-iconbutton", { key: '176fdf45a3c04290895be367027c38581292c2c0', "data-scope": "clear", name: "x", size: "md", emphasis: "lower", class: "clear-button", onMouseDown: (e) => e.preventDefault(), onClick: this.handleClearButtonClick, "aria-label": "Clear selection", title: "Clear selection" })), this.error && (h("nv-icon", { key: '7eef5e80d744b7bfbcfb3fc857837c58e6ce4e54', name: "alert-circle", class: "validation", size: "md" })), this.success && (h("nv-icon", { key: '68085ced60e2c9aa70aa26db8fa96f0a5407d3c4', name: "circle-check", class: "validation", size: "md" })), !this.multiple && (h("nv-iconbutton", { key: 'c1e85cc79e3438f20ae891fb439b77ba694d8db8', name: "chevron-down", size: "md", emphasis: "lower", tabindex: -1 })))), h("slot", { key: '5534a2610d76d6d23e91ca3010b29f331501c923', name: "after-input" })), (this.description ||
|
|
419
|
+
this.el.querySelector('[slot="description"]')) && (h("div", { key: 'eda00100479bb6325a49db62933f7d325e559491', class: "description", id: `${this.inputId}-description` }, h("slot", { key: 'f976d87998ef48b7e1e493f6064547efa1c212c3', name: "description" }, this.description))), (this.errorDescription ||
|
|
420
|
+
this.el.querySelector('[slot="error-description"]')) && (h("div", { key: '28d55210a573fe85b57752873ca14f0adc65a404', class: "error-description", id: `${this.inputId}-error` }, h("slot", { key: 'ac95ef49e88372d3b69456affbbdaad753a5e5c4', name: "error-description" }, this.errorDescription)))));
|
|
384
421
|
}
|
|
385
422
|
static get is() { return "nv-fieldselect"; }
|
|
386
423
|
static get formAssociated() { return true; }
|
|
@@ -713,6 +750,26 @@ export class NvFieldselect {
|
|
|
713
750
|
"attribute": "multiple",
|
|
714
751
|
"defaultValue": "false"
|
|
715
752
|
},
|
|
753
|
+
"clearable": {
|
|
754
|
+
"type": "boolean",
|
|
755
|
+
"mutable": false,
|
|
756
|
+
"complexType": {
|
|
757
|
+
"original": "boolean",
|
|
758
|
+
"resolved": "boolean",
|
|
759
|
+
"references": {}
|
|
760
|
+
},
|
|
761
|
+
"required": false,
|
|
762
|
+
"optional": false,
|
|
763
|
+
"docs": {
|
|
764
|
+
"tags": [],
|
|
765
|
+
"text": "Shows the inline clear (\u00D7) button when a value is selected. The\nprogrammatic `clear()` method works regardless of this prop \u2014 leave\nit off when you want to manage clearing from outside the component."
|
|
766
|
+
},
|
|
767
|
+
"getter": false,
|
|
768
|
+
"setter": false,
|
|
769
|
+
"reflect": true,
|
|
770
|
+
"attribute": "clearable",
|
|
771
|
+
"defaultValue": "false"
|
|
772
|
+
},
|
|
716
773
|
"value": {
|
|
717
774
|
"type": "string",
|
|
718
775
|
"mutable": true,
|
|
@@ -820,8 +877,44 @@ export class NvFieldselect {
|
|
|
820
877
|
"resolved": "string",
|
|
821
878
|
"references": {}
|
|
822
879
|
}
|
|
880
|
+
}, {
|
|
881
|
+
"method": "cleared",
|
|
882
|
+
"name": "cleared",
|
|
883
|
+
"bubbles": false,
|
|
884
|
+
"cancelable": true,
|
|
885
|
+
"composed": true,
|
|
886
|
+
"docs": {
|
|
887
|
+
"tags": [],
|
|
888
|
+
"text": "Emitted when the field is cleared via the inline clear button or the\nprogrammatic `clear()` method. Useful for reacting to user-initiated\nclears without subscribing to every `valueChanged` emission."
|
|
889
|
+
},
|
|
890
|
+
"complexType": {
|
|
891
|
+
"original": "void",
|
|
892
|
+
"resolved": "void",
|
|
893
|
+
"references": {}
|
|
894
|
+
}
|
|
823
895
|
}];
|
|
824
896
|
}
|
|
897
|
+
static get methods() {
|
|
898
|
+
return {
|
|
899
|
+
"clear": {
|
|
900
|
+
"complexType": {
|
|
901
|
+
"signature": "() => Promise<void>",
|
|
902
|
+
"parameters": [],
|
|
903
|
+
"references": {
|
|
904
|
+
"Promise": {
|
|
905
|
+
"location": "global",
|
|
906
|
+
"id": "global::Promise"
|
|
907
|
+
}
|
|
908
|
+
},
|
|
909
|
+
"return": "Promise<void>"
|
|
910
|
+
},
|
|
911
|
+
"docs": {
|
|
912
|
+
"text": "Clears the current selection. Resets the value to an empty string and\nemits `valueChanged` and `cleared` when the value actually changed.\nThe `@Watch('value')` watcher takes care of syncing the underlying\nnative `<select>` options and the form value.",
|
|
913
|
+
"tags": []
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
};
|
|
917
|
+
}
|
|
825
918
|
static get elementRef() { return "el"; }
|
|
826
919
|
static get watchers() {
|
|
827
920
|
return [{
|
|
@@ -164,6 +164,9 @@ nv-fieldselect .select-wrapper .select-container > .select-icons > nv-iconbutton
|
|
|
164
164
|
border-top-right-radius: var(--form-field-radius);
|
|
165
165
|
border-bottom-right-radius: var(--form-field-radius);
|
|
166
166
|
}
|
|
167
|
+
nv-fieldselect .select-wrapper .select-container > .select-icons > nv-iconbutton.clear-button {
|
|
168
|
+
pointer-events: auto;
|
|
169
|
+
}
|
|
167
170
|
nv-fieldselect .select-wrapper .select-container input {
|
|
168
171
|
display: flex;
|
|
169
172
|
align-items: center;
|
|
@@ -464,11 +464,11 @@ export class NvFieldslider {
|
|
|
464
464
|
/****************************************************************************/
|
|
465
465
|
//#region RENDER
|
|
466
466
|
render() {
|
|
467
|
-
return (h(Host, { key: '
|
|
467
|
+
return (h(Host, { key: '6426519f29a4a345a2371ef6ba05c6e2f59fd01f' }, (this.label || this.el.querySelector('[slot="label"]')) && (h("label", { key: '83583c4f6610032c5ba3b2b6e0d58a1ce6117f8a', htmlFor: this.startInputId }, h("slot", { key: '91bf1a9106d9044e8180b6115510764904d39c15', name: "label" }, this.label))), h("div", { key: 'f5154fb1aa800cda282c924e2ff036df6ba70969', class: "slider-container" }, this.range ? (h(FieldInput, { range: this.range, hasField: this.hasField, value: this.valueInternal, rangeValue: this.rangeValueInternal, index: 0, inputId: this.startInputId, min: this.min, max: this.max, step: this.step, disabled: this.disabled, readonly: this.readonly, onInput: this.handleFieldChange, labelBeforeValue: this.labelBeforeValue, labelAfterValue: this.labelAfterValue, name: this.name, endName: this.endName })) : null, h("div", { key: '3a11f56bc52e1bb2ff0fb82e14488173dffa5d48', class: "track-container" }, h("div", { key: '48065424f96d4bff452bfb122217a30767563219', class: "track", onPointerDown: this.onTrackInteraction }, this.range ? (h(RangeThumb, { rangeValue: this.rangeValueInternal, rawRangePosition: this.rawRangePosition, activeDragThumb: this.activeDragThumb, isDragging: this.isDragging, snap: this.snap, min: this.min, max: this.max, step: this.step, disabled: this.disabled, readonly: this.readonly, onKeyDown: this.onKeyDown, labelBeforeValue: this.labelBeforeValue, labelAfterValue: this.labelAfterValue })) : (h(SingleThumb, { value: this.valueInternal, min: this.min, max: this.max, step: this.step, rawPosition: this.rawPosition, isDragging: this.isDragging, snap: this.snap, disabled: this.disabled, readonly: this.readonly, onKeyDown: this.onKeyDown, labelBeforeValue: this.labelBeforeValue, labelAfterValue: this.labelAfterValue }))), h(TickMarks, { key: '3c03a6c0bb8e8f24d076f29c178bd71eaf9cda0e', ticks: this.internalTicks, min: this.min, max: this.max })), this.range ? (h(FieldInput, { range: this.range, hasField: this.hasField, value: this.valueInternal, rangeValue: this.rangeValueInternal, index: 1, inputId: this.endInputId, min: this.min, max: this.max, step: this.step, disabled: this.disabled, readonly: this.readonly, onInput: this.handleFieldChange, labelBeforeValue: this.labelBeforeValue, labelAfterValue: this.labelAfterValue, name: this.name, endName: this.endName })) : (h(FieldInput, { range: this.range, hasField: this.hasField, value: this.valueInternal, rangeValue: this.rangeValueInternal, inputId: this.startInputId, min: this.min, max: this.max, step: this.step, disabled: this.disabled, readonly: this.readonly, onInput: this.handleFieldChange, labelBeforeValue: this.labelBeforeValue, labelAfterValue: this.labelAfterValue, name: this.name }))), (this.success ||
|
|
468
468
|
this.description ||
|
|
469
|
-
this.el.querySelector('[slot="description"]')) && (h("div", { key: '
|
|
469
|
+
this.el.querySelector('[slot="description"]')) && (h("div", { key: '7f2adaba3d758f14acc45e04636daca743264b53', class: "description" }, this.success && (h("nv-icon", { key: 'd499915841c2fb34e26af179e5fe1a592306c6ce', name: "circle-check", class: "validation", size: "md" })), h("slot", { key: 'bdd412849474b4ffaf5473005c1dad19cc9bb2ee', name: "description" }, this.description))), (this.error ||
|
|
470
470
|
this.errorDescription ||
|
|
471
|
-
this.el.querySelector('[slot="error-description"]')) && (h("div", { key: '
|
|
471
|
+
this.el.querySelector('[slot="error-description"]')) && (h("div", { key: 'b24b65aed4437a953fba34820a3cd6c385c246b7', class: "error-description", hidden: !this.error }, this.error && (h("nv-icon", { key: '76c21755d1f90aa3f2f64f03b20a57249f5ea568', name: "alert-circle", class: "validation", size: "md" })), h("slot", { key: '59d05da46df9e86b62f65db1d7ed967bb640675a', name: "error-description" }, this.errorDescription)))));
|
|
472
472
|
}
|
|
473
473
|
static get is() { return "nv-fieldslider"; }
|
|
474
474
|
static get formAssociated() { return true; }
|
|
@@ -148,11 +148,11 @@ export class NvFieldtext {
|
|
|
148
148
|
? ariaRequiredAttrValue === 'true' || ariaRequiredAttrValue === ''
|
|
149
149
|
: undefined;
|
|
150
150
|
const useNativeRequired = this.required && (!useAriaRequired || ariaRequiredValue === true);
|
|
151
|
-
return (h(Host, { key: '
|
|
151
|
+
return (h(Host, { key: '90ac165e82d023f829f92a29c96752034c23c9f2' }, (this.label || this.el.querySelector('[slot="label"]')) && (h("label", { key: 'f530f667afb8d7ca92b08091ed56334344a143f2', htmlFor: this.inputId }, h("slot", { key: 'fc47f6054630cabc3ad1990b015aa092f4aa4340', name: "label" }, this.label))), h("div", { key: '1e391ffe7dcf66df1ca71b0bdac6b2f6e1db0bbd', class: "input-wrapper" }, h("slot", { key: '10b6c0ba26cfa5746f49b5306fa50e9621abef2c', name: "before-input" }), h("div", { key: 'b4b09153ca8604d1b3e0196468fa76cc2a8f9241', class: "input-container", onClick: this.handleInputContainerClick }, h("slot", { key: '0eeca77278eafbc0387e70e4aa2393f094ac011c', name: "leading-input" }), h("input", { key: '6fe1319ef9d8b6f6adad33c6d7aa3fda31bdcbe3', id: this.inputId, ref: e => (this.inputElement = e), placeholder: this.placeholder, name: this.name, type: this.type, disabled: this.disabled, readOnly: this.readonly, required: useNativeRequired ? this.required : undefined, ...(ariaRequiredValue !== undefined && {
|
|
152
152
|
'aria-required': String(ariaRequiredValue),
|
|
153
|
-
}), maxlength: this.maxlength, minlength: this.minlength, pattern: this.pattern, autofocus: this.autofocus, autocomplete: this.autocomplete, multiple: this.multiple, value: this.value, onInput: this.handleInput }), h("slot", { key: '
|
|
154
|
-
this.el.querySelector('[slot="description"]')) && (h("div", { key: '
|
|
155
|
-
this.el.querySelector('[slot="error-description"]')) && (h("div", { key: '
|
|
153
|
+
}), maxlength: this.maxlength, minlength: this.minlength, pattern: this.pattern, autofocus: this.autofocus, autocomplete: this.autocomplete, multiple: this.multiple, value: this.value, onInput: this.handleInput }), h("slot", { key: '8371a6e3dda9c4d61a99246e675826c44b102f85', name: "trailing-input" }), this.error && (h("nv-icon", { key: 'a36ff6b50c314255cb0ff141d199da1da14c0d4e', name: "alert-circle", class: "validation", size: "md" })), this.success && (h("nv-icon", { key: 'b51a8059483bbc78d383b7cf71b5a90bfd2633a4', name: "circle-check", class: "validation", size: "md" }))), h("slot", { key: '6b7eb32b47c9b74e6a567a359617668e7256efcb', name: "after-input" })), (this.description ||
|
|
154
|
+
this.el.querySelector('[slot="description"]')) && (h("div", { key: 'ce97f38d7d31b18df36a92d75cd4dd7dd44063ab', class: "description" }, h("slot", { key: '92cc67f9b9c277e91316236c977e1bc9bd63a0c7', name: "description" }, this.description))), (this.errorDescription ||
|
|
155
|
+
this.el.querySelector('[slot="error-description"]')) && (h("div", { key: '44711fb351ac1da5da1a0f0630a1d7596957664d', hidden: !this.error, class: "error-description" }, h("slot", { key: '4645cc36a7383587f6baa8db0bb2b664f252768c', name: "error-description" }, this.errorDescription)))));
|
|
156
156
|
}
|
|
157
157
|
static get is() { return "nv-fieldtext"; }
|
|
158
158
|
static get formAssociated() { return true; }
|
|
@@ -215,11 +215,11 @@ export class NvFieldtextarea {
|
|
|
215
215
|
? ariaRequiredAttrValue === 'true' || ariaRequiredAttrValue === ''
|
|
216
216
|
: undefined;
|
|
217
217
|
const useNativeRequired = this.required && (!useAriaRequired || ariaRequiredValue === true);
|
|
218
|
-
return (h(Host, { key: '
|
|
218
|
+
return (h(Host, { key: '1cddc37522161a4316ae8f82d3daf285ffb785b5' }, (this.label || this.el.querySelector('[slot="label"]')) && (h("label", { key: '0c351922af13d881f90b17cea5d482fd45a34e65', htmlFor: this.inputId }, h("slot", { key: '665bee53de0fd1a1f076ecfcba06be68919881e0', name: "label" }, this.label))), h("div", { key: '22fc452a7657ea9b13a867d57b4242268dde2bca', class: "textarea-wrapper" }, h("div", { key: '333aace09346fae421a7a6654b1f6024fa0f87f7', class: "textarea-container", onClick: this.handleTextareaContainerClick }, h("textarea", { key: '69172853551f5cbb2fc739a13fa5299142b191c1', id: this.inputId, ref: e => (this.textareaElement = e), placeholder: this.placeholder, autofocus: this.autofocus, name: this.name, disabled: this.disabled, readOnly: this.readonly, required: useNativeRequired ? this.required : undefined, ...(ariaRequiredValue !== undefined && {
|
|
219
219
|
'aria-required': String(ariaRequiredValue),
|
|
220
220
|
}), maxlength: this.maxlength, minlength: this.minlength, autocomplete: "off", value: this.value, onInput: this.handleTextarea, rows: this.rows, class: clsx(this.resize === 'none' && 'resize-none', this.resize === 'vertical' && 'resize-y', this.resize === 'horizontal' && 'resize-x', this.resize === 'both' && 'resize') }))), (this.description ||
|
|
221
|
-
this.el.querySelector('[slot="description"]')) && (h("div", { key: '
|
|
222
|
-
this.el.querySelector('[slot="error-description"]')) && (h("div", { key: '
|
|
221
|
+
this.el.querySelector('[slot="description"]')) && (h("div", { key: '91fc165e6275f96547eea666d643f9bd5184d06f', class: "description" }, h("slot", { key: '996a87505c112d9cb5c1a6d7877e6bc88ab14556', name: "description" }, this.description))), (this.errorDescription ||
|
|
222
|
+
this.el.querySelector('[slot="error-description"]')) && (h("div", { key: '3d105e76819ca671aa6c23722344ba9acfe90f38', hidden: !this.error, class: "error-description" }, h("slot", { key: '7d721e77b392dbb0bdcf6892f4237f0d8d944c64', name: "error-description" }, this.errorDescription)))));
|
|
223
223
|
}
|
|
224
224
|
static get is() { return "nv-fieldtextarea"; }
|
|
225
225
|
static get formAssociated() { return true; }
|