@nova-design-system/nova-react 3.22.0 → 3.24.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.
Files changed (91) hide show
  1. package/dist/cjs/_commonjsHelpers-B85MJLTf-CFO10eej.js +7 -0
  2. package/dist/cjs/{collapse.animation-6e0b08df-AHWzNGm_.js → collapse.animation-DZDm0vSK-C2TOIhIK.js} +3 -3
  3. package/dist/cjs/events.utils-B6GgGra--01N__3wY.js +23 -0
  4. package/dist/cjs/{fade.animation-9b939939-DV--bM4S.js → fade.animation-DcRL9lcm-DAZeHoKN.js} +75 -75
  5. package/dist/cjs/generated/components.server.js +292 -50
  6. package/dist/cjs/{grow.animation-24ad5cf8-LUp_ITEx.js → grow.animation-D7ep_aVl-BuXEDSK-.js} +5 -26
  7. package/dist/cjs/i18n.utils-IlwlcG9l-ku0bScip.js +2494 -0
  8. package/dist/cjs/{index-WPRkQD3O.js → index-kU2nW5aN.js} +12692 -7009
  9. package/dist/cjs/{nv-dialog.entry-CDSK9pUH.js → index.esm-D3eWMME9-CG1TVKfu.js} +1 -296
  10. package/dist/cjs/index.js +15 -1
  11. package/dist/cjs/inputmask-CSo292ul-DlvupPk6.js +3758 -0
  12. package/dist/cjs/{nv-accordion-item.entry-BuTvA6w9.js → nv-accordion-item.entry-Bu1tAcCq.js} +11 -10
  13. package/dist/cjs/{nv-accordion.entry-Dtsfw6He.js → nv-accordion.entry-jWjLdX8w.js} +9 -11
  14. package/dist/cjs/{nv-alert.entry-TIdfdU7Y.js → nv-alert.entry-E9ZJay_K.js} +22 -23
  15. package/dist/cjs/{nv-avatar.entry-CaxrhPuw.js → nv-avatar.entry-CUX7u0kR.js} +11 -11
  16. package/dist/cjs/{nv-badge_2.entry-CfYvTZxX.js → nv-badge_2.entry-bxpV5gxE.js} +24 -24
  17. package/dist/cjs/{nv-breadcrumb.entry-BCZ4MmfD.js → nv-breadcrumb.entry-Cbbb9Qeh.js} +5 -5
  18. package/dist/cjs/{nv-breadcrumbs.entry-DwzCE7F6.js → nv-breadcrumbs.entry-BTqnp9zO.js} +3 -3
  19. package/dist/cjs/{nv-button.entry-Cr_86bcZ.js → nv-button.entry-upWH19y6.js} +12 -14
  20. package/dist/cjs/{nv-buttongroup.entry-CWjRoHY1.js → nv-buttongroup.entry-CuZCRsnV.js} +3 -3
  21. package/dist/cjs/{nv-calendar.entry-CXfwNt6G.js → nv-calendar.entry-CT3mASW6.js} +113 -97
  22. package/dist/cjs/{nv-col.entry-CJLDS3LY.js → nv-col.entry--pCxkaTh.js} +5 -5
  23. package/dist/cjs/{nv-datagrid.entry-Cns8XSud.js → nv-datagrid.entry-CGCEhO8C.js} +80 -85
  24. package/dist/cjs/{nv-datagridcolumn.entry-CFFAipHF.js → nv-datagridcolumn.entry-Fsqc7CT_.js} +2 -1
  25. package/dist/cjs/nv-dialog.entry-B6OYcZxQ.js +300 -0
  26. package/dist/cjs/{nv-dialogfooter_2.entry-To_dGUn4.js → nv-dialogfooter_2.entry-C4fP_n2-.js} +10 -11
  27. package/dist/cjs/nv-drawer.entry-C5O4KvHU.js +445 -0
  28. package/dist/cjs/nv-drawerfooter_2.entry-C-reYJXG.js +146 -0
  29. package/dist/cjs/nv-fieldcheckbox.entry-bk7UNQny.js +177 -0
  30. package/dist/cjs/{nv-fielddate.entry-C3pXtMHL.js → nv-fielddate.entry-dqZDBVmm.js} +89 -46
  31. package/dist/cjs/{nv-fielddaterange.entry-CjVVPEK_.js → nv-fielddaterange.entry-wNRasXky.js} +151 -103
  32. package/dist/cjs/nv-fielddropdown.entry-BA15piWa.js +678 -0
  33. package/dist/cjs/{nv-fielddropdownitem.entry-Dah-PaE8.js → nv-fielddropdownitem.entry-DEWaf9dC.js} +7 -7
  34. package/dist/cjs/{nv-fieldmultiselect.entry-BMLjhqoJ.js → nv-fieldmultiselect.entry-BWY5xOAd.js} +343 -236
  35. package/dist/cjs/nv-fieldnumber.entry-DoYORd0d.js +187 -0
  36. package/dist/cjs/nv-fieldpassword.entry-CPaLj9aD.js +165 -0
  37. package/dist/cjs/{nv-fieldradio.entry-X_2VT1Dj.js → nv-fieldradio.entry-CvUmEaCa.js} +11 -11
  38. package/dist/cjs/{nv-fieldselect.entry-pSp-2rNn.js → nv-fieldselect.entry-uUIZ6hmN.js} +52 -13
  39. package/dist/cjs/{nv-fieldslider.entry-pZf7zzLU.js → nv-fieldslider.entry-DnvmxxYY.js} +16 -31
  40. package/dist/cjs/nv-fieldtext.entry-BYAJp3n_.js +163 -0
  41. package/dist/cjs/{nv-fieldtextarea.entry-t3Ixxi23.js → nv-fieldtextarea.entry-DU2bWYeg.js} +52 -14
  42. package/dist/cjs/{nv-fieldtime.entry-DY7D5_6K.js → nv-fieldtime.entry-DlMNDTht.js} +128 -84
  43. package/dist/cjs/{nv-icon.entry-6oYPSf4c.js → nv-icon.entry-CnUkRzaA.js} +12 -12
  44. package/dist/cjs/{nv-iconbutton_2.entry-ChULGovr.js → nv-iconbutton_2.entry-hqp4AcRq.js} +10 -12
  45. package/dist/cjs/{nv-menu.entry-sd0tatWq.js → nv-menu.entry-Dc_FvIx7.js} +18 -32
  46. package/dist/cjs/{nv-menuitem.entry-CCOqR7UF.js → nv-menuitem.entry-DzMhx6c_.js} +6 -5
  47. package/dist/cjs/nv-notification-bullet.entry-BwhHCMQF.js +76 -0
  48. package/dist/cjs/{nv-notification.entry-Cc3zE3yY.js → nv-notification.entry-C3m5p5BL.js} +42 -128
  49. package/dist/cjs/{nv-notificationcontainer.entry-DV4D6oOH.js → nv-notificationcontainer.entry-DTRNn7VE.js} +4 -4
  50. package/dist/cjs/{nv-popover.entry-DQSwI2jT.js → nv-popover.entry-B0c-2rO4.js} +51 -47
  51. package/dist/cjs/{nv-row.entry-UUuMSAY5.js → nv-row.entry-CdcjVGZv.js} +4 -4
  52. package/dist/cjs/nv-sidebar.entry-CiN813gQ.js +177 -0
  53. package/dist/cjs/nv-sidebarcontent.entry-D9hpAhK8.js +22 -0
  54. package/dist/cjs/nv-sidebardivider.entry-B4EMyca5.js +22 -0
  55. package/dist/cjs/nv-sidebarfooter.entry-CHi4qOFe.js +22 -0
  56. package/dist/cjs/nv-sidebargroup.entry-RVqrsyIU.js +23 -0
  57. package/dist/cjs/nv-sidebarheader.entry-_7ch0O3G.js +22 -0
  58. package/dist/cjs/nv-sidebarlogo.entry-Ch9F-JnT.js +32 -0
  59. package/dist/cjs/nv-sidebarnavitem.entry-DVrafSMr.js +296 -0
  60. package/dist/cjs/nv-sidebarnavsubitem.entry-C0XDAzma.js +35 -0
  61. package/dist/cjs/{nv-split.entry-CYP2bTTM.js → nv-split.entry-0HTslRAX.js} +47 -45
  62. package/dist/cjs/{nv-stack.entry-D35-75Vw.js → nv-stack.entry-CqO7uTQf.js} +5 -5
  63. package/dist/cjs/{nv-table.entry-DevWJBnL.js → nv-table.entry-DH85n8Mc.js} +9 -11
  64. package/dist/cjs/{nv-tableheader.entry-Hs7nUSOC.js → nv-tableheader.entry-CKfocdxD.js} +7 -7
  65. package/dist/cjs/{nv-toggle.entry-Eje9d--6.js → nv-toggle.entry-BHUl76Im.js} +9 -9
  66. package/dist/cjs/nv-togglebutton.entry-D_9COjY-.js +67 -0
  67. package/dist/cjs/{nv-togglebuttongroup.entry-CWN_Ucry.js → nv-togglebuttongroup.entry-C0NLbsq7.js} +10 -8
  68. package/dist/cjs/{nv-tooltip.entry-BGkKDEFg.js → nv-tooltip.entry-BfViGE_U.js} +5 -5
  69. package/dist/cjs/slide.animation-CmH5d1of-BZuw607U.js +90 -0
  70. package/dist/cjs/{style-value-types.es-f5d10b79-D0QCM8OB.js → style-value-types.es-xlgmw4x8-B1vLqX9m.js} +6 -3
  71. package/dist/cjs/{v4-a79185f4-2n0dOd_Y.js → v4-BdYh22OP-C1vaJ4yP.js} +1 -1
  72. package/dist/components/NvDatatable/NvDatatable.js +40 -24
  73. package/dist/generated/components.js +107 -0
  74. package/dist/generated/components.server.js +260 -50
  75. package/dist/providers/NotificationProvider.js +3 -4
  76. package/dist/types/components/NvDatatable/NvDatatable.d.ts +1 -1
  77. package/dist/types/components/NvDatatable/types.d.ts +8 -3
  78. package/dist/types/generated/components.d.ts +46 -0
  79. package/dist/types/generated/components.server.d.ts +46 -0
  80. package/package.json +2 -2
  81. package/dist/cjs/_commonjsHelpers-1789f0cf-BJu3ubxk.js +0 -10
  82. package/dist/cjs/inputmask-edcad3c1-B9Omti4z.js +0 -3749
  83. package/dist/cjs/nv-fieldcheckbox.entry-fdonR07Z.js +0 -138
  84. package/dist/cjs/nv-fielddropdown.entry-C9mXuNNj.js +0 -392
  85. package/dist/cjs/nv-fieldnumber.entry-DBdJviXu.js +0 -148
  86. package/dist/cjs/nv-fieldpassword.entry-Cim_usSM.js +0 -122
  87. package/dist/cjs/nv-fieldtext.entry-DlI_ExaV.js +0 -124
  88. package/dist/cjs/nv-togglebutton.entry-LGI7pIeK.js +0 -56
  89. /package/dist/cjs/{clsx-297c1ffe-BtxeOLZW.js → clsx-ChV9xqsO-BtxeOLZW.js} +0 -0
  90. /package/dist/cjs/{constants-69bafca2-DpB_ghPF.js → constants-BReL3Lsa-DpB_ghPF.js} +0 -0
  91. /package/dist/cjs/{timeline.animation-79215cd4-KteJaZPb.js → timeline.animation-CgHCo_Ho-KteJaZPb.js} +0 -0
@@ -0,0 +1,678 @@
1
+ 'use strict';
2
+
3
+ var index = require('./index-kU2nW5aN.js');
4
+ var i18n_utilsIlwlcG9l = require('./i18n.utils-IlwlcG9l-ku0bScip.js');
5
+ var v4BdYh22OP = require('./v4-BdYh22OP-C1vaJ4yP.js');
6
+ require('@stencil/react-output-target/runtime');
7
+ require('react');
8
+ require('react-dom');
9
+
10
+ const nvFielddropdownCss = "nv-fieldslider .slider-container .track-container:has(.thumb:hover) .track-range{background:var(--components-slider-track-filled-hover)}nv-fieldslider .slider-container .track-container:has(.thumb:hover) .thumb{border-color:var(--components-slider-track-filled-hover)}nv-fieldslider .slider-container .track-container:has(.thumb:focus) .track-range{background:var(--components-slider-track-filled-focus)}nv-fieldslider .slider-container .track-container:has(.thumb:focus) .thumb{border-color:var(--components-slider-track-filled-focus)}nv-fieldslider[error] .slider-container .track-container .track .track-range{background:var(--components-slider-track-filled-error)}nv-fieldslider[error] .slider-container .track-container .track .thumb{border-color:var(--components-slider-track-filled-error)}nv-fieldslider[error] .slider-container .track-container .track .thumb:hover{border-color:var(--components-slider-track-filled-error);outline:calc(var(--focus-outline-stroke) * 1) solid var(--components-slider-track-filled-error);outline-offset:calc(var(--focus-outline-offset) * 1);background-color:var(--components-slider-handler-background-error)}nv-fieldslider[error] .slider-container .track-container .track .thumb:focus{border-color:var(--components-slider-track-filled-error);outline:calc(var(--focus-outline-stroke) * 1) solid var(--components-slider-track-filled-error);outline-offset:calc(var(--focus-outline-offset) * 1);background-color:var(--components-slider-track-filled-error)}nv-fieldslider[error] .slider-container .track-container:has(.thumb:hover) .track-range{background:var(--components-slider-track-filled-error)}nv-fieldslider[error] .slider-container .track-container:has(.thumb:hover) .thumb{border-color:var(--components-slider-track-filled-error)}nv-fielddropdown{--nv-field-border-default:var(--components-form-field-border-default);--nv-field-border-hover:var(--components-form-field-border-hover);--nv-field-border-focus:var(--components-form-field-border-focus);--nv-field-border-disabled:var(--components-form-field-border-default);--nv-field-border-readonly:var(--components-form-field-border-default);--nv-field-focus-box-shadow:var(--color-focus-brand);--nv-field-background:var(--components-form-field-background-default);display:flex;flex-direction:column;align-items:flex-start;gap:var(--form-gap-y);box-sizing:border-box;max-width:480px}nv-fielddropdown[fluid]:not([fluid=false]){max-width:unset}nv-fielddropdown[readonly]:not([readonly=false]){--nv-field-border-default:var(--components-form-field-border-readonly);--nv-field-border-hover:var(--nv-field-border-default);--nv-field-border-focus:var(--components-form-field-border-focus);--nv-field-border-disabled:var(--nv-field-border-default);--nv-field-border-readonly:var(--nv-field-border-default);--nv-field-background:var(--components-form-field-background-readonly)}nv-fielddropdown[error]:not([error=false]){--nv-field-border-default:var(--components-form-field-border-error);--nv-field-border-hover:var(--nv-field-border-default);--nv-field-border-focus:var(--nv-field-border-default);--nv-field-border-disabled:var(--nv-field-border-default);--nv-field-border-readonly:var(--nv-field-border-default);--nv-field-focus-box-shadow:var(--color-focus-destructive-in-field)}nv-fielddropdown[required]:not([required=false]) label::after,nv-fielddropdown[aria-required=true] label::after{content:\"*\";color:var(--components-form-text-required);font-weight:var(--font-weight-high-emphasis)}nv-fielddropdown[hidden]:not([hidden=false]) label{display:none}nv-fielddropdown label{display:flex;align-items:center;gap:var(--form-label-gap);align-self:stretch;color:var(--components-form-text-label-default);font-family:var(--font-family-default), var(--font-family-fallback), sans-serif;font-size:var(--form-label-font-size);font-style:normal;font-weight:var(--font-weight-medium-emphasis);line-height:var(--form-label-line-height)}nv-fielddropdown nv-popover{width:100%;display:block}nv-fielddropdown nv-popover [data-scope=popover]{min-width:100%;width:max-content;max-width:400px;padding:var(--list-dropdown-padding);border-radius:var(--list-dropdown-radius);background-color:var(--components-list-dropdown-background);border:1px solid var(--components-list-dropdown-border)}nv-fielddropdown nv-popover [slot=content]{gap:var(--list-dropdown-gap-y);display:flex;flex-direction:column}nv-fielddropdown nv-popover hr{color:var(--components-list-dropdown-separator)}nv-fielddropdown nv-popover div[slot=content]::-webkit-scrollbar{width:6px;height:6px}nv-fielddropdown nv-popover div[slot=content]::-webkit-scrollbar-track{background-color:var(--color-level-10-background);border-radius:9999px}nv-fielddropdown nv-popover div[slot=content]::-webkit-scrollbar-thumb{background-color:var(--color-gray-200);border-radius:9999px}nv-fielddropdown nv-popover div[slot=content]{max-height:calc(90vh - var(--list-dropdown-padding) * 2);overflow-y:auto;position:relative}nv-fielddropdown .input-wrapper{display:flex;flex-wrap:wrap;gap:var(--form-gap-x);align-items:stretch;align-self:stretch;width:100%}nv-fielddropdown .input-container{display:flex;flex-grow:1;justify-content:center;align-items:center;align-self:stretch;border-radius:var(--form-field-radius);border-width:1px;border-style:solid;border-color:var(--nv-field-border-default);opacity:var(--components-form-opacity-default, 1);background:var(--nv-field-background);transition:all 150ms ease-out}nv-fielddropdown .input-container:hover{border-color:var(--nv-field-border-hover)}nv-fielddropdown .input-container:focus-within,nv-fielddropdown .input-container:focus-within:hover,nv-fielddropdown .input-container:focus,nv-fielddropdown .input-container:focus:hover{border-color:var(--nv-field-border-focus);box-shadow:0px 0px 0px var(--focus-field-stroke) var(--nv-field-focus-box-shadow)}nv-fielddropdown .input-container:has(input:read-only){background-color:var(--components-form-field-background-readonly);border-color:var(--nv-field-border-readonly)}nv-fielddropdown .input-container:has(input:disabled){opacity:0.5;background-color:var(--components-form-field-background-disabled);border-color:var(--nv-field-border-disabled)}nv-fielddropdown .input-container{position:relative;width:100%;min-height:40px}nv-fielddropdown .input-container input[type=search]::-webkit-search-decoration,nv-fielddropdown .input-container input[type=search]::-webkit-search-cancel-button,nv-fielddropdown .input-container input[type=search]::-webkit-search-results-button,nv-fielddropdown .input-container input[type=search]::-webkit-search-results-decoration{-webkit-appearance:none}nv-fielddropdown .input-container input,nv-fielddropdown .input-container p.non-filterable-text{display:flex;align-items:center;flex:1 0 0;overflow:hidden;background-color:transparent;color:var(--components-form-field-content-text);padding:calc(var(--form-field-padding-y) - 1px) var(--form-field-padding-x);font-size:var(--form-field-font-size);font-style:normal;font-weight:var(--font-weight-medium-emphasis);line-height:var(--form-field-line-height);width:100%}nv-fielddropdown .input-container input:focus,nv-fielddropdown .input-container p.non-filterable-text:focus{outline:none}nv-fielddropdown .input-container input::placeholder,nv-fielddropdown .input-container p.non-filterable-text::placeholder{overflow:hidden;color:var(--components-form-field-content-placeholder);text-overflow:ellipsis;font-family:var(--font-family-default), var(--font-family-fallback), sans-serif;font-size:var(--form-field-font-size);font-style:normal;font-weight:var(--font-weight-low-emphasis);line-height:var(--form-field-line-height)}nv-fielddropdown .input-container input,nv-fielddropdown .input-container p.non-filterable-text{}nv-fielddropdown .input-container input[type=password]::-ms-clear,nv-fielddropdown .input-container input[type=password]::-ms-reveal,nv-fielddropdown .input-container p.non-filterable-text[type=password]::-ms-clear,nv-fielddropdown .input-container p.non-filterable-text[type=password]::-ms-reveal{display:none;width:0;height:0}nv-fielddropdown .input-container p.non-filterable-text{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;border-radius:var(--form-field-radius);background-color:var(--nv-field-background);color:var(--components-form-field-content-text);font-size:var(--form-field-font-size);font-weight:var(--font-weight-medium-emphasis);line-height:var(--form-field-line-height);box-sizing:border-box;cursor:pointer;height:100%;min-height:40px}nv-fielddropdown .input-container p.non-filterable-text span{display:inline-block;width:100%;overflow:hidden;text-overflow:ellipsis}nv-fielddropdown .input-container>nv-iconbutton{border:0px;border-radius:0px}nv-fielddropdown .input-container>nv-iconbutton:focus-visible{border-radius:var(--button-md-border-radius);outline-offset:-3px}nv-fielddropdown .input-container>nv-iconbutton:last-of-type{border-top-right-radius:var(--form-field-radius);border-bottom-right-radius:var(--form-field-radius)}nv-fielddropdown .input-container nv-icon.validation{color:var(--nv-field-border-default)}nv-fielddropdown .description{display:flex;align-items:center;align-self:stretch;gap:var(--spacing-1);color:var(--components-form-text-description-default);font-family:var(--font-family-default), var(--font-family-fallback), sans-serif;font-size:var(--form-description-font-size);font-style:normal;line-height:var(--form-description-line-height)}nv-fielddropdown .error-description{display:flex;align-items:center;align-self:stretch;gap:var(--spacing-1);color:var(--components-form-text-description-default);font-family:var(--font-family-default), var(--font-family-fallback), sans-serif;font-size:var(--form-description-font-size);font-style:normal;line-height:var(--form-description-line-height);color:var(--components-form-text-description-error)}";
11
+
12
+ const NvFielddropdown = class {
13
+ constructor(hostRef) {
14
+ index.registerInstance(this, hostRef);
15
+ this.valueChanged = index.createEvent(this, "valueChanged", 3);
16
+ this.filterTextChanged = index.createEvent(this, "filterTextChanged", 3);
17
+ this.openChanged = index.createEvent(this, "openChanged", 3);
18
+ this.dropdownItemSelected = index.createEvent(this, "dropdownItemSelected", 3);
19
+ /** Pre-computed search index for efficient filtering */
20
+ this.indexedItems = [];
21
+ /** Raw items for worker initialization */
22
+ this.rawItems = [];
23
+ /** Web Worker client for async search operations */
24
+ this.workerClient = null;
25
+ /** Effective filter mode (may differ from prop if fuzzy falls back to smart) */
26
+ this.effectiveFilterMode = 'strict';
27
+ /****************************************************************************/
28
+ //#region PROPERTIES
29
+ /**
30
+ * Sets the ID for the input element and the for attribute of the associated
31
+ * label. If no ID is provided, a random one will be automatically generated
32
+ * to ensure unique identification, facilitating proper label association and
33
+ * accessibility.
34
+ */
35
+ this.inputId = v4BdYh22OP.v4();
36
+ /**
37
+ * The autocomplete prop helps users fill out the input field faster by
38
+ * suggesting entries they've used before, like their email or address.
39
+ * You can turn it on to make forms more convenient or off to ensure users
40
+ * always type in fresh data.
41
+ */
42
+ this.autocomplete = 'off';
43
+ /**
44
+ * Marks the input field as required, ensuring that the user must fill it out
45
+ * before submitting the form.
46
+ * @note This uses the native HTML `required` attribute, which triggers browser validation.
47
+ */
48
+ this.required = false;
49
+ /**
50
+ * Marks the input field as required for accessibility purposes without triggering
51
+ * native HTML validation. Use this when implementing custom validation logic.
52
+ * @note When set, this uses `aria-required` instead of the native `required` attribute.
53
+ * This allows developers to implement custom validation while maintaining accessibility.
54
+ * @note If this prop is not explicitly set, the component will check for the HTML attribute
55
+ * 'aria-required' directly to determine if it should be applied.
56
+ */
57
+ this.ariaRequiredAttr = false;
58
+ /**
59
+ * Display the input field's content without allowing users to change it.
60
+ * Users can still click on it, select, and copy the text, but they won't be
61
+ * able to type or delete anything.
62
+ */
63
+ this.readonly = false;
64
+ /**
65
+ * The disabled prop lets you turn off the input field so that users can't
66
+ * type in it. When disabled, the field is grayed out and won't respond to
67
+ * clicks or touches.
68
+ */
69
+ this.disabled = false;
70
+ /**
71
+ * Alters the input field's appearance to indicate an error, helping users
72
+ * identify fields that need correction.
73
+ * @validator error
74
+ */
75
+ this.error = false;
76
+ /**
77
+ * Defines the maximum height of the multiselect list when open.
78
+ */
79
+ this.maxHeight = '';
80
+ /**
81
+ * The text to display when no items match the filter.
82
+ */
83
+ this.emptyResult = 'No results found';
84
+ /**
85
+ * Enables or disables the filtering feature for the dropdown items.
86
+ */
87
+ this.filterable = false;
88
+ /**
89
+ * When an item is selected by the user, the dropdown will continue to stay
90
+ * open.
91
+ */
92
+ this.openOnSelect = false;
93
+ /**
94
+ * Determines if the component’s filtering behavior is managed externally.
95
+ * When set to true and filterable is enabled, the component won’t
96
+ * automatically filter items. Instead, you must implement your own filtering
97
+ * logic (e.g., server-side search or custom matching) using the
98
+ * filterTextChanged event.
99
+ */
100
+ this.controlledFilter = false;
101
+ /**
102
+ * Delay in milliseconds before the search is triggered when typing in the
103
+ * filter input.
104
+ * @default 300
105
+ */
106
+ this.debounceDelay = 300;
107
+ /**
108
+ * Applies focus to the input field as soon as the component is mounted. This
109
+ * is equivalent to setting the native autofocus attribute on an <input>
110
+ * element.
111
+ */
112
+ this.autofocus = false;
113
+ /**
114
+ * Allows the field to stretch and fill the entire width of its container.
115
+ */
116
+ this.fluid = false;
117
+ /**
118
+ * Filter mode for dropdown search:
119
+ * - 'strict': Simple substring matching (normalized includes)
120
+ * - 'smart': Token-based matching (all query tokens must exist, order ignored)
121
+ * - 'fuzzy': Typo-tolerant matching using Fuse.js (runs in Web Worker)
122
+ * @default 'strict'
123
+ */
124
+ this.filterMode = 'strict';
125
+ /**
126
+ * Maximum number of results to display. Protects UI performance on large datasets.
127
+ * Values are clamped between 10 and 500 (hard cap).
128
+ * @default 25
129
+ */
130
+ this.maxResults = 25;
131
+ /**
132
+ * Minimum number of characters required before filtering starts.
133
+ * Useful for preventing overwhelming results on very large datasets.
134
+ * @default 0
135
+ */
136
+ this.startFilterAt = 0;
137
+ /**
138
+ * Number of items above which filtering is offloaded to a Web Worker.
139
+ * This keeps the main thread responsive for large datasets.
140
+ * @default 2000
141
+ */
142
+ this.workerThreshold = 2000;
143
+ /**
144
+ * Threshold for fuzzy matching (0-1). Lower values are stricter.
145
+ * Only applies when filterMode is 'fuzzy'.
146
+ * @default 0.3
147
+ * @see {@link https://fusejs.io/api/options.html#threshold} Fuse.js threshold documentation
148
+ */
149
+ this.fuzzyThreshold = 0.3;
150
+ //#endregion PROPERTIES
151
+ /****************************************************************************/
152
+ //#region STATE
153
+ /**
154
+ * The text entered by the user for filtering dropdown items.
155
+ */
156
+ this.filterText = '';
157
+ this.selectedValues = new Set();
158
+ this.open = false;
159
+ /**
160
+ * Whether search results were truncated due to maxResults limit.
161
+ */
162
+ this.resultsTruncated = false;
163
+ /**
164
+ * Total number of matches before truncation.
165
+ */
166
+ this.totalResults = 0;
167
+ /**
168
+ * Whether a worker search is in progress (shows loading indicator).
169
+ */
170
+ this.isSearching = false;
171
+ /**
172
+ * Closes the popover when a click is detected outside the component.
173
+ * @param {MouseEvent} event - The click event.
174
+ */
175
+ this.handleClickOutside = (event) => {
176
+ if (!(event.target instanceof Node))
177
+ return;
178
+ if (!this.el?.contains(event.target))
179
+ this.open = false;
180
+ };
181
+ this.handleFilterInput = () => {
182
+ this.open = true;
183
+ this.filterText = this.inputElement.value;
184
+ this.filterTextChanged.emit(this.inputElement.value);
185
+ clearTimeout(this.debounceTimer);
186
+ // Use longer debounce for fuzzy mode (Fuse.js needs more time)
187
+ // For fuzzy mode, use FUZZY_DEBOUNCE_DELAY (300ms), otherwise use this.debounceDelay
188
+ const debounce = this.effectiveFilterMode === 'fuzzy'
189
+ ? i18n_utilsIlwlcG9l.FUZZY_DEBOUNCE_DELAY
190
+ : this.debounceDelay;
191
+ this.debounceTimer = window.setTimeout(() => {
192
+ this.filterItems();
193
+ }, debounce);
194
+ };
195
+ this.getSelectedLabel = () => {
196
+ if (!this.value)
197
+ return '';
198
+ if (this.filterText?.length)
199
+ return this.filterText;
200
+ if (this.options?.length > 1) {
201
+ const matchingItem = this.options.find(option => option.value === this.value);
202
+ return matchingItem?.label ?? matchingItem?.value ?? this.value;
203
+ }
204
+ const items = Array.from(this.el.querySelectorAll('nv-fielddropdownitem'));
205
+ const matchingItem = items.find(item => item.value === this.value);
206
+ const selectedLabel = matchingItem
207
+ ? matchingItem.label ??
208
+ matchingItem.textContent?.trim() ??
209
+ matchingItem.value
210
+ : '';
211
+ return selectedLabel;
212
+ };
213
+ }
214
+ /* eslint-enable nova/event-bubbling */
215
+ //#endregion EVENTS
216
+ /****************************************************************************/
217
+ //#region WATCHERS
218
+ handleOpenChange(newOpen) {
219
+ if (newOpen === false) {
220
+ clearTimeout(this.debounceTimer);
221
+ setTimeout(() => {
222
+ this.clearFilter();
223
+ }, 100);
224
+ }
225
+ }
226
+ handleValueChange() {
227
+ this.updateSelectedItem();
228
+ if (!this.open || !this.filterText)
229
+ this.setFilterInputToSelectedValue();
230
+ }
231
+ handleOptionsChange() {
232
+ this.updateSelectedItem();
233
+ this.rebuildSearchIndex();
234
+ }
235
+ //#endregion WATCHERS
236
+ /****************************************************************************/
237
+ //#region LISTENERS
238
+ /* eslint-disable nova/native-event-listener */
239
+ handleDropdownItemSelected(event) {
240
+ event.stopPropagation();
241
+ if (this.disabled || this.readonly)
242
+ return;
243
+ if (!this.openOnSelect)
244
+ this.open = false;
245
+ if (event.detail.detached)
246
+ return;
247
+ const items = this.getAllItems();
248
+ items.forEach(item => {
249
+ if (item !== event.target) {
250
+ item.removeAttribute('selected');
251
+ }
252
+ else {
253
+ item.setAttribute('selected', 'true');
254
+ }
255
+ });
256
+ this.value = event.detail.value;
257
+ this.setFilterInputToSelectedValue();
258
+ this.valueChanged.emit(event.detail.value);
259
+ }
260
+ /* eslint-enable nova/native-event-listener */
261
+ handleFocus(event) {
262
+ if (event.relatedTarget instanceof HTMLElement &&
263
+ event.relatedTarget.tagName.includes('NV-FIELDDROPDOWNITEM')) {
264
+ return;
265
+ }
266
+ if (event.target != this.toggleElement)
267
+ this.open = true;
268
+ }
269
+ handleFocusOut(event) {
270
+ if (!(event.relatedTarget instanceof Node))
271
+ return;
272
+ if (this.el.contains(event.relatedTarget))
273
+ return;
274
+ this.open = false;
275
+ }
276
+ handleKeyDown(event) {
277
+ if (event.key === 'Escape') {
278
+ this.focusField();
279
+ this.open = false;
280
+ return;
281
+ }
282
+ if (event.key === ' ') {
283
+ if (event.target == this.selectElement) {
284
+ event.preventDefault(); // Prevent scrolling down
285
+ this.open = true;
286
+ }
287
+ return;
288
+ }
289
+ const items = this.getNavigableItems();
290
+ const highlightedItem = this.getHighlightedItemIndex(items);
291
+ if (event.key === 'ArrowDown') {
292
+ event.preventDefault(); // Prevent scrolling down
293
+ this.open = true;
294
+ const nextIndex = highlightedItem + 1;
295
+ this.updateHighlightedItem(items, nextIndex >= items.length ? 0 : nextIndex);
296
+ }
297
+ if (event.key === 'ArrowUp') {
298
+ event.preventDefault(); // Prevent scrolling up
299
+ this.open = true;
300
+ const nextIndex = highlightedItem - 1;
301
+ this.updateHighlightedItem(items, nextIndex < 0 ? items.length - 1 : nextIndex);
302
+ }
303
+ }
304
+ handleDocumentClick(event) {
305
+ this.handleClickOutside(event);
306
+ }
307
+ //#endregion LISTENERS
308
+ /****************************************************************************/
309
+ //#region METHODS
310
+ /** Clears the filter text */
311
+ async clearFilter() {
312
+ if (!this.filterable)
313
+ return;
314
+ if (this.filterText?.length) {
315
+ this.filterText = '';
316
+ this.filterTextChanged.emit(this.filterText);
317
+ }
318
+ this.filterItems();
319
+ // Wait for wrapper lifecycle to finish
320
+ setTimeout(() => {
321
+ this.setFilterInputToSelectedValue();
322
+ }, 0);
323
+ }
324
+ /**
325
+ * Toggles the dropdown popover open state
326
+ * @param {boolean} open - The open state to set, if null, toggles the state
327
+ */
328
+ async toggleDropdown(open) {
329
+ if (open !== undefined) {
330
+ setTimeout(() => {
331
+ this.open = open;
332
+ }, 0);
333
+ }
334
+ else {
335
+ setTimeout(() => {
336
+ this.open = !this.open;
337
+ }, 0);
338
+ }
339
+ }
340
+ syncToggleDropdown() {
341
+ this.open = !this.open;
342
+ }
343
+ setFilterInputToSelectedValue() {
344
+ if (!this.filterable && !this.disabled && !this.readonly)
345
+ return;
346
+ if (!this.inputElement)
347
+ return;
348
+ if (!this.value)
349
+ return (this.inputElement.value = '');
350
+ this.inputElement.value = this.getSelectedLabel();
351
+ }
352
+ // Will exclude detached items and data-empty
353
+ getFilterableItems() {
354
+ return Array.from(this.el.querySelectorAll('nv-fielddropdownitem:not([data-empty]):not([detached])'));
355
+ }
356
+ getNavigableItems() {
357
+ return Array.from(this.el.querySelectorAll('nv-fielddropdownitem:not([disabled]):not([hidden])'));
358
+ }
359
+ getAllItems() {
360
+ return Array.from(this.el.querySelectorAll('nv-fielddropdownitem'));
361
+ }
362
+ getHighlightedItemIndex(items) {
363
+ return items.findIndex(item => item.classList.contains('highlighted'));
364
+ }
365
+ updateHighlightedItem(items, index) {
366
+ items.forEach((item, i) => {
367
+ item.classList.remove('highlighted');
368
+ if (i === index) {
369
+ item.classList.add('highlighted');
370
+ item.focus();
371
+ item.scrollIntoView({ block: 'nearest' });
372
+ }
373
+ });
374
+ }
375
+ focusField() {
376
+ const focusableItem = this.el.querySelector('[data-scope="focusable"]');
377
+ focusableItem?.focus();
378
+ }
379
+ /**
380
+ * Rebuilds the search index from current items (options prop or slot items).
381
+ */
382
+ async rebuildSearchIndex() {
383
+ const items = this.getFilterableItems();
384
+ // Build raw items array for indexing
385
+ this.rawItems = items.map((item, index) => ({
386
+ id: item.value || `item-${index}`,
387
+ label: item.label || item.textContent?.trim() || item.value || '',
388
+ }));
389
+ // Also include options prop items if present
390
+ if (this.options?.length) {
391
+ this.options.forEach((opt, index) => {
392
+ this.rawItems.push({
393
+ id: opt.value || `opt-${index}`,
394
+ label: opt.label || opt.value || '',
395
+ });
396
+ });
397
+ }
398
+ // Build local index for main-thread search
399
+ this.indexedItems = i18n_utilsIlwlcG9l.buildIndex(this.rawItems);
400
+ // Determine effective filter mode
401
+ this.effectiveFilterMode = i18n_utilsIlwlcG9l.getEffectiveFilterMode(this.filterMode);
402
+ // Initialize worker if needed
403
+ const itemCount = this.rawItems.length;
404
+ const threshold = i18n_utilsIlwlcG9l.clampWorkerThreshold(this.workerThreshold);
405
+ if (i18n_utilsIlwlcG9l.shouldUseWorker(itemCount, this.effectiveFilterMode, threshold)) {
406
+ await this.initWorker();
407
+ }
408
+ else {
409
+ // Clean up worker if no longer needed
410
+ this.terminateWorker();
411
+ }
412
+ }
413
+ /**
414
+ * Initializes the Web Worker for search operations.
415
+ * Falls back to main thread if worker is not available.
416
+ * Note: Fuzzy search now works on main thread with Fuse.js, so no mode change needed.
417
+ */
418
+ async initWorker() {
419
+ if (!i18n_utilsIlwlcG9l.isWorkerSupported()) {
420
+ // Workers not supported - will use main thread (fuzzy still works with Fuse.js)
421
+ return;
422
+ }
423
+ if (!this.workerClient) {
424
+ this.workerClient = new i18n_utilsIlwlcG9l.SearchWorkerClient();
425
+ // No fallback mode change needed - fuzzy works on main thread now
426
+ }
427
+ // Init will silently handle fallback if worker can't be created
428
+ await this.workerClient.init(this.rawItems);
429
+ }
430
+ /**
431
+ * Terminates the Web Worker and cleans up resources.
432
+ */
433
+ terminateWorker() {
434
+ if (this.workerClient) {
435
+ this.workerClient.terminate();
436
+ this.workerClient = null;
437
+ }
438
+ }
439
+ /**
440
+ * Filter dropdown items based on the text entered by the user.
441
+ * Uses the search engine for optimized filtering with configurable modes.
442
+ * If no items are found, display a message indicating no results.
443
+ */
444
+ async filterItems() {
445
+ if (this.controlledFilter)
446
+ return;
447
+ // Ensure index is built
448
+ if (!this.indexedItems.length) {
449
+ await this.rebuildSearchIndex();
450
+ }
451
+ const items = this.getFilterableItems();
452
+ // Remove any existing "no results found" or "truncated" items
453
+ this.el
454
+ .querySelectorAll('nv-fielddropdownitem[data-empty], nv-fielddropdownitem[data-truncated]')
455
+ .forEach(item => item.remove());
456
+ // Check if we should start filtering
457
+ if (this.filterText.length < this.startFilterAt) {
458
+ // Show all items up to maxResults
459
+ const effectiveMaxResults = i18n_utilsIlwlcG9l.clampMaxResults(this.maxResults);
460
+ let visibleCount = 0;
461
+ items.forEach(item => {
462
+ if (visibleCount < effectiveMaxResults) {
463
+ item.removeAttribute('hidden');
464
+ visibleCount++;
465
+ }
466
+ else {
467
+ item.setAttribute('hidden', '');
468
+ }
469
+ });
470
+ this.resultsTruncated = items.length > effectiveMaxResults;
471
+ this.totalResults = items.length;
472
+ if (this.resultsTruncated) {
473
+ this.addTruncatedMessage(effectiveMaxResults, items.length);
474
+ }
475
+ return;
476
+ }
477
+ // Determine if we should use worker
478
+ const itemCount = this.rawItems.length;
479
+ const threshold = i18n_utilsIlwlcG9l.clampWorkerThreshold(this.workerThreshold);
480
+ const useWorker = i18n_utilsIlwlcG9l.shouldUseWorker(itemCount, this.effectiveFilterMode, threshold);
481
+ let result;
482
+ if (useWorker && this.workerClient?.isReady) {
483
+ // Use worker for search
484
+ this.isSearching = true;
485
+ try {
486
+ result = await this.workerClient.search(this.filterText, this.effectiveFilterMode, this.maxResults, this.fuzzyThreshold);
487
+ }
488
+ catch (error) {
489
+ console.error('Worker search failed, falling back to main thread:', error);
490
+ // Fall back to main thread search (now supports fuzzy with Fuse.js)
491
+ result = i18n_utilsIlwlcG9l.search(this.indexedItems, {
492
+ query: this.filterText,
493
+ filterMode: this.effectiveFilterMode,
494
+ maxResults: this.maxResults,
495
+ startFilterAt: this.startFilterAt,
496
+ fuzzyThreshold: this.fuzzyThreshold,
497
+ });
498
+ }
499
+ finally {
500
+ this.isSearching = false;
501
+ }
502
+ }
503
+ else {
504
+ // Use main thread search (now supports fuzzy mode with Fuse.js)
505
+ result = i18n_utilsIlwlcG9l.search(this.indexedItems, {
506
+ query: this.filterText,
507
+ filterMode: this.effectiveFilterMode,
508
+ maxResults: this.maxResults,
509
+ startFilterAt: this.startFilterAt,
510
+ fuzzyThreshold: this.fuzzyThreshold,
511
+ });
512
+ }
513
+ this.resultsTruncated = result.truncated;
514
+ this.totalResults = result.total;
515
+ // Apply results to DOM
516
+ this.applySearchResults(result, items);
517
+ }
518
+ /**
519
+ * Applies search results to the DOM, showing/hiding items as needed.
520
+ * @param {SearchResult} result - The search result.
521
+ * @param {HTMLNvFielddropdownitemElement[]} items - The items to apply the search results to.
522
+ * @example
523
+ * const result: SearchResult = {
524
+ * ids: ['item-1', 'item-2'],
525
+ * total: 2,
526
+ * truncated: false,
527
+ * };
528
+ * const items = Array.from(
529
+ * this.el.querySelectorAll('nv-fielddropdownitem'),
530
+ * ) as HTMLNvFielddropdownitemElement[];
531
+ * this.applySearchResults(result, items);
532
+ * // Matching items are shown, non-matching items are hidden.
533
+ * // If no items match, a "no results" item is prepended to the list.
534
+ */
535
+ applySearchResults(result, items) {
536
+ // Create a Set of matching IDs for fast lookup
537
+ const matchingIds = new Set(result.ids);
538
+ let hasVisibleItems = false;
539
+ let visibleCount = 0;
540
+ const effectiveMaxResults = i18n_utilsIlwlcG9l.clampMaxResults(this.maxResults);
541
+ items.forEach(item => {
542
+ const itemId = item.value || '';
543
+ const itemLabel = item.label || item.textContent?.trim() || '';
544
+ // Check if this item matches (by ID or by re-running search on label)
545
+ const isMatch = matchingIds.has(itemId) ||
546
+ result.ids.some(id => {
547
+ const indexed = this.indexedItems.find(i => i.id === id);
548
+ return (indexed && (indexed.label === itemLabel || indexed.id === itemId));
549
+ });
550
+ if (isMatch && visibleCount < effectiveMaxResults) {
551
+ item.removeAttribute('hidden');
552
+ hasVisibleItems = true;
553
+ visibleCount++;
554
+ }
555
+ else {
556
+ item.setAttribute('hidden', '');
557
+ }
558
+ });
559
+ // If no items are visible, add the "no results found" item
560
+ if (!hasVisibleItems) {
561
+ const emptyItem = document.createElement('nv-fielddropdownitem');
562
+ emptyItem.setAttribute('data-empty', 'true');
563
+ emptyItem.setAttribute('disabled', 'true');
564
+ emptyItem.textContent = this.emptyResult;
565
+ this.el.querySelector('div[slot="content"] ul')?.prepend(emptyItem);
566
+ }
567
+ else if (result.truncated) {
568
+ // Add truncation message if results were limited
569
+ this.addTruncatedMessage(result.ids.length, result.total);
570
+ }
571
+ }
572
+ /**
573
+ * Adds a non-selectable item showing truncation info.
574
+ * @param {number} shown - The number of items shown.
575
+ * @param {number} total - The total number of items.
576
+ * @example
577
+ * // Show a truncation message like "10 of 100 results".
578
+ * this.addTruncatedMessage(10, 100);
579
+ */
580
+ addTruncatedMessage(shown, total) {
581
+ // Get the text template: use provided text or auto-detect from locale
582
+ const textTemplate = this.truncatedResultsText || i18n_utilsIlwlcG9l.getTruncatedResultsText(this.locale);
583
+ const truncatedItem = document.createElement('nv-fielddropdownitem');
584
+ truncatedItem.setAttribute('data-truncated', 'true');
585
+ truncatedItem.setAttribute('disabled', 'true');
586
+ truncatedItem.setAttribute('detached', 'true');
587
+ truncatedItem.className = 'truncated-message';
588
+ truncatedItem.textContent = i18n_utilsIlwlcG9l.formatTruncatedResults(textTemplate, shown, total);
589
+ const ul = this.el.querySelector('div[slot="content"] ul');
590
+ if (ul) {
591
+ ul.appendChild(truncatedItem);
592
+ }
593
+ }
594
+ async updateSelectedItem() {
595
+ const items = this.getAllItems();
596
+ if (this.value) {
597
+ items.forEach(item => {
598
+ if (item.value === this.value) {
599
+ item.selected = true;
600
+ }
601
+ else {
602
+ item.selected = false;
603
+ }
604
+ });
605
+ }
606
+ }
607
+ //#endregion METHODS
608
+ /****************************************************************************/
609
+ //#region LIFECYCLE
610
+ componentDidLoad() {
611
+ this.updateSelectedItem();
612
+ this.setFilterInputToSelectedValue();
613
+ // Build the search index on load
614
+ this.rebuildSearchIndex();
615
+ }
616
+ disconnectedCallback() {
617
+ clearTimeout(this.debounceTimer);
618
+ this.terminateWorker();
619
+ }
620
+ componentDidRender() {
621
+ // Make sure to show the value when the field is disabled or readonly
622
+ // as we switch to an input instead of a p in that case
623
+ if (!this.filterable && (this.disabled || this.readonly)) {
624
+ this.inputElement.value = this.getSelectedLabel();
625
+ }
626
+ }
627
+ //#endregion LIFECYCLE
628
+ /****************************************************************************/
629
+ //#region RENDER
630
+ render() {
631
+ // Check aria-required from multiple sources:
632
+ // 1. JavaScript prop (most reliable)
633
+ // 2. HTML attribute 'aria-required' (direct HTML)
634
+ // 3. HTML attribute 'aria-required-attr' (from JSX kebab-case conversion)
635
+ // Check aria-required from multiple sources:
636
+ // 1. HTML attribute 'aria-required' (direct HTML) - check if explicitly set
637
+ // 2. JavaScript prop (when prop is explicitly set via JavaScript)
638
+ // We use hasAttribute to determine if the attribute was explicitly set by the user,
639
+ // since the prop now defaults to false (to maintain Blazor compatibility)
640
+ const hasAriaRequiredAttr = this.el.hasAttribute('aria-required') ||
641
+ this.el.hasAttribute('aria-required-attr');
642
+ const ariaRequiredFromAttr = hasAriaRequiredAttr
643
+ ? this.el.getAttribute('aria-required') ||
644
+ this.el.getAttribute('aria-required-attr')
645
+ : null;
646
+ // Use aria-required if the attribute was explicitly set
647
+ // With reflect: true, setting the prop will also set the attribute
648
+ const useAriaRequired = hasAriaRequiredAttr;
649
+ // Determine the value: use attribute if it exists (prop reflects to attribute via reflect: true)
650
+ // If attribute doesn't exist, the prop was never set and we don't use aria-required
651
+ const ariaRequiredAttrValue = hasAriaRequiredAttr
652
+ ? ariaRequiredFromAttr
653
+ : null;
654
+ // Determine which attributes to use
655
+ // If aria-required HTML attribute is present, use it (convert string to boolean)
656
+ // If required is set and aria-required is not "false", use native required
657
+ // If aria-required is "false", don't use native required even if required is set
658
+ const ariaRequiredValue = useAriaRequired
659
+ ? ariaRequiredAttrValue === 'true' || ariaRequiredAttrValue === ''
660
+ : undefined;
661
+ const useNativeRequired = this.required && (!useAriaRequired || ariaRequiredValue === true);
662
+ return (index.h(index.Host, { key: 'a6f4a91185ad666409fb4fa9e2cc2580506c13f6', role: "combobox", "aria-expanded": this.open.toString(), "aria-haspopup": "listbox", "aria-label": this.label }, (this.label || this.el.querySelector('[slot="label"]')) && (index.h("label", { key: '7ca71ff79f234ceb1dc8d41dc4a53634e2cea7af', htmlFor: this.inputId, onClick: this.syncToggleDropdown.bind(this) }, index.h("slot", { key: 'b5eb4bfdf25c113c5dd817eb51f7fb13279254d6', name: "label" }, this.label))), index.h("nv-popover", { key: '3eb2ee8885869d39ff5a7c698a973ee9489c7849', triggerMode: "controlled", placement: "bottom-start", open: this.open, onOpenChanged: e => this.openChanged.emit(e.detail) }, index.h("div", { key: 'f8242972d005ccb2fb442c1d4e0ef7897ea3a85d', class: "input-wrapper", slot: "trigger" }, index.h("slot", { key: '125541e0c277e753aee5865ec2e8f95a1d9cbbcc', name: "before-input" }), index.h("div", { key: 'e3cd1a684cf1c0389073d8e2cd8d64bffe09ede4', class: "input-container" }, index.h("slot", { key: 'daab53125bfefc34d50386b076a86855a5cc42d4', name: "leading-input" }), this.filterable || this.disabled || this.readonly ? (index.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 && {
663
+ 'aria-required': String(ariaRequiredValue),
664
+ }), disabled: this.disabled, readOnly: this.readonly, onInput: this.handleFilterInput })) : (index.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.filterable && this.filterText && (index.h("nv-iconbutton", { key: '0f46ff14f2627929fea9728efa1009f27eab2596', name: "x", size: "md", emphasis: "lower", class: "clear-button", onClick: this.clearFilter.bind(this), "aria-label": "Clear input" })), this.error && (index.h("nv-icon", { key: '19a8983a7fa485aeda81029c4b082552866ca2b8', name: "alert-circle", class: "validation", size: "md" })), index.h("nv-iconbutton", { key: '6cc2ef2c986b71b1f542badccf2202c6737778a9', "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 })), index.h("slot", { key: '1e6b1fcb94ee4d658cd20518c11407bd84ac4100', name: "after-input" })), index.h("div", { key: '3f3cbed73c08ebfcdf51abd0879a43855bfb3023', slot: "content", style: this.maxHeight ? { maxHeight: this.maxHeight } : {} }, this.options?.length > 0 && (index.h("ul", { key: 'abeaeef3f99c3a63c5930e2ad79810613d29c0bf' }, this.options.map(option => (index.h("nv-fielddropdownitem", { label: option.label, value: option.value, disabled: option.disabled, selected: option.value === this.value }))))), index.h("slot", { key: 'e9f1cd86ca7ed091df2ea89e60a2dcd061bf974e', name: "content" }))), (this.description ||
665
+ this.el.querySelector('[slot="description"]')) && (index.h("div", { key: '8a5705537aedbaddc3e50b06baf4866aec45f4d5', class: "description" }, index.h("slot", { key: '405186007d26c05f5a6664e2824cac7691b244dc', name: "description" }, this.description))), (this.errorDescription ||
666
+ this.el.querySelector('[slot="error-description"]')) && (index.h("div", { key: '1b2e942461cb154226ec28b9c05e15df84b616d8', hidden: !this.error, class: "error-description" }, index.h("slot", { key: 'cbb0c466fd8ecd6b470cdc4107a874a148565cd2', name: "error-description" }, this.errorDescription)))));
667
+ }
668
+ static get formAssociated() { return true; }
669
+ get el() { return index.getElement(this); }
670
+ static get watchers() { return {
671
+ "open": ["handleOpenChange"],
672
+ "value": ["handleValueChange"],
673
+ "options": ["handleOptionsChange"]
674
+ }; }
675
+ };
676
+ NvFielddropdown.style = nvFielddropdownCss;
677
+
678
+ exports.nv_fielddropdown = NvFielddropdown;